Sync with 5.4.1
[deliverable/titan.core.git] / compiler2 / ttcn3 / AST_ttcn3.cc
CommitLineData
970ed795 1///////////////////////////////////////////////////////////////////////////////
3abe9331 2// Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
3// All rights reserved. This program and the accompanying materials
4// are made available under the terms of the Eclipse Public License v1.0
5// which accompanies this distribution, and is available at
6// http://www.eclipse.org/legal/epl-v10.html
7///////////////////////////////////////////////////////////////////////////////
8#include "../../common/dbgnew.hh"
9#include "AST_ttcn3.hh"
10#include "../Identifier.hh"
11#include "../CompilerError.hh"
12#include "../Setting.hh"
13#include "../Type.hh"
14#include "../CompField.hh"
15#include "../CompType.hh"
16#include "../TypeCompat.hh"
17#include "../Valuestuff.hh"
18#include "../Value.hh"
19#include "Ttcnstuff.hh"
20#include "TtcnTemplate.hh"
21#include "Templatestuff.hh"
22#include "ArrayDimensions.hh"
23#include "compiler.h"
24#include "../main.hh"
25#include "Statement.hh"
26#include "ILT.hh"
27#include "Attributes.hh"
28#include "PatternString.hh"
29#include "../../common/version_internal.h"
30#include "../CodeGenHelper.hh"
31#include "../../common/JSON_Tokenizer.hh"
32#include <limits.h>
33
34// implemented in coding_attrib_p.y
35extern Ttcn::ExtensionAttributes * parse_extattributes(
36 Ttcn::WithAttribPath *w_attrib_path);
37
38// implemented in compiler.y
39extern Ttcn::ErroneousAttributeSpec* ttcn3_parse_erroneous_attr_spec_string(
40 const char* p_str, const Common::Location& str_loc);
41
42
43extern void init_coding_attrib_lex(const Ttcn::AttributeSpec& attrib);
44extern int coding_attrib_parse();
45extern void cleanup_coding_attrib_lex();
46extern Ttcn::ExtensionAttributes *extatrs;
47
48/** Create a field name in the anytype
49 *
50 * The output of this function will be used to create an identifier
51 * to be used as the field name in the anytype.
52 * The type_name may be a built-in type (e.g. "integer") or a user-defined
53 * type.
54 *
55 * If the name has multiple components (a fullname?), it keeps just the last
56 * component without any dots. *
57 * Also, the space in "universal charstring" needs to be replaced
58 * with an underscore to make it an identifier.
59 *
60 * Note: Prefixing with "AT_" is not done here, but in defUnionClass().
61 *
62 * @param type_name string
63 * @return string to be used as the identifier.
64 */
65string anytype_field(const string& type_name)
66{
67 string retval(type_name);
68
69 // keep just the last part of the name
70 // TODO check if there's a way to get just the last component (note that fetching the string is done outside of this function)
71 size_t dot = retval.rfind('.');
72 if (dot >= retval.size()) dot = 0;
73 else ++dot;
74 retval.replace(0, dot, "");
75
76 return retval;
77}
78
79extern Common::Modules *modules; // in main.cc
80
81namespace {
82static const string _T_("_T_");
83}
84
85namespace Ttcn {
86
87 using namespace Common;
88
89 // =================================
90 // ===== FieldOrArrayRef
91 // =================================
92
93 FieldOrArrayRef::FieldOrArrayRef(const FieldOrArrayRef& p)
94 : Node(p), Location(p), ref_type(p.ref_type)
95 {
96 switch (p.ref_type) {
97 case FIELD_REF:
98 u.id = p.u.id->clone();
99 break;
100 case ARRAY_REF:
101 u.arp = p.u.arp->clone();
102 break;
103 default:
104 FATAL_ERROR("FieldOrArrayRef::FieldOrArrayRef()");
105 }
106 }
107
108 FieldOrArrayRef::FieldOrArrayRef(Identifier *p_id)
109 : Node(), Location(), ref_type(FIELD_REF)
110 {
111 if (!p_id) FATAL_ERROR("FieldOrArrayRef::FieldOrArrayRef()");
112 u.id = p_id;
113 }
114
115 FieldOrArrayRef::FieldOrArrayRef(Value *p_arp)
116 : Node(), Location(), ref_type(ARRAY_REF)
117 {
118 if (!p_arp) FATAL_ERROR("FieldOrArrayRef::FieldOrArrayRef()");
119 u.arp = p_arp;
120 }
121
122 FieldOrArrayRef::~FieldOrArrayRef()
123 {
124 switch (ref_type) {
125 case FIELD_REF:
126 delete u.id;
127 break;
128 case ARRAY_REF:
129 delete u.arp;
130 break;
131 default:
132 FATAL_ERROR("FieldOrArrayRef::~FieldOrArrayRef()");
133 }
134 }
135
136 FieldOrArrayRef *FieldOrArrayRef::clone() const
137 {
138 return new FieldOrArrayRef(*this);
139 }
140
141 void FieldOrArrayRef::set_fullname(const string& p_fullname)
142 {
143 Node::set_fullname(p_fullname);
144 if (ref_type == ARRAY_REF)
145 u.arp->set_fullname(p_fullname + ".<array_index>");
146 }
147
148 void FieldOrArrayRef::set_my_scope(Scope *p_scope)
149 {
150 if (ref_type == ARRAY_REF) u.arp->set_my_scope(p_scope);
151 }
152
153 const Identifier* FieldOrArrayRef::get_id() const
154 {
155 if (ref_type != FIELD_REF) FATAL_ERROR("FieldOrArrayRef::get_id()");
156 return u.id;
157 }
158
159 Value *FieldOrArrayRef::get_val() const
160 {
161 if (ref_type != ARRAY_REF) FATAL_ERROR("FieldOrArrayRef::get_val()");
162 return u.arp;
163 }
164
165 void FieldOrArrayRef::append_stringRepr(string& str) const
166 {
167 switch (ref_type) {
168 case FIELD_REF:
169 str += '.';
170 str += u.id->get_dispname();
171 break;
172 case ARRAY_REF:
173 str += '[';
174 str += u.arp->get_stringRepr();
175 str += ']';
176 break;
177 default:
178 str += "<unknown sub-reference>";
179 }
180 }
3abe9331 181
182 void FieldOrArrayRef::set_field_name_to_lowercase()
183 {
184 if (ref_type != FIELD_REF) FATAL_ERROR("FieldOrArrayRef::set_field_name_to_lowercase()");
185 string new_name = u.id->get_name();
186 if (isupper(new_name[0])) {
187 new_name[0] = tolower(new_name[0]);
188 if (new_name[new_name.size() - 1] == '_') {
189 // an underscore is inserted at the end of the field name if it's
190 // a basic type's name (since it would conflict with the class generated
191 // for that type)
192 // remove the underscore, it won't conflict with anything if its name
193 // starts with a lowercase letter
194 new_name.replace(new_name.size() - 1, 1, "");
195 }
196 delete u.id;
197 u.id = new Identifier(Identifier::ID_NAME, new_name);
198 }
199 }
970ed795
EL
200
201 // =================================
202 // ===== FieldOrArrayRefs
203 // =================================
204
205 FieldOrArrayRefs::FieldOrArrayRefs(const FieldOrArrayRefs& p)
206 : Node(p), refs_str_element(false)
207 {
208 for (size_t i = 0; i < p.refs.size(); i++) refs.add(p.refs[i]->clone());
209 }
210
211 FieldOrArrayRefs::~FieldOrArrayRefs()
212 {
213 for (size_t i = 0; i < refs.size(); i++) delete refs[i];
214 refs.clear();
215 }
216
217 FieldOrArrayRefs *FieldOrArrayRefs::clone() const
218 {
219 return new FieldOrArrayRefs(*this);
220 }
221
222 void FieldOrArrayRefs::set_fullname(const string& p_fullname)
223 {
224 Node::set_fullname(p_fullname);
225 for (size_t i = 0; i < refs.size(); i++)
226 refs[i]->set_fullname(p_fullname +
a38c6d4c 227 ".<sub_reference" + Int2string(i + 1) + ">");
970ed795
EL
228 }
229
230 void FieldOrArrayRefs::set_my_scope(Scope *p_scope)
231 {
232 for (size_t i = 0; i < refs.size(); i++) refs[i]->set_my_scope(p_scope);
233 }
234
235 bool FieldOrArrayRefs::has_unfoldable_index() const
236 {
237 for (size_t i = 0; i < refs.size(); i++) {
238 FieldOrArrayRef *ref = refs[i];
239 if (ref->get_type() == FieldOrArrayRef::ARRAY_REF) {
a38c6d4c 240 Value *v = ref->get_val();
241 v->set_lowerid_to_ref();
242 if (v->is_unfoldable()) return true;
970ed795
EL
243 }
244 }
245 return false;
246 }
247
248 void FieldOrArrayRefs::remove_refs(size_t n)
249 {
250 for (size_t i = 0; i < n; i++) delete refs[i];
251 refs.replace(0, n, NULL);
252 set_fullname(get_fullname());
253 }
254
255 /* remove_last_field is used when unfolding references for
256 ischosen and ispresent function operands.
257 In this case it is NOT sure the last field exists.
258 Calling remove_last_field previously
259 will avoid getting the "variable...Has no member called..." error message.
260 The last field component will be checked as a separate step.
261 Warning: the removed Identifier has to be deleted later */
262
263 Identifier* FieldOrArrayRefs::remove_last_field()
264 {
265 if (refs.size() == 0) return 0;
266 size_t last_elem_ind = refs.size() - 1;
267 FieldOrArrayRef* last_elem = refs[last_elem_ind];
268 if (last_elem->get_type() == FieldOrArrayRef::FIELD_REF) {
269 Identifier *ret_val = last_elem->get_id()->clone();
270 delete last_elem;
271 refs.replace(last_elem_ind, 1, NULL);
272 return ret_val;
273 } else return 0;
274 }
275
276 void FieldOrArrayRefs::generate_code(expression_struct *expr,
277 Common::Assignment *ass, size_t nof_subrefs /* = UINT_MAX*/)
278 {
279 Type *type = 0;
280 bool is_template = false;
281 switch (ass->get_asstype()) {
282 case Common::Assignment::A_CONST: // a Def_Const
283 case Common::Assignment::A_EXT_CONST: // a Def_ExtConst
284 case Common::Assignment::A_MODULEPAR: // a Def_Modulepar
285 case Common::Assignment::A_VAR: // a Def_Var
286 case Common::Assignment::A_FUNCTION_RVAL: // a Def_Function
287 case Common::Assignment::A_EXT_FUNCTION_RVAL: // a Def_ExtFunction
288 case Common::Assignment::A_PAR_VAL_IN: // a FormalPar
289 case Common::Assignment::A_PAR_VAL_OUT: // a FormalPar
290 case Common::Assignment::A_PAR_VAL_INOUT: // a FormalPar
291 // The type is important since the referred entities are value objects.
292 type = ass->get_Type();
293 break;
294 case Common::Assignment::A_MODULEPAR_TEMP: // a Def_Modulepar_Template
295 case Common::Assignment::A_TEMPLATE: // a Def_Template
296 case Common::Assignment::A_VAR_TEMPLATE: // a Def_Var_Template
297 case Common::Assignment::A_PAR_TEMPL_IN: // a FormalPar
298 case Common::Assignment::A_PAR_TEMPL_OUT: // a FormalPar
299 case Common::Assignment::A_PAR_TEMPL_INOUT: // a FormalPar
300 // The type is semi-important because fields of anytype templates
301 // need the prefix.
302 type = ass->get_Type();
303 is_template = true;
304 break;
305 case Common::Assignment::A_TIMER: // a Def_Timer
306 case Common::Assignment::A_PORT: // a Def_Port
307 case Common::Assignment::A_FUNCTION_RTEMP: // a Def_Function
308 case Common::Assignment::A_EXT_FUNCTION_RTEMP: // a Def_ExtFunction
309 case Common::Assignment::A_PAR_TIMER: // a FormalPar
310 case Common::Assignment::A_PAR_PORT: // a FormalPar
311 // The type is not relevant (i.e. the optional fields do not require
312 // special handling).
313 type = 0;
314 break;
315 default:
316 // Reference to other definitions cannot occur during code generation.
317 FATAL_ERROR("FieldOrArrayRefs::generate_code()");
318 type = 0;
319 }
320 size_t n_refs = (nof_subrefs != UINT_MAX) ? nof_subrefs : refs.size();
321 for (size_t i = 0; i < n_refs; i++) {
322 if (type) type = type->get_type_refd_last();
323 // type changes inside the loop; need to recompute "last" every time.
324 FieldOrArrayRef *ref = refs[i];
325 if (ref->get_type() == FieldOrArrayRef::FIELD_REF) {
326 // Write a call to the field accessor method.
327 // Fields of the anytype get a special prefix; see also:
328 // Template::generate_code_init_se, TypeConv::gen_conv_func_choice_anytype,
329 // defUnionClass and defUnionTemplate.
330 const Identifier& id = *ref->get_id();
331 expr->expr = mputprintf(expr->expr, ".%s%s()",
332 ((type!=0 && type->get_typetype()==Type::T_ANYTYPE) ? "AT_" : ""),
333 id.get_name().c_str());
a38c6d4c 334 if (type) {
335 CompField *cf = type->get_comp_byName(id);
336 // If the field is optional, the return type of the accessor is an
337 // OPTIONAL<T>. Write a call to OPTIONAL<T>::operator(),
338 // which "reaches into" the OPTIONAL to get the contained type T.
339 // Don't do this at the end of the reference chain.
340 // Accessor methods for a foo_template return a bar_template
341 // and OPTIONAL<> is not involved, hence no "()".
342 if (!is_template && i < n_refs - 1 && cf->get_is_optional())
343 expr->expr = mputstr(expr->expr, "()");
970ed795 344 // Follow the field type.
a38c6d4c 345 type = cf->get_type();
346 }
970ed795
EL
347 } else {
348 // Generate code for array reference.
349 expr->expr = mputc(expr->expr, '[');
a38c6d4c 350 ref->get_val()->generate_code_expr(expr);
970ed795 351 expr->expr = mputc(expr->expr, ']');
a38c6d4c 352 if (type) {
970ed795 353 // Follow the embedded type.
a38c6d4c 354 switch (type->get_typetype()) {
355 case Type::T_SEQOF:
356 case Type::T_SETOF:
357 case Type::T_ARRAY:
358 type = type->get_ofType();
359 break;
360 default:
361 // The index points to a string element.
362 // There are no further sub-references.
363 type = 0;
364 } // switch
365 } // if (type)
970ed795
EL
366 } // if (ref->get_type)
367 } // next reference
368 }
369
370 void FieldOrArrayRefs::append_stringRepr(string& str) const
371 {
372 for (size_t i = 0; i < refs.size(); i++) refs[i]->append_stringRepr(str);
373 }
374
375 // =================================
376 // ===== Ref_base
377 // =================================
378
379 Ref_base::Ref_base(const Ref_base& p)
380 : Ref_simple(p), subrefs(p.subrefs)
381 {
382 modid = p.modid ? p.modid->clone() : 0;
383 id = p.id ? p.id->clone() : 0;
384 params_checked = p.is_erroneous;
385 }
386
387 Ref_base::Ref_base(Identifier *p_modid, Identifier *p_id)
388 : Ref_simple(), modid(p_modid), id(p_id), params_checked(false)
389 , usedInIsbound(false)
390 {
391 if (!p_id)
392 FATAL_ERROR("NULL parameter: Ttcn::Ref_base::Ref_base()");
393 }
394
395 Ref_base::~Ref_base()
396 {
397 delete modid;
398 delete id;
399 }
400
401 void Ref_base::set_fullname(const string& p_fullname)
402 {
403 Ref_simple::set_fullname(p_fullname);
404 subrefs.set_fullname(p_fullname);
405 }
406
407 void Ref_base::set_my_scope(Scope *p_scope)
408 {
409 Ref_simple::set_my_scope(p_scope);
410 subrefs.set_my_scope(p_scope);
411 }
412
413 /* returns the referenced variable's base type or value */
414 Setting* Ref_base::get_refd_setting()
415 {
416 Common::Assignment *ass = get_refd_assignment();
417 if (ass) return ass->get_Setting();
418 else return 0;
419 }
420
421 FieldOrArrayRefs *Ref_base::get_subrefs()
422 {
423 if (!id) get_modid();
424 if (subrefs.get_nof_refs() == 0) return 0;
425 else return &subrefs;
426 }
427
428 bool Ref_base::has_single_expr()
429 {
430 Common::Assignment *ass = get_refd_assignment();
431 if (!ass) FATAL_ERROR("Ref_base::has_single_expr()");
432 for (size_t i = 0; i < subrefs.get_nof_refs(); i++) {
433 FieldOrArrayRef *ref = subrefs.get_ref(i);
434 if (ref->get_type() == FieldOrArrayRef::ARRAY_REF &&
435 !ref->get_val()->has_single_expr()) return false;
436 }
437 return true;
438 }
439
440 void Ref_base::set_code_section(
441 GovernedSimple::code_section_t p_code_section)
442 {
443 for (size_t i = 0; i < subrefs.get_nof_refs(); i++) {
444 FieldOrArrayRef *ref = subrefs.get_ref(i);
445 if (ref->get_type() == FieldOrArrayRef::ARRAY_REF)
446 ref->get_val()->set_code_section(p_code_section);
447 }
448 }
449
450 void Ref_base::generate_code_const_ref(expression_struct_t */*expr*/)
451 {
452 FATAL_ERROR("Ref_base::generate_code_const_ref()");
453 }
454
455 // =================================
456 // ===== Reference
457 // =================================
458
459 Reference::Reference(Identifier *p_id)
460 : Ref_base(), parlist(0)
461 {
462 subrefs.add(new FieldOrArrayRef(p_id));
463 }
464
465 Reference::~Reference()
466 {
467 if (parlist) {
468 delete parlist;
469 }
470 }
471
472 /* Called by:
a38c6d4c 473 * Common::PortTypeBody::PortTypeBody
474 * Common::Type::Type
475 * Common::TypeMappingTarget::TypeMappingTarget
476 * Common::PatternString::ps_elem_t::chk_ref */
970ed795
EL
477 Reference *Reference::clone() const
478 {
479 return new Reference(*this);
480 }
481
482 string Reference::get_dispname()
483 {
484 string ret_val;
485 if (id) {
486 if (modid) {
a38c6d4c 487 ret_val += modid->get_dispname();
488 ret_val += '.';
970ed795
EL
489 }
490 ret_val += id->get_dispname();
491 subrefs.append_stringRepr(ret_val);
492 } else {
493 subrefs.append_stringRepr(ret_val);
494 // cut the leading dot
495 if (!ret_val.empty() && ret_val[0] == '.')
496 ret_val.replace(0, 1, "");
497 }
498 return ret_val;
499 }
500
501 Common::Assignment* Reference::get_refd_assignment(bool check_parlist)
502 {
503 Common::Assignment *ass = Ref_base::get_refd_assignment(check_parlist);
504 // In fact calls Ref_simple::get_refd_assignment
505 if (ass && check_parlist && !params_checked) {
506 params_checked = true;
507 FormalParList *fplist = ass->get_FormalParList();
508 if (fplist) {
509 if (fplist->has_only_default_values()
510 && Common::Assignment::A_TEMPLATE == ass->get_asstype()) {
511 Ttcn::ParsedActualParameters params;
512 Error_Context cntxt(&params, "In actual parameter list of %s",
513 ass->get_description().c_str());
514 parlist = new ActualParList();
515 is_erroneous = fplist->fold_named_and_chk(&params, parlist);
516 parlist->set_fullname(get_fullname());
517 parlist->set_my_scope(my_scope);
518 } else {
519 error("Reference to parameterized definition `%s' without "
a38c6d4c 520 "actual parameter list", ass->get_id().get_dispname().c_str());
970ed795
EL
521 }
522 }
523 }
524 return ass;
525 }
526
527 const Identifier* Reference::get_modid()
528 {
529 if (!id) detect_modid();
530 return modid;
531 }
532
533 const Identifier* Reference::get_id()
534 {
535 if (!id) detect_modid();
536 return id;
537 }
538
539 Type *Reference::chk_variable_ref()
540 {
541 Common::Assignment *t_ass = get_refd_assignment();
542 if (!t_ass) return 0;
543 switch (t_ass->get_asstype()) {
544 case Common::Assignment::A_PAR_VAL_IN:
545 t_ass->use_as_lvalue(*this);
546 // no break
547 case Common::Assignment::A_VAR:
548 case Common::Assignment::A_PAR_VAL_OUT:
549 case Common::Assignment::A_PAR_VAL_INOUT:
550 break;
551 default:
552 error("Reference to a variable or value parameter was "
a38c6d4c 553 "expected instead of %s", t_ass->get_description().c_str());
970ed795
EL
554 return 0;
555 }
556 FieldOrArrayRefs *t_subrefs = get_subrefs();
557 Type *ret_val = t_ass->get_Type()->get_field_type(t_subrefs,
558 Type::EXPECTED_DYNAMIC_VALUE);
559 if (ret_val && t_subrefs && t_subrefs->refers_to_string_element()) {
560 error("Reference to a string element of type `%s' cannot be used in "
a38c6d4c 561 "this context", ret_val->get_typename().c_str());
970ed795
EL
562 }
563 return ret_val;
564 }
565
566 Type *Reference::chk_comptype_ref()
567 {
568 Common::Assignment *ass = get_refd_assignment();
569 if (ass) {
570 if (ass->get_asstype() == Common::Assignment::A_TYPE) {
571 Type *t = ass->get_Type()->get_type_refd_last();
a38c6d4c 572 switch (t->get_typetype()) {
573 case Type::T_ERROR:
574 // remain silent
575 break;
576 case Type::T_COMPONENT:
577 return t;
578 default:
579 error("Reference `%s' does not refer to a component type",
580 get_dispname().c_str());
581 }
970ed795 582 } else {
a38c6d4c 583 error("Reference `%s' does not refer to a type",
584 get_dispname().c_str());
970ed795
EL
585 }
586 }
587 return 0;
588 }
589
590 bool Reference::has_single_expr()
591 {
592 if (!Ref_base::has_single_expr()) {
593 return false;
594 }
595 if (parlist != NULL) {
596 for (size_t i = 0; i < parlist->get_nof_pars(); i++) {
597 if (!parlist->get_par(i)->has_single_expr()) {
598 return false;
599 }
600 }
601 }
602 return true;
603 }
604
605 void Reference::generate_code(expression_struct_t *expr)
606 {
607 Common::Assignment *ass = get_refd_assignment();
608 if (!ass) FATAL_ERROR("Reference::generate_code()");
609 if (parlist) {
610 // reference without parameters to a template that has only default formal parameters.
611 // if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
612 expr->expr = mputprintf(expr->expr, "%s(",
613 ass->get_genname_from_scope(my_scope).c_str());
614 parlist->generate_code_alias(expr, ass->get_FormalParList(),
615 ass->get_RunsOnType(), false);
616 expr->expr = mputc(expr->expr, ')');
617 } else {
618 expr->expr = mputstr(expr->expr,
619 LazyParamData::in_lazy() ?
620 LazyParamData::add_ref_genname(ass, my_scope).c_str() :
621 ass->get_genname_from_scope(my_scope).c_str());
622 }
623 if (subrefs.get_nof_refs() > 0) subrefs.generate_code(expr, ass);
624 }
625
626 void Reference::generate_code_const_ref(expression_struct_t *expr)
627 {
628 FieldOrArrayRefs *t_subrefs = get_subrefs();
629 if (!t_subrefs || t_subrefs->get_nof_refs() == 0) {
630 generate_code(expr);
631 return;
632 }
633
634 Common::Assignment *ass = get_refd_assignment();
635 if (!ass) FATAL_ERROR("Reference::generate_code_const_ref()");
636
637 bool is_template;
638 switch (ass->get_asstype()) {
639 case Common::Assignment::A_MODULEPAR:
640 case Common::Assignment::A_VAR:
641 case Common::Assignment::A_FUNCTION_RVAL:
642 case Common::Assignment::A_EXT_FUNCTION_RVAL:
643 case Common::Assignment::A_PAR_VAL_IN:
644 case Common::Assignment::A_PAR_VAL_OUT:
645 case Common::Assignment::A_PAR_VAL_INOUT: {
646 is_template = false;
647 break; }
648 case Common::Assignment::A_MODULEPAR_TEMP:
649 case Common::Assignment::A_TEMPLATE:
650 case Common::Assignment::A_VAR_TEMPLATE:
651 case Common::Assignment::A_PAR_TEMPL_IN:
652 case Common::Assignment::A_PAR_TEMPL_OUT:
653 case Common::Assignment::A_PAR_TEMPL_INOUT: {
654 is_template = true;
655 break; }
656 case Common::Assignment::A_CONST:
657 case Common::Assignment::A_EXT_CONST:
658 default:
659 generate_code(expr);
660 return;
661 }
662
663 Type *refd_gov = ass->get_Type();
664 if (is_template) {
665 expr->expr = mputprintf(expr->expr, "const_cast< const %s&>(",
666 refd_gov->get_genname_template(get_my_scope()).c_str() );
667 } else {
668 expr->expr = mputprintf(expr->expr, "const_cast< const %s&>(",
669 refd_gov->get_genname_value(get_my_scope()).c_str());
670 }
671 if (parlist) {
672 // reference without parameters to a template that has only default formal parameters.
673 // if @lazy: nothing to do, it's a C++ function call just like in case of Ref_pard::generate_code()
674 expr->expr = mputprintf(expr->expr, "%s(",
675 ass->get_genname_from_scope(my_scope).c_str());
676 parlist->generate_code_alias(expr, ass->get_FormalParList(),
677 ass->get_RunsOnType(), false);
678 expr->expr = mputc(expr->expr, ')');
679 } else {
680 expr->expr = mputstr(expr->expr,
681 LazyParamData::in_lazy() ?
682 LazyParamData::add_ref_genname(ass, my_scope).c_str() :
683 ass->get_genname_from_scope(my_scope).c_str());
684 }
685 expr->expr = mputstr(expr->expr, ")");
686
687 if (t_subrefs && t_subrefs->get_nof_refs() > 0)
688 t_subrefs->generate_code(expr, ass);
689 }
690
691 void Reference::generate_code_portref(expression_struct_t *expr,
692 Scope *p_scope)
693 {
694 Common::Assignment *ass = get_refd_assignment();
695 if (!ass) FATAL_ERROR("Reference::generate_code_portref()");
696 expr->expr = mputstr(expr->expr,
697 ass->get_genname_from_scope(p_scope).c_str());
698 if (subrefs.get_nof_refs() > 0) subrefs.generate_code(expr, ass);
699 }
700
701 //FIXME quick hack
702 void Reference::generate_code_ispresentbound(expression_struct_t *expr,
703 bool is_template, const bool isbound)
704 {
705 Common::Assignment *ass = get_refd_assignment();
706 const string& ass_id = ass->get_genname_from_scope(my_scope);
707 const char *ass_id_str = ass_id.c_str();
708
709 if (subrefs.get_nof_refs() > 0) {
710 const string& tmp_generalid = my_scope->get_scope_mod_gen()
711 ->get_temporary_id();
712 const char *tmp_generalid_str = tmp_generalid.c_str();
713
714 expression_struct isbound_expr;
715 Code::init_expr(&isbound_expr);
716 isbound_expr.preamble = mputprintf(isbound_expr.preamble,
717 "boolean %s = %s.is_bound();\n", tmp_generalid_str,
718 ass_id_str);
719 ass->get_Type()->generate_code_ispresentbound(&isbound_expr, &subrefs, my_scope->get_scope_mod_gen(),
720 tmp_generalid, ass_id, is_template, isbound);
721
722 expr->preamble = mputstr(expr->preamble, isbound_expr.preamble);
723 expr->preamble = mputstr(expr->preamble, isbound_expr.expr);
724 Code::free_expr(&isbound_expr);
725
726 expr->expr = mputprintf(expr->expr, "%s", tmp_generalid_str);
727 } else {
3abe9331 728 expr->expr = mputprintf(expr->expr, "%s.%s(%s)", ass_id_str,
729 isbound ? "is_bound":"is_present",
730 (!isbound && is_template && omit_in_value_list) ? "TRUE" : "");
970ed795
EL
731 }
732 }
733
734 void Reference::detect_modid()
735 {
736 // do nothing if detection is already performed
737 if (id) return;
738 // the first element of subrefs must be an <id>
739 const Identifier *first_id = subrefs.get_ref(0)->get_id(), *second_id = 0;
740 if (subrefs.get_nof_refs() > 1) {
741 FieldOrArrayRef *second_ref = subrefs.get_ref(1);
742 if (second_ref->get_type() == FieldOrArrayRef::FIELD_REF) {
743 // the reference begins with <id>.<id> (most complicated case)
a38c6d4c 744 // there are 3 possible situations:
745 // 1. first_id points to a local definition (this has the priority)
746 // modid: 0, id: first_id
747 // 2. first_id points to an imported module (trivial case)
748 // modid: first_id, id: second_id
749 // 3. none of the above (first_id might be an imported symbol)
750 // modid: 0, id: first_id
751 // Note: Rule 1 has the priority because it can be overridden using
752 // the notation <id>.objid { ... }.<id> (modid and id are set in the
753 // constructor), but there is no work-around in the reverse way.
754 if (!my_scope->has_ass_withId(*first_id)
755 && my_scope->is_valid_moduleid(*first_id)) {
756 // rule 1 is not fulfilled, but rule 2 is fulfilled
757 second_id = second_ref->get_id();
758 }
970ed795
EL
759 } // else: the reference begins with <id>[<arrayref>] -> there is no modid
760 } // else: the reference consists of a single <id> -> there is no modid
761 if (second_id) {
762 modid = first_id->clone();
763 id = second_id->clone();
764 subrefs.remove_refs(2);
765 } else {
766 modid = 0;
767 id = first_id->clone();
768 subrefs.remove_refs(1);
769 }
770 }
771
772 // =================================
773 // ===== Ref_pard
774 // =================================
775
776 Ref_pard::Ref_pard(const Ref_pard& p)
777 : Ref_base(p), parlist(p.parlist), expr_cache(0)
778 {
779 params = p.params ? p.params->clone() : 0;
780 }
781
782 Ref_pard::Ref_pard(Identifier *p_modid, Identifier *p_id,
783 ParsedActualParameters *p_params)
784 : Ref_base(p_modid, p_id), parlist(), params(p_params), expr_cache(0)
785 {
786 if (!p_params)
787 FATAL_ERROR("Ttcn::Ref_pard::Ref_pard(): NULL parameter");
788 }
789
790 Ref_pard::~Ref_pard()
791 {
792 delete params;
793 Free(expr_cache);
794 }
795
796 Ref_pard *Ref_pard::clone() const
797 {
798 return new Ref_pard(*this);
799 }
800
801 void Ref_pard::set_fullname(const string& p_fullname)
802 {
803 Ref_base::set_fullname(p_fullname);
804 parlist.set_fullname(p_fullname);
805 if (params) params->set_fullname(p_fullname);
806 }
807
808 void Ref_pard::set_my_scope(Scope *p_scope)
809 {
810 Ref_base::set_my_scope(p_scope);
811 parlist.set_my_scope(p_scope);
812 if (params) params->set_my_scope(p_scope);
813 }
814
815 string Ref_pard::get_dispname()
816 {
817 if (is_erroneous) return string("erroneous");
818 string ret_val;
819 if (modid) {
820 ret_val += modid->get_dispname();
821 ret_val += '.';
822 }
823 ret_val += id->get_dispname();
824 ret_val += '(';
825 if (params_checked) {
826 // used after semantic analysis
827 for (size_t i = 0; i < parlist.get_nof_pars(); i++) {
a38c6d4c 828 if (i > 0) ret_val += ", ";
829 parlist.get_par(i)->append_stringRepr(ret_val);
970ed795
EL
830 }
831 } else {
832 // used before semantic analysis
833 for (size_t i = 0; i < params->get_nof_tis(); i++) {
a38c6d4c 834 if (i > 0) ret_val += ", ";
835 params->get_ti_byIndex(i)->append_stringRepr(ret_val);
970ed795
EL
836 }
837 }
838 ret_val += ')';
839 subrefs.append_stringRepr(ret_val);
840 return ret_val;
841 }
842
843 Common::Assignment* Ref_pard::get_refd_assignment(bool check_parlist)
844 {
845 Common::Assignment *ass = Ref_base::get_refd_assignment(check_parlist);
846 if (ass && check_parlist && !params_checked) {
847 params_checked = true;
848 FormalParList *fplist = ass->get_FormalParList();
849 if (fplist) {
a38c6d4c 850 Error_Context cntxt(params, "In actual parameter list of %s",
851 ass->get_description().c_str());
852 is_erroneous = fplist->fold_named_and_chk(params, &parlist);
853 parlist.set_fullname(get_fullname());
854 parlist.set_my_scope(my_scope);
855 // the parsed parameter list is no longer needed
856 delete params;
857 params = 0;
970ed795
EL
858 } else {
859 params->error("The referenced %s cannot have actual parameters",
a38c6d4c 860 ass->get_description().c_str());
970ed795
EL
861 }
862 }
863 return ass;
864 }
865
866 const Identifier* Ref_pard::get_modid()
867 {
868 return modid;
869 }
870
871 const Identifier* Ref_pard::get_id()
872 {
873 return id;
874 }
875
876 ActualParList *Ref_pard::get_parlist()
877 {
878 if (!params_checked) FATAL_ERROR("Ref_pard::get_parlist()");
879 return &parlist;
880 }
881
882 bool Ref_pard::chk_activate_argument()
883 {
884 Common::Assignment *t_ass = get_refd_assignment();
885 if (!t_ass) return false;
886 if (t_ass->get_asstype() != Common::Assignment::A_ALTSTEP) {
887 error("Reference to an altstep was expected in the argument instead of "
a38c6d4c 888 "%s", t_ass->get_description().c_str());
970ed795
EL
889 return false;
890 }
891 my_scope->chk_runs_on_clause(t_ass, *this, "activate");
892 // the altstep reference cannot have sub-references
893 if (get_subrefs()) FATAL_ERROR("Ref_pard::chk_activate_argument()");
894 FormalParList *fp_list = t_ass->get_FormalParList();
895 // the altstep must have formal parameter list
896 if (!fp_list) FATAL_ERROR("Ref_pard::chk_activate_argument()");
897 return fp_list->chk_activate_argument(&parlist,
898 t_ass->get_description().c_str());
899 }
900
901 bool Ref_pard::has_single_expr()
902 {
903 if (!Ref_base::has_single_expr()) return false;
904 for (size_t i = 0; i < parlist.get_nof_pars(); i++)
905 if (!parlist.get_par(i)->has_single_expr()) return false;
906 // if any formal parameter has lazy evaluation
907 Common::Assignment *ass = get_refd_assignment();
908 if (ass) {
909 const FormalParList *fplist = ass->get_FormalParList();
910 if (fplist) {
911 size_t num_formal = fplist->get_nof_fps();
912 for (size_t i=0; i<num_formal; ++i) {
913 const FormalPar *fp = fplist->get_fp_byIndex(i);
914 if (fp->get_lazy_eval()) return false;
915 }
916 }
917 }
918 return true;
919 }
920
921 void Ref_pard::set_code_section(
922 GovernedSimple::code_section_t p_code_section)
923 {
924 Ref_base::set_code_section(p_code_section);
925 for (size_t i = 0; i < parlist.get_nof_pars(); i++)
926 parlist.get_par(i)->set_code_section(p_code_section);
927 }
928
929 void Ref_pard::generate_code(expression_struct_t *expr)
930 {
931 Common::Assignment *ass = get_refd_assignment();
932 // C++ function reference with actual parameter list
933 expr->expr = mputprintf(expr->expr, "%s(",
934 ass->get_genname_from_scope(my_scope).c_str());
935 parlist.generate_code_alias(expr, ass->get_FormalParList(),
936 ass->get_RunsOnType(),false);
937 expr->expr = mputc(expr->expr, ')');
938 // subreferences
939 if (subrefs.get_nof_refs() > 0) subrefs.generate_code(expr, ass);
940 }
941
942 void Ref_pard::generate_code_cached(expression_struct_t *expr)
943 {
944 if (expr_cache) {
945 expr->expr = mputstr(expr->expr, expr_cache);
946 }
947 else {
948 generate_code(expr);
949 expr_cache = mputstr(expr_cache, expr->expr);
950 }
951 }
952
953 void Ref_pard::generate_code_const_ref(expression_struct_t *expr)
954 {
955 FieldOrArrayRefs *t_subrefs = get_subrefs();
956 if (!t_subrefs || t_subrefs->get_nof_refs() == 0) {
957 generate_code(expr);
958 return;
959 }
960
961 Common::Assignment *ass = get_refd_assignment();
962 if (!ass) FATAL_ERROR("Ref_pard::generate_code_const_ref()");
963
964 bool is_template;
965 switch (ass->get_asstype()) {
3abe9331 966 case Common::Assignment::A_TEMPLATE:
967 if (NULL == ass->get_FormalParList()) {
968 // not a parameterized template
969 is_template = true;
970 break;
971 }
972 // else fall through
970ed795
EL
973 case Common::Assignment::A_CONST:
974 case Common::Assignment::A_EXT_CONST:
975 case Common::Assignment::A_ALTSTEP:
976 case Common::Assignment::A_TESTCASE:
977 case Common::Assignment::A_FUNCTION:
978 case Common::Assignment::A_EXT_FUNCTION:
3abe9331 979 case Common::Assignment::A_FUNCTION_RVAL:
980 case Common::Assignment::A_EXT_FUNCTION_RVAL:
981 case Common::Assignment::A_FUNCTION_RTEMP:
982 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
970ed795
EL
983 generate_code(expr);
984 return;
985 case Common::Assignment::A_MODULEPAR:
986 case Common::Assignment::A_VAR:
970ed795
EL
987 case Common::Assignment::A_PAR_VAL_IN:
988 case Common::Assignment::A_PAR_VAL_OUT:
989 case Common::Assignment::A_PAR_VAL_INOUT: {
990 is_template = false;
991 break; }
992 case Common::Assignment::A_MODULEPAR_TEMP:
970ed795 993 case Common::Assignment::A_VAR_TEMPLATE:
970ed795
EL
994 case Common::Assignment::A_PAR_TEMPL_IN:
995 case Common::Assignment::A_PAR_TEMPL_OUT:
996 case Common::Assignment::A_PAR_TEMPL_INOUT: {
997 is_template = true;
998 break; }
999 default:
1000 is_template = false;
1001 break;
1002 }
1003
1004 Type *refd_gov = ass->get_Type();
1005 if (!refd_gov) {
1006 generate_code(expr);
1007 return;
1008 }
1009
1010 if (is_template) {
1011 expr->expr = mputprintf(expr->expr, "const_cast< const %s&>(",
1012 refd_gov->get_genname_template(get_my_scope()).c_str() );
1013 } else {
1014 expr->expr = mputprintf(expr->expr, "const_cast< const %s%s&>(",
1015 refd_gov->get_genname_value(get_my_scope()).c_str(),
1016 is_template ? "_template":"");
1017 }
1018
1019 expr->expr = mputprintf(expr->expr, "%s(",
1020 ass->get_genname_from_scope(my_scope).c_str());
1021 parlist.generate_code_alias(expr, ass->get_FormalParList(),
1022 ass->get_RunsOnType(), false);
1023 expr->expr = mputstr(expr->expr, "))");
1024
1025 t_subrefs->generate_code(expr, ass);
1026 }
1027
1028 // =================================
1029 // ===== NameBridgingScope
1030 // =================================
1031 string NameBridgingScope::get_scopeMacro_name() const
1032 {
1033 if (scopeMacro_name.empty()) FATAL_ERROR("NameBridgingScope::get_scopeMacro_name()");
1034 return scopeMacro_name;
1035 }
1036
1037 NameBridgingScope *NameBridgingScope::clone() const
1038 {
1039 FATAL_ERROR("NameBridgingScope::clone");
1040 }
1041
1042 Common::Assignment* NameBridgingScope::get_ass_bySRef(Ref_simple *p_ref)
1043 {
1044 return get_parent_scope()->get_ass_bySRef(p_ref);
1045 }
1046
1047 // =================================
1048 // ===== RunsOnScope
1049 // =================================
1050
1051 RunsOnScope::RunsOnScope(Type *p_comptype)
1052 : Scope(), component_type(p_comptype)
1053 {
1054 if (!p_comptype || p_comptype->get_typetype() != Type::T_COMPONENT)
1055 FATAL_ERROR("RunsOnScope::RunsOnScope()");
1056 component_type->set_ownertype(Type::OT_RUNSON_SCOPE, this);
1057 component_defs = p_comptype->get_CompBody();
1058 set_scope_name("runs on `" + p_comptype->get_fullname() + "'");
1059 }
1060
1061 RunsOnScope *RunsOnScope::clone() const
1062 {
1063 FATAL_ERROR("RunsOnScope::clone()");
1064 }
1065
1066 void RunsOnScope::chk_uniq()
1067 {
1068 // do not perform this check if the component type is defined in the same
1069 // module as the 'runs on' clause
1070 if (parent_scope->get_scope_mod() == component_defs->get_scope_mod())
1071 return;
1072 size_t nof_defs = component_defs->get_nof_asss();
1073 for (size_t i = 0; i < nof_defs; i++) {
1074 Common::Assignment *comp_def = component_defs->get_ass_byIndex(i);
1075 const Identifier& id = comp_def->get_id();
1076 if (parent_scope->has_ass_withId(id)) {
1077 comp_def->warning("Imported component element definition `%s' hides a "
a38c6d4c 1078 "definition at module scope", comp_def->get_fullname().c_str());
1079 Reference ref(0, id.clone());
1080 Common::Assignment *hidden_ass = parent_scope->get_ass_bySRef(&ref);
1081 hidden_ass->warning("Hidden definition `%s' is here",
1082 hidden_ass->get_fullname().c_str());
970ed795
EL
1083 }
1084
1085 }
1086 }
1087
1088 RunsOnScope *RunsOnScope::get_scope_runs_on()
1089 {
1090 return this;
1091 }
1092
1093 Common::Assignment *RunsOnScope::get_ass_bySRef(Ref_simple *p_ref)
1094 {
1095 if (!p_ref) FATAL_ERROR("Ttcn::RunsOnScope::get_ass_bySRef()");
1096 if (p_ref->get_modid()) return parent_scope->get_ass_bySRef(p_ref);
1097 else {
1098 const Identifier& id = *p_ref->get_id();
1099 if (component_defs->has_local_ass_withId(id)) {
1100 Common::Assignment* ass = component_defs->get_local_ass_byId(id);
1101 if (!ass) FATAL_ERROR("Ttcn::RunsOnScope::get_ass_bySRef()");
1102
1103 if (component_defs->is_own_assignment(ass)) return ass;
1104 else if (ass->get_visibility() == PUBLIC) {
1105 return ass;
1106 }
1107
1108 p_ref->error("The member definition `%s' in component type `%s'"
1109 " is not visible in this scope", id.get_dispname().c_str(),
1110 component_defs->get_id()->get_dispname().c_str());
1111 return 0;
1112 } else return parent_scope->get_ass_bySRef(p_ref);
1113 }
1114 }
1115
1116 bool RunsOnScope::has_ass_withId(const Identifier& p_id)
1117 {
1118 return component_defs->has_ass_withId(p_id)
1119 || parent_scope->has_ass_withId(p_id);
1120 }
1121
1122 // =================================
1123 // ===== FriendMod
1124 // =================================
1125
1126 FriendMod::FriendMod(Identifier *p_modid)
1127 : Node(), modid(p_modid), w_attrib_path(0), parentgroup(0), checked(false)
1128 {
1129 if (!p_modid) FATAL_ERROR("NULL parameter: Ttcn::FriendMod::FriendMod()");
1130 set_fullname("<friends>."+modid->get_dispname());
1131 }
1132
1133 FriendMod::~FriendMod()
1134 {
1135 delete modid;
1136
1137 delete w_attrib_path;
1138 }
1139
1140 FriendMod *FriendMod::clone() const
1141 {
1142 FATAL_ERROR("Ttcn::FriendMod::clone()");
1143 }
1144
1145 void FriendMod::set_fullname(const string& p_fullname)
1146 {
1147 if(w_attrib_path) w_attrib_path->set_fullname(p_fullname + ".<attribpath>");
1148 }
1149
1150 void FriendMod::chk()
1151 {
1152 if (checked) return;
1153
1154 Error_Context cntxt(this, "In friend module declaration");
1155
1156 if (w_attrib_path) {
1157 w_attrib_path->chk_global_attrib();
1158 w_attrib_path->chk_no_qualif();
1159 }
1160
1161 checked = true;
1162 }
1163
1164 void FriendMod::set_with_attr(MultiWithAttrib* p_attrib)
1165 {
1166 if (w_attrib_path) FATAL_ERROR("FriendMod::set_with_attr()");
1167 w_attrib_path = new WithAttribPath();
1168 if (p_attrib && p_attrib->get_nof_elements() > 0) {
1169 w_attrib_path->set_with_attr(p_attrib);
1170 }
1171 }
1172
1173 WithAttribPath* FriendMod::get_attrib_path()
1174 {
1175 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
1176 return w_attrib_path;
1177 }
1178
1179 void FriendMod::set_parent_path(WithAttribPath* p_path)
1180 {
1181 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
1182 w_attrib_path->set_parent(p_path);
1183 }
1184
1185 void FriendMod::set_parent_group(Group* p_group)
1186 {
1187 if(parentgroup) FATAL_ERROR("FriendMod::set_parent_group");
1188 parentgroup = p_group;
1189 }
1190
1191 // =================================
1192 // ===== ImpMod
1193 // =================================
1194
1195 ImpMod::ImpMod(Identifier *p_modid)
1196 : Node(), mod(0), my_mod(0), imptype(I_UNDEF), modid(p_modid),
1197 language_spec(0), is_recursive(false),
1198 w_attrib_path(0), parentgroup(0), visibility(PRIVATE)
1199 {
1200 if (!p_modid) FATAL_ERROR("NULL parameter: Ttcn::ImpMod::ImpMod()");
1201 set_fullname("<imports>." + modid->get_dispname());
1202 }
1203
1204 ImpMod::~ImpMod()
1205 {
1206 delete modid;
1207 delete language_spec;
1208
1209 delete w_attrib_path;
1210 }
1211
1212 ImpMod *ImpMod::clone() const
1213 {
1214 FATAL_ERROR("No clone for you!");
1215 }
1216
1217 void ImpMod::set_fullname(const string& p_fullname)
1218 {
1219 if(w_attrib_path) w_attrib_path->set_fullname(p_fullname + ".<attribpath>");
1220 }
1221
1222 void ImpMod::chk()
1223 {
1224 if (w_attrib_path) {
1225 w_attrib_path->chk_global_attrib();
1226 w_attrib_path->chk_no_qualif();
1227 }
1228 }
1229
1230 void ImpMod::chk_imp(ReferenceChain& refch, vector<Common::Module>& moduleStack)
1231 {
1232 Error_Context cntxt(this, "In import definition");
1233
1234 if (!modules->has_mod_withId(*modid)) {
1235 error("There is no module with identifier `%s'",
1236 modid->get_dispname().c_str());
1237 return;
1238 }
1239
1240 Common::Module *m = modules->get_mod_byId(*modid);
1241 if (m == NULL)
1242 return;
1243
1244 set_mod(m);
1245 if (m == my_mod) {
1246 error("A module cannot import from itself");
1247 return;
1248 }
1249 chk();
1250
1251 moduleStack.add(m);
1252
1253 refch.mark_state();
1254 if (refch.exists(my_mod->get_fullname())) {
1255 if(my_mod->get_moduletype()!=Common::Module::MOD_ASN){ // Do not warning for circular import in ASN.1 module. It is legal
1256 my_mod->warning("Circular import chain is not recommended: %s",
1257 refch.get_dispstr(my_mod->get_fullname()).c_str());
1258 }
1259 refch.prev_state();
1260 return;
1261 } else {
1262 refch.add(my_mod->get_fullname());
1263
1264 if (ImpMod::I_IMPORTIMPORT == imptype){
1265 Ttcn::Module* ttcnmodule =static_cast<Ttcn::Module*>(m);
1266 const Imports& imp = ttcnmodule->get_imports();
1267
1268 for (size_t t = 0; t < imp.impmods_v.size(); t++) {
1269 const ImpMod *im = imp.impmods_v[t];
1270 const Identifier& im_id = im->get_modid();
1271 Common::Module *cm = modules->get_mod_byId(im_id); // never NULL
1272
1273 refch.mark_state();
1274 if (PRIVATE != im->get_visibility()) {
1275 if (refch.exists(m->get_fullname())) {
1276 if(m->get_moduletype()!=Common::Module::MOD_ASN){ // Do not warning for circular import in ASN.1 module. It is legal
1277 m->warning("Circular import chain is not recommended: %s",
1278 refch.get_dispstr(m->get_fullname()).c_str());
1279 }
1280 refch.prev_state();
1281 continue;
1282 } else {
1283 refch.add(m->get_fullname());
1284 cm->chk_imp(refch, moduleStack);
1285 }
1286 }
1287 refch.prev_state();
1288 }
1289 } else {
1290 //refch.mark_state();
1291 m->chk_imp(refch, moduleStack);
1292 //refch.prev_state();
1293 }
1294 }
1295 refch.prev_state();
1296
1297 size_t state=moduleStack.size();
1298 moduleStack.replace(state, moduleStack.size() - state);
1299 }
1300
1301 bool ImpMod::has_imported_def(const Identifier& p_source_modid,
1302 const Identifier& p_id, const Location *loc) const
1303 {
1304 if (!mod) return false;
1305 else {
1306 switch (imptype) {
1307 case I_ALL:
1308 case I_IMPORTSPEC:
1309 {
1310 Common::Assignment* return_assignment = mod->importAssignment(p_source_modid, p_id);
1311 if (return_assignment != NULL) {
1312 return true;
1313 } else {
1314 return false;
1315 }
1316 break;
1317 }
1318 case I_IMPORTIMPORT:
1319 {
1320 Ttcn::Module *tm = static_cast<Ttcn::Module*>(mod); // B
1321
1322 const Imports & imps = tm->get_imports();
1323
1324 vector<ImpMod> tempusedImpMods;
1325 for (size_t i = 0, num = imps.impmods_v.size(); i < num; ++i) {
1326 ReferenceChain* referencechain = new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
1327 Common::Assignment* return_assignment = imps.impmods_v[i]->
1328 get_imported_def(p_source_modid, p_id, loc, referencechain, tempusedImpMods); // C
1329 referencechain->reset();
1330 delete referencechain;
1331
1332 if (return_assignment != NULL) {
1333 return true;
1334 } else {
1335 return false;
1336 }
1337 }
1338 //satisfy destructor
1339 tempusedImpMods.clear();
1340
1341 break;
1342 }
1343 default:
1344 FATAL_ERROR("ImpMod::get_imported_def");
1345 }
1346 }
1347 return false;
1348 }
1349
1350 Common::Assignment *ImpMod::get_imported_def(
1351 const Identifier& p_source_modid, const Identifier& p_id,
1352 const Location *loc, ReferenceChain* refch,
1353 vector<ImpMod>& usedImpMods) const
1354 {
1355 if (!mod) return 0;
1356 else {
1357
1358 Common::Assignment* result = NULL;
1359
1360 switch (imptype) {
1361 case I_ALL:
1362 case I_IMPORTSPEC:
1363 result = mod->importAssignment(p_source_modid, p_id);
1364 if (result != NULL) {
1365 usedImpMods.add(const_cast<Ttcn::ImpMod*>(this));
1366 }
1367 return result;
1368 break;
1369 case I_IMPORTIMPORT:
1370 {
1371 Ttcn::Module *tm = static_cast<Ttcn::Module*>(mod);
1372
1373 const Imports & imps = tm->get_imports();
1374 Common::Assignment* t_ass = NULL;
1375
1376 for (size_t i = 0, num = imps.impmods_v.size(); i < num; ++i) {
1377 vector<ImpMod> tempusedImpMods;
1378
1379 refch->mark_state();
1380 if (imps.impmods_v[i]->get_visibility() == PUBLIC) {
1381 t_ass = imps.impmods_v[i]->get_imported_def(p_source_modid, p_id, loc, refch, tempusedImpMods );
1382 }
1383 else if (imps.impmods_v[i]->get_visibility() == FRIEND) {
1384 t_ass = imps.impmods_v[i]->get_imported_def(p_source_modid, p_id, loc, refch, tempusedImpMods );
1385 if (t_ass != NULL){
1386 tempusedImpMods.add(imps.impmods_v[i]);
1387 }
1388 }
1389 refch->prev_state();
1390
1391 if (t_ass != NULL) {
1392 bool visible = true;
1393 for (size_t j = 0; j < tempusedImpMods.size(); j++) {
1394 ImpMod* impmod_l = tempusedImpMods[j];
1395 //check whether the module is TTCN
1396 if (impmod_l->get_mod()->get_moduletype() == Common::Module::MOD_TTCN) {
1397 // cast to ttcn module
1398 Ttcn::Module *ttcn_m = static_cast<Ttcn::Module*>(impmod_l->get_mod());
1399 if (!ttcn_m->is_visible(mod->get_modid(), impmod_l->get_visibility())) {
1400 visible= false;
1401 }
1402 }
1403 }
1404 if (visible) {
1405 for (size_t t = 0; i< tempusedImpMods.size(); i++) {
1406 usedImpMods.add(tempusedImpMods[t]);
1407 }
1408
1409 if (!result) {
1410 result = t_ass;
1411 } else if(result != t_ass) {
1412 if (loc == NULL) {
1413 result = NULL;
1414 } else {
1415 loc->error(
1416 "It is not possible to resolve the reference unambigously"
1417 ", as it can be resolved to `%s' and to `%s'",
1418 result->get_fullname().c_str(), t_ass->get_fullname().c_str());
1419 }
1420 }
1421 }
1422 t_ass = NULL;
1423 }
1424 tempusedImpMods.clear();
1425 }
1426
1427 if (result != NULL) {
1428 usedImpMods.add(const_cast<Ttcn::ImpMod*>(this));
1429 }
1430 return result;
1431 break;
1432 }
1433 default:
1434 FATAL_ERROR("ImpMod::get_imported_def");
1435 }
1436 }
1437 }
1438
1439 void ImpMod::set_language_spec(const char *p_language_spec)
1440 {
1441 if (language_spec) FATAL_ERROR("ImpMod::set_language_spec()");
1442 if (p_language_spec) language_spec = new string(p_language_spec);
1443 }
1444
1445 void ImpMod::generate_code(output_struct *target)
1446 {
1447 const char *module_name = modid->get_name().c_str();
1448
1449 target->header.includes = mputprintf(target->header.includes,
1450 "#include \"%s.hh\"\n",
1451 duplicate_underscores ? module_name : modid->get_ttcnname().c_str());
1452
1453 target->functions.pre_init = mputprintf(target->functions.pre_init,
a38c6d4c 1454 "%s%s.pre_init_module();\n", module_name,
970ed795
EL
1455 "::module_object");
1456
1457 if (mod->get_moduletype() == Common::Module::MOD_TTCN) {
1458 target->functions.post_init = mputprintf(target->functions.post_init,
a38c6d4c 1459 "%s%s.post_init_module();\n", module_name,
970ed795
EL
1460 "::module_object");
1461
1462 }
1463 }
1464
1465 void ImpMod::dump(unsigned level) const
1466 {
1467 DEBUG(level, "Import from module %s", modid->get_dispname().c_str());
1468 if (w_attrib_path) {
1469 MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
1470 if (attrib) {
a38c6d4c 1471 DEBUG(level + 1, "Attributes:");
1472 attrib->dump(level + 2);
970ed795
EL
1473 }
1474 }
1475 }
1476
1477 void ImpMod::set_with_attr(MultiWithAttrib* p_attrib)
1478 {
1479 if (w_attrib_path) FATAL_ERROR("ImpMod::set_with_attr()");
1480 w_attrib_path = new WithAttribPath();
1481 if (p_attrib && p_attrib->get_nof_elements() > 0) {
1482 w_attrib_path->set_with_attr(p_attrib);
1483 }
1484 }
1485
1486 WithAttribPath* ImpMod::get_attrib_path()
1487 {
1488 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
1489 return w_attrib_path;
1490 }
1491
1492 void ImpMod::set_parent_path(WithAttribPath* p_path)
1493 {
1494 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
1495 w_attrib_path->set_parent(p_path);
1496 }
1497
1498 void ImpMod::set_parent_group(Group* p_group)
1499 {
1500 if(parentgroup) FATAL_ERROR("ImpMod::set_parent_group");
1501 parentgroup = p_group;
1502 }
1503
1504 // =================================
1505 // ===== Imports
1506 // =================================
1507
1508 Imports::~Imports()
1509 {
1510 for (size_t i = 0; i< impmods_v.size(); i++)
1511 delete impmods_v[i];
1512 impmods_v.clear();
1513 }
1514
1515 Imports *Imports::clone() const
1516 {
1517 FATAL_ERROR("Ttcn::Imports::clone()");
1518 }
1519
1520 void Imports::add_impmod(ImpMod *p_impmod)
1521 {
1522 if (!p_impmod) FATAL_ERROR("Ttcn::Imports::add_impmod()");
1523 impmods_v.add(p_impmod);
1524 p_impmod->set_my_mod(my_mod);
1525 }
1526
1527 void Imports::set_my_mod(Module *p_mod)
1528 {
1529 my_mod = p_mod;
1530 for(size_t i = 0; i < impmods_v.size(); i++)
1531 impmods_v[i]->set_my_mod(my_mod);
1532 }
1533
1534 bool Imports::has_impmod_withId(const Identifier& p_id) const
1535 {
1536 for (size_t i = 0, size = impmods_v.size(); i < size; ++i) {
1537 const ImpMod* im = impmods_v[i];
1538 const Identifier& im_id = im->get_modid();
1539 const string& im_name = im_id.get_name();
1540 if (p_id.get_name() == im_name) {
1541 // The identifier represents a module imported in the current module
1542 return true;
1543 }
1544 }
1545 return false;
1546 }
1547
1548 void Imports::chk_imp(ReferenceChain& refch, vector<Common::Module>& moduleStack)
1549 {
1550 if (impmods_v.size() <= 0) return;
1551
1552 if (!my_mod) FATAL_ERROR("Ttcn::Imports::chk_imp()");
1553
1554 checked = true;
1555
1556 //Do some checks
1557 for(size_t n = 0; n < impmods_v.size(); n++)
1558 {
1559 impmods_v[n]->chk();
1560 }
1561
1562 //TODO this whole thing should be moved into impmod::chk
1563 Identifier address_id(Identifier::ID_TTCN, string("address"));
1564 for (size_t n = 0; n < impmods_v.size(); n++) {
1565 ImpMod *im = impmods_v[n];
1566 im->chk_imp(refch, moduleStack);
1567
1568 const Identifier& im_id = im->get_modid();
1569 Common::Module *m = modules->get_mod_byId(im_id);
1570 if (m == NULL)
1571 continue;
1572 if (m->get_gen_code()) my_mod->set_gen_code();
1573 } // next assignment
1574 }
1575
1576 bool Imports::has_imported_def(const Identifier& p_id, const Location *loc) const
1577 {
1578 for (size_t n = 0; n < impmods_v.size(); n++) {
1579 ImpMod *im = impmods_v[n];
1580 bool return_bool = im->has_imported_def(my_mod->get_modid(), p_id, loc);
1581 if (return_bool) return true;
1582 }
1583 return false;
1584 }
1585
1586 Common::Assignment *Imports::get_imported_def(
1587 const Identifier& p_source_modid, const Identifier& p_id,
1588 const Location *loc, ReferenceChain* refch)
1589 {
1590 vector<ImpMod> tempusedImpMods;
1591 Common::Assignment* result = NULL;
1592 for (size_t n = 0; n < impmods_v.size(); n++) {
1593 ImpMod *im = impmods_v[n];
1594 refch->mark_state();
1595 Common::Assignment* ass = im->get_imported_def(
1596 p_source_modid, p_id, loc, refch, tempusedImpMods);
1597 tempusedImpMods.clear();
1598 refch->prev_state();
1599
1600 if(ass) {
1601 if (!result) {
1602 result = ass;
1603 } else if(result != ass && loc) {
1604 if(loc == NULL) {
1605 result = NULL;
1606 } else {
1607 loc->error(
1608 "It is not possible to resolve the reference unambigously"
1609 ", as it can be resolved to `%s' and to `%s'",
1610 result->get_fullname().c_str(), ass->get_fullname().c_str());
1611 }
1612 }
1613 }
1614 }
1615 return result;
1616 }
1617
1618 void Imports::get_imported_mods(Module::module_set_t& p_imported_mods) const
1619 {
1620 for (size_t i = 0; i < impmods_v.size(); i++) {
1621 ImpMod *im = impmods_v[i];
1622 Common::Module *m = im->get_mod();
1623 if (!m) continue;
1624 if (!p_imported_mods.has_key(m)) {
1625 p_imported_mods.add(m, 0);
1626 m->get_visible_mods(p_imported_mods);
1627 }
1628 }
1629 }
1630
1631 void Imports::generate_code(output_struct *target)
1632 {
1633 bool base_lib_needed = true;
1634 for (size_t i = 0; i < impmods_v.size(); i++) {
1635 ImpMod *im = impmods_v[i];
1636 Common::Module *m = im->get_mod();
1637 // do not include the header file of the base library if a real
1638 // (not circular) imported module is found
1639 if (base_lib_needed && !m->is_visible(my_mod)) base_lib_needed = false;
1640 // inclusion of m's header file can be eliminated if we find another
1641 // imported module that imports m
1642 bool covered = false;
1643 for (size_t j = 0; j < impmods_v.size(); j++) {
a38c6d4c 1644 // skip over the same import definition
1645 if (j == i) continue;
1646 ImpMod *im2 = impmods_v[j];
1647 Common::Module *m2 = im2->get_mod();
1648 // a module that is equivalent to the current module due to
1649 // circular imports cannot be used to cover anything
1650 if (m2->is_visible(my_mod)) continue;
1651 if (m2->is_visible(m) && !m->is_visible(m2)) {
1652 // m2 covers m (i.e. m is visible from m2)
1653 // and they are not in the same import loop
1654 covered = true;
1655 break;
1656 }
970ed795
EL
1657 }
1658 // do not generate the #include if a covering module is found
1659 if (!covered) im->generate_code(target);
1660 }
1661 if (base_lib_needed) {
3abe9331 1662 // if no real import was found the base library definitions have to be
1663 // #include'd (also, make sure this is the first include)
1664 char* temp = target->header.includes;
1665 target->header.includes = mcopystr("#include <TTCN3.hh>\n");
1666 target->header.includes = mputstr(target->header.includes, temp);
1667 Free(temp);
970ed795
EL
1668 }
1669 }
1670
1671 void Imports::generate_code(CodeGenHelper& cgh) {
1672 generate_code(cgh.get_current_outputstruct());
1673 }
1674
1675 void Imports::dump(unsigned level) const
1676 {
1677 DEBUG(level, "Imports (%lu pcs.)", (unsigned long) impmods_v.size());
1678 for (size_t i = 0; i < impmods_v.size(); i++)
1679 impmods_v[i]->dump(level + 1);
1680 }
1681
1682 // =================================
1683 // ===== Definitions
1684 // =================================
1685
1686 Definitions::~Definitions()
1687 {
1688 for(size_t i = 0; i < ass_v.size(); i++) delete ass_v[i];
1689 ass_v.clear();
1690 ass_m.clear();
1691 }
1692
1693 Definitions *Definitions::clone() const
1694 {
1695 FATAL_ERROR("Definitions::clone");
1696 }
1697
1698 void Definitions::add_ass(Definition *p_ass)
1699 {
1700 // it is too late to add a new one after it has been checked.
1701 if (checked || !p_ass) FATAL_ERROR("Ttcn::OtherDefinitions::add_ass()");
1702 ass_v.add(p_ass);
1703 p_ass->set_my_scope(this);
1704 }
1705
1706 void Definitions::set_fullname(const string& p_fullname)
1707 {
1708 Common::Assignments::set_fullname(p_fullname);
1709 for(size_t i = 0; i < ass_v.size(); i++) {
1710 Definition *ass = ass_v[i];
1711 ass->set_fullname(p_fullname + "." + ass->get_id().get_dispname());
1712 }
1713 }
1714
1715 bool Definitions::has_local_ass_withId(const Identifier& p_id)
1716 {
1717 if (!checked) chk_uniq();
1718 return ass_m.has_key(p_id.get_name());
1719 }
1720
1721 Common::Assignment* Definitions::get_local_ass_byId(const Identifier& p_id)
1722 {
1723 if (!checked) chk_uniq();
1724 return ass_m[p_id.get_name()];
1725 }
1726
1727 size_t Definitions::get_nof_asss()
1728 {
1729 if (!checked) chk_uniq();
1730 return ass_m.size();
1731 }
1732
1733 size_t Definitions::get_nof_raw_asss()
1734 {
1735 return ass_v.size();
1736 }
1737
1738 Common::Assignment* Definitions::get_ass_byIndex(size_t p_i)
1739 {
1740 if (!checked) chk_uniq();
1741 return ass_m.get_nth_elem(p_i);
1742 }
1743
1744 Ttcn::Definition* Definitions::get_raw_ass_byIndex(size_t p_i) {
1745 return ass_v[p_i];
1746 }
1747
1748 void Definitions::chk_uniq()
1749 {
1750 if (checked) return;
1751 ass_m.clear();
1752 for (size_t i = 0; i < ass_v.size(); i++) {
1753 Definition *ass = ass_v[i];
1754 const Identifier& id = ass->get_id();
1755 const string& name = id.get_name();
1756 if (ass_m.has_key(name)) {
1757 const char *dispname_str = id.get_dispname().c_str();
1758 ass->error("Duplicate definition with name `%s'", dispname_str);
1759 ass_m[name]->note("Previous definition of `%s' is here", dispname_str);
1760 } else {
a38c6d4c 1761 ass_m.add(name, ass);
1762 if (parent_scope->is_valid_moduleid(id)) {
1763 ass->warning("Definition with name `%s' hides a module identifier",
1764 id.get_dispname().c_str());
1765 }
970ed795
EL
1766 }
1767 }
1768 checked = true;
1769 }
1770
1771 void Definitions::chk()
1772 {
1773 for (size_t i = 0; i < ass_v.size(); i++) ass_v[i]->chk();
1774 }
1775
1776 void Definitions::chk_for()
1777 {
1778 if (checked) return;
1779 checked = true;
1780 ass_m.clear();
1781 // all checks are done in one iteration because
1782 // forward referencing is not allowed between the definitions
1783 for (size_t i = 0; i < ass_v.size(); i++) {
1784 Definition *def = ass_v[i];
1785 const Identifier& id = def->get_id();
1786 const string& name = id.get_name();
1787 if (ass_m.has_key(name)) {
a38c6d4c 1788 const char *dispname_str = id.get_dispname().c_str();
1789 def->error("Duplicate definition with name `%s'", dispname_str);
1790 ass_m[name]->note("Previous definition of `%s' is here", dispname_str);
970ed795 1791 } else {
a38c6d4c 1792 ass_m.add(name, def);
1793 if (parent_scope) {
1794 if (parent_scope->has_ass_withId(id)) {
1795 const char *dispname_str = id.get_dispname().c_str();
1796 def->error("Definition with identifier `%s' is not unique in the "
1797 "scope hierarchy", dispname_str);
1798 Reference ref(0, id.clone());
1799 Common::Assignment *ass = parent_scope->get_ass_bySRef(&ref);
1800 if (!ass) FATAL_ERROR("OtherDefinitions::chk_for()");
1801 ass->note("Previous definition with identifier `%s' in higher "
1802 "scope unit is here", dispname_str);
1803 } else if (parent_scope->is_valid_moduleid(id)) {
1804 def->warning("Definition with name `%s' hides a module identifier",
1805 id.get_dispname().c_str());
1806 }
1807 }
970ed795
EL
1808 }
1809 def->chk();
1810 }
1811 }
1812
1813 void Definitions::set_genname(const string& prefix)
1814 {
1815 for (size_t i = 0; i < ass_v.size(); i++) {
1816 Definition *def = ass_v[i];
1817 def->set_genname(prefix + def->get_id().get_name());
1818 }
1819 }
1820
1821 void Definitions::generate_code(output_struct* target)
1822 {
1823 for(size_t i = 0; i < ass_v.size(); i++) ass_v[i]->generate_code(target);
1824 }
1825
1826 void Definitions::generate_code(CodeGenHelper& cgh) {
1827 // FIXME: implement
1828 for(size_t i = 0; i < ass_v.size(); i++) ass_v[i]->generate_code(cgh);
1829 }
1830
1831 char* Definitions::generate_code_str(char *str)
1832 {
1833 for(size_t i=0; i<ass_v.size(); i++) {
1834 str = ass_v[i]->update_location_object(str);
1835 str=ass_v[i]->generate_code_str(str);
1836 }
1837 return str;
1838 }
1839
1840 void Definitions::ilt_generate_code(ILT *ilt)
1841 {
1842 for(size_t i=0; i<ass_v.size(); i++)
1843 ass_v[i]->ilt_generate_code(ilt);
1844 }
1845
1846
1847 void Definitions::dump(unsigned level) const
1848 {
1849 DEBUG(level, "Definitions: (%lu pcs.)", (unsigned long) ass_v.size());
1850 for(size_t i = 0; i < ass_v.size(); i++) ass_v[i]->dump(level + 1);
1851 }
1852
1853 // =================================
1854 // ===== Group
1855 // =================================
1856
1857 Group::Group(Identifier *p_id)
1858 : Node(), Location(), parent_group(0), w_attrib_path(0), id(p_id),
1859 checked(false)
1860 {
1861 if (!p_id) FATAL_ERROR("Group::Group()");
1862 }
1863
1864 Group::~Group()
1865 {
1866 delete w_attrib_path;
1867 ass_v.clear();
1868 ass_m.clear();
1869 for (size_t i = 0; i < group_v.size(); i++) delete group_v[i];
1870 group_v.clear();
1871 group_m.clear();
1872 impmods_v.clear();
1873 friendmods_v.clear();
1874 delete id;
1875 }
1876
1877 Group* Group::clone() const
1878 {
1879 FATAL_ERROR("Ttcn::Group::clone()");
1880 }
1881
1882 void Group::set_fullname(const string& p_fullname)
1883 {
1884 Node::set_fullname(p_fullname);
1885 for(size_t i = 0; i < group_v.size() ; i++)
1886 {
1887 group_v[i]->set_fullname(p_fullname + ".<group " + Int2string(i) + ">");
1888 }
1889 if (w_attrib_path) w_attrib_path->set_fullname( p_fullname
1890 + ".<attribpath>");
1891 }
1892
1893 void Group::add_ass(Definition* p_ass)
1894 {
1895 ass_v.add(p_ass);
1896 p_ass->set_parent_group(this);
1897 }
1898
1899 void Group::add_group(Group* p_group)
1900 {
1901 group_v.add(p_group);
1902 }
1903
1904 void Group::set_parent_group(Group* p_parent_group)
1905 {
1906 if (parent_group) FATAL_ERROR("Group::set_parent_group()");
1907 parent_group = p_parent_group;
1908 }
1909
1910 void Group::set_with_attr(MultiWithAttrib* p_attrib)
1911 {
1912 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
1913 w_attrib_path->set_with_attr(p_attrib);
1914 }
1915
1916 WithAttribPath* Group::get_attrib_path()
1917 {
1918 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
1919 return w_attrib_path;
1920 }
1921
1922 void Group::set_parent_path(WithAttribPath* p_path)
1923 {
1924 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
1925 w_attrib_path->set_parent(p_path);
1926 }
1927
1928 void Group::chk_uniq()
1929 {
1930 if (checked) return;
1931 ass_m.clear();
1932 group_m.clear();
1933
1934 for (size_t i = 0; i < ass_v.size(); i++) {
1935 Definition *ass = ass_v[i];
1936 const string& ass_name = ass->get_id().get_name();
1937 if (!ass_m.has_key(ass_name)) ass_m.add(ass_name, ass);
1938 }
1939
1940 for(size_t i = 0; i < group_v.size(); i++) {
1941 Group *group = group_v[i];
1942 const Identifier& group_id = group->get_id();
1943 const string& group_name = group_id.get_name();
1944 if (ass_m.has_key(group_name)) {
1945 group->error("Group name `%s' clashes with a definition",
a38c6d4c 1946 group_id.get_dispname().c_str());
970ed795 1947 ass_m[group_name]->note("Definition of `%s' is here",
a38c6d4c 1948 group_id.get_dispname().c_str());
970ed795
EL
1949 }
1950 if (group_m.has_key(group_name)) {
1951 group->error("Duplicate group with name `%s'",
a38c6d4c 1952 group_id.get_dispname().c_str());
970ed795 1953 group_m[group_name]->note("Group `%s' is already defined here",
a38c6d4c 1954 group_id.get_dispname().c_str());
970ed795
EL
1955 } else group_m.add(group_name, group);
1956 }
1957 checked = true;
1958 }
1959
1960 void Group::chk()
1961 {
1962 Error_Context cntxt(this, "In group `%s'", id->get_dispname().c_str());
1963
1964 chk_uniq();
1965
1966 if (w_attrib_path) {
1967 w_attrib_path->chk_global_attrib();
1968 w_attrib_path->chk_no_qualif();
1969 }
1970
1971 for(size_t i = 0; i < group_v.size(); i++) group_v[i]->chk();
1972 }
1973
1974 void Group::add_impmod(ImpMod *p_impmod)
1975 {
1976 impmods_v.add(p_impmod);
1977 p_impmod->set_parent_group(this);
1978 }
1979
1980 void Group::add_friendmod(FriendMod *p_friendmod)
1981 {
1982 friendmods_v.add(p_friendmod);
1983 p_friendmod->set_parent_group(this);
1984 }
1985
1986 void Group::dump(unsigned level) const
1987 {
1988 DEBUG(level, "Group: %s", id->get_dispname().c_str());
1989 DEBUG(level + 1, "Nested groups: (%lu pcs.)",
1990 (unsigned long) group_v.size());
1991 for(size_t i = 0; i < group_v.size(); i++) group_v[i]->dump(level + 2);
1992 DEBUG(level + 1, "Nested definitions: (%lu pcs.)",
1993 (unsigned long) ass_v.size());
1994 for(size_t i = 0; i < ass_v.size(); i++) ass_v[i]->dump(level + 2);
1995 DEBUG(level + 1, "Nested imports: (%lu pcs.)",
1996 (unsigned long) impmods_v.size());
1997 for(size_t i = 0; i < impmods_v.size(); i++) impmods_v[i]->dump(level + 2);
1998 if (w_attrib_path) {
1999 MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
2000 if (attrib) {
a38c6d4c 2001 DEBUG(level + 1, "Group Attributes:");
2002 attrib->dump(level + 2);
970ed795
EL
2003 }
2004 }
2005 }
2006
2007 // =================================
2008 // ===== ControlPart
2009 // =================================
2010
2011 ControlPart::ControlPart(StatementBlock* p_block)
2012 : Node(), Location(), block(p_block), w_attrib_path(0)
2013 {
2014 if (!p_block) FATAL_ERROR("ControlPart::ControlPart()");
2015 }
2016
2017 ControlPart::~ControlPart()
2018 {
2019 delete block;
2020 delete w_attrib_path;
2021 }
2022
2023 ControlPart* ControlPart::clone() const
2024 {
2025 FATAL_ERROR("ControlPart::clone");
2026 }
2027
2028 void ControlPart::set_fullname(const string& p_fullname)
2029 {
2030 block->set_fullname(p_fullname);
2031 if(w_attrib_path) w_attrib_path->set_fullname(p_fullname + ".<attribpath>");
2032 }
2033
2034 void ControlPart::set_my_scope(Scope *p_scope)
2035 {
2036 bridgeScope.set_parent_scope(p_scope);
2037 string temp("control");
2038 bridgeScope.set_scopeMacro_name(temp);
2039
2040 block->set_my_scope(&bridgeScope);
2041 }
2042
2043 void ControlPart::chk()
2044 {
2045 Error_Context cntxt(this, "In control part");
2046 block->chk();
2047 if (!semantic_check_only)
2048 block->set_code_section(GovernedSimple::CS_INLINE);
2049 if (w_attrib_path) {
2050 w_attrib_path->chk_global_attrib();
2051 w_attrib_path->chk_no_qualif();
2052 }
2053 }
2054
2055 void ControlPart::generate_code(output_struct *target, Module *my_module)
2056 {
2057 const char *module_dispname = my_module->get_modid().get_dispname().c_str();
2058 target->functions.control =
2059 create_location_object(target->functions.control, "CONTROLPART",
2060 module_dispname);
2061 target->functions.control = mputprintf(target->functions.control,
2062 "TTCN_Runtime::begin_controlpart(\"%s\");\n", module_dispname);
2063 target->functions.control =
2064 block->generate_code(target->functions.control);
2065 target->functions.control = mputstr(target->functions.control,
2066 "TTCN_Runtime::end_controlpart();\n");
2067 }
2068
2069 void ControlPart::set_with_attr(MultiWithAttrib* p_attrib)
2070 {
2071 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2072 w_attrib_path->set_with_attr(p_attrib);
2073 }
2074
2075 WithAttribPath* ControlPart::get_attrib_path()
2076 {
2077 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2078 return w_attrib_path;
2079 }
2080
2081 void ControlPart::set_parent_path(WithAttribPath* p_path)
2082 {
2083 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2084 w_attrib_path->set_parent(p_path);
2085 block->set_parent_path(w_attrib_path);
2086 }
2087
2088 void ControlPart::dump(unsigned level) const
2089 {
2090 DEBUG(level, "Control part");
2091 block->dump(level + 1);
2092 if (w_attrib_path) {
2093 MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
2094 if (attrib) {
a38c6d4c 2095 DEBUG(level + 1, "Attributes:");
2096 attrib->dump(level + 2);
970ed795
EL
2097 }
2098 }
2099 }
2100
2101 // =================================
2102 // ===== Module
2103 // =================================
2104
2105 Module::Module(Identifier *p_modid)
2106 : Common::Module(MOD_TTCN, p_modid), language_spec(0), w_attrib_path(0),
2107 controlpart(0)
2108 {
2109 asss = new Definitions();
2110 asss->set_parent_scope(this);
2111 imp = new Imports();
2112 imp->set_my_mod(this);
2113 //modified_encodings = true; // Assume always true for TTCN modules
2114 }
2115
2116 Module::~Module()
2117 {
2118 delete language_spec;
2119 delete asss;
2120 for (size_t i = 0; i < group_v.size(); i++) delete group_v[i];
2121 group_v.clear();
2122 group_m.clear();
2123 delete imp;
2124 for (size_t i = 0; i < friendmods_v.size(); i++) delete friendmods_v[i];
2125 friendmods_v.clear();
2126 delete controlpart;
2127 for (size_t i = 0; i < runs_on_scopes.size(); i++)
2128 delete runs_on_scopes[i];
2129 runs_on_scopes.clear();
2130 delete w_attrib_path;
2131 }
2132
2133 void Module::add_group(Group* p_group)
2134 {
2135 group_v.add(p_group);
2136 }
2137
2138 void Module::add_friendmod(FriendMod *p_friendmod)
2139 {
2140 friendmods_v.add(p_friendmod);
2141 p_friendmod->set_my_mod(this);
2142 }
2143
2144 Module *Module::clone() const
2145 {
2146 FATAL_ERROR("Ttcn::Module::clone()");
2147 }
2148
2149 Common::Assignment *Module::importAssignment(const Identifier& p_modid,
2150 const Identifier& p_id) const
2151 {
2152 if (asss->has_local_ass_withId(p_id)) {
2153 Common::Assignment* ass = asss->get_local_ass_byId(p_id);
2154 if (!ass) FATAL_ERROR("Ttcn::Module::importAssignment()");
2155
2156 switch(ass->get_visibility()) {
2157 case FRIEND:
2158 for (size_t i = 0; i < friendmods_v.size(); i++) {
2159 if (friendmods_v[i]->get_modid() == p_modid) return ass;
2160 }
2161 return 0;
2162 case PUBLIC:
2163 return ass;
2164 case PRIVATE:
2165 return 0;
2166 default:
2167 FATAL_ERROR("Ttcn::Module::importAssignment()");
2168 return 0;
2169 }
2170 } else return 0;
2171 }
2172
2173 void Module::set_fullname(const string& p_fullname)
2174 {
2175 Node::set_fullname(p_fullname);
2176 asss->set_fullname(p_fullname);
2177 if (controlpart) controlpart->set_fullname(p_fullname + ".control");
2178 for(size_t i = 0; i < group_v.size(); i++)
2179 {
2180 group_v[i]->set_fullname(p_fullname + ".<group " + Int2string(i) + ">");
2181 }
2182 if (w_attrib_path) w_attrib_path->set_fullname(p_fullname
2183 + ".<attribpath>");
2184 }
2185
2186 Common::Assignments *Module::get_scope_asss()
2187 {
2188 return asss;
2189 }
2190
2191 bool Module::has_imported_ass_withId(const Identifier& p_id)
2192 {
2193 const Location *loc = NULL;
2194 for (size_t i = 0, num = imp->get_imports_size(); i < num; ++i) {
2195 const ImpMod* im = imp->get_impmod(i);
2196 //TODO use a reference instead of an identifier
2197 if(im->has_imported_def(*modid, p_id, loc)) return true;
2198 }
2199 return false;
2200 }
2201
2202 Common::Assignment* Module::get_ass_bySRef(Ref_simple *p_ref)
2203 {
2204 const Identifier *r_modid = p_ref->get_modid();
2205 const Identifier *r_id = p_ref->get_id();
2206 if (r_modid) {
2207 // the reference contains a module name
2208 if (r_modid->get_name() != modid->get_name()) {
2209 // the reference points to another module
2210 bool has_impmod_with_name = false;
2211 Common::Assignment* result_ass = NULL;
2212 for (size_t i = 0, num = imp->get_imports_size(); i < num; ++i) {
2213 const ImpMod* im = imp->get_impmod(i);
2214 const Identifier& im_id = im->get_modid();
2215 const string& im_name = im_id.get_name();
2216 if (r_modid->get_name() == im_name) {
2217 has_impmod_with_name = true;
2218 vector<ImpMod> tempusedImpMods;
2219 ReferenceChain* referencechain = new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
2220 Common::Assignment *t_ass = im->get_imported_def(*modid, *r_id, p_ref, referencechain, tempusedImpMods);
2221 referencechain->reset();
2222 delete referencechain;
2223
2224 if (t_ass != NULL) {
2225 Ttcn::Module *ttcn_m = static_cast<Ttcn::Module*>(im->get_mod());
2226 if (!ttcn_m->is_visible(*modid, t_ass->get_visibility())) {
2227 t_ass = NULL;
2228 }
2229
2230 if (t_ass != NULL) {
2231 if (result_ass == NULL) {
2232 result_ass = t_ass;
2233 } else if(result_ass != t_ass) {
2234 p_ref->error(
2235 "It is not possible to resolve the reference unambigously"
2236 ", as it can be resolved to `%s' and to `%s'",
2237 result_ass->get_fullname().c_str(), t_ass->get_fullname().c_str());
2238 }
2239 }
2240 }
2241 tempusedImpMods.clear();
2242 }
2243 }
2244 if (result_ass) return result_ass;
2245
2246 if (has_impmod_with_name) {
2247 p_ref->error("There is no definition with name `%s' visible from "
2248 "module `%s'", r_id->get_dispname().c_str(),
2249 r_modid->get_dispname().c_str());
2250 } else {
2251 if (modules->has_mod_withId(*r_modid)) {
2252 Common::Module *m = modules->get_mod_byId(*r_modid);
2253 if (m->get_asss()->has_ass_withId(*r_id)) {
2254 p_ref->error("Definition with name `%s' is not imported from "
2255 "module `%s'", r_id->get_dispname().c_str(),
2256 r_modid->get_dispname().c_str());
2257 } else {
2258 p_ref->error("There is no definition with name `%s' in "
2259 "module `%s'", r_id->get_dispname().c_str(),
2260 r_modid->get_dispname().c_str());
2261 }
2262 } else {
2263 p_ref->error("There is no module with name `%s'",
2264 r_modid->get_dispname().c_str());
2265 }
2266 return 0;
2267 }
2268 } else {
2269 // the reference points to the own module
2270 if (asss->has_local_ass_withId(*r_id)) {
2271 return asss->get_local_ass_byId(*r_id);
2272 } else {
2273 p_ref->error("There is no definition with name `%s' in "
2274 "module `%s'", r_id->get_dispname().c_str(),
2275 r_modid->get_dispname().c_str());
2276 }
2277 }
2278 } else {
2279 // no module name is given in the reference
2280 if (asss->has_local_ass_withId(*r_id)) {
2281 return asss->get_local_ass_byId(*r_id);
2282 } else {
2283 // the reference was not found locally -> look at the import list
2284 Common::Assignment *t_result = NULL, *t_ass = NULL;
2285 for (size_t i = 0, num = imp->get_imports_size(); i < num; ++i) {
2286 const ImpMod* im = imp->get_impmod(i);
2287
2288 vector<ImpMod> tempusedImpMods;
2289 ReferenceChain* referencechain = new ReferenceChain(this, "NEW IMPORT REFERNCECHAIN");
2290 t_ass = im->get_imported_def(*modid, *r_id, p_ref, referencechain, tempusedImpMods);
2291 referencechain->reset();
2292
2293 delete referencechain;
2294 if (t_ass != NULL) {
2295 Ttcn::Module *ttcn_m = static_cast<Ttcn::Module*>(im->get_mod());
2296 if (!ttcn_m->is_visible(*modid, t_ass->get_visibility())) {
2297 t_ass = NULL;
2298 }
2299
2300 if (t_ass != NULL) {
2301 if (t_result == NULL) {
2302 t_result = t_ass;
2303 } else if(t_result != t_ass) {
2304 p_ref->error(
2305 "It is not possible to resolve the reference unambigously"
2306 ", as it can be resolved to `%s' and to `%s'",
2307 t_result->get_fullname().c_str(), t_ass->get_fullname().c_str());
2308 }
2309 }
2310 }
2311 tempusedImpMods.clear();
2312 }
2313
2314 if (t_result) return t_result;
2315
2316 p_ref->error("There is no local or imported definition with name `%s'"
2317 ,r_id->get_dispname().c_str());
2318 }
2319 }
2320 return 0;
2321 }
2322
2323 bool Module::is_valid_moduleid(const Identifier& p_id)
2324 {
2325 // The identifier represents the current module
2326 if (p_id.get_name() == modid->get_name()) return true;
2327 // The identifier represents a module imported in the current module
2328 if(imp->has_impmod_withId(p_id)) return true;
2329 return false;
2330 }
2331
2332 Common::Assignments *Module::get_asss()
2333 {
2334 return asss;
2335 }
2336
2337 bool Module::exports_sym(const Identifier&)
2338 {
2339 FATAL_ERROR("Ttcn::Module::exports_sym()");
2340 return true;
2341 }
2342
2343 Type *Module::get_address_type()
2344 {
2345 Identifier address_id(Identifier::ID_TTCN, string("address"));
2346 // return NULL if address type is not defined
2347 if (!asss->has_local_ass_withId(address_id)) return 0;
2348 Common::Assignment *t_ass = asss->get_local_ass_byId(address_id);
2349 if (t_ass->get_asstype() != Common::Assignment::A_TYPE)
2350 FATAL_ERROR("Module::get_address_type(): address is not a type");
2351 return t_ass->get_Type();
2352 }
2353
2354 void Module::chk_imp(ReferenceChain& refch, vector<Common::Module>& moduleStack)
2355 {
2356 if (imp_checked) return;
2357 const string& module_name = modid->get_dispname();
2358
2359 Error_Context backup;
2360 Error_Context cntxt(this, "In TTCN-3 module `%s'", module_name.c_str());
2361 imp->chk_imp(refch, moduleStack);
2362 imp_checked = true;
2363 asss->chk_uniq();
2364 collect_visible_mods();
2365 }
2366
2367 void Module::chk()
2368 {
2369 DEBUG(1, "Checking TTCN-3 module `%s'", modid->get_dispname().c_str());
2370 Error_Context cntxt(this, "In TTCN-3 module `%s'",
2371 modid->get_dispname().c_str());
2372 if (w_attrib_path) {
2373 w_attrib_path->chk_global_attrib();
2374 w_attrib_path->chk_no_qualif();
2375
2376 // Check "extension" attributes in the module's "with" statement
2377 MultiWithAttrib *multi = w_attrib_path->get_with_attr();
2378 if (multi) for (size_t i = 0; i < multi->get_nof_elements(); ++i) {
2379 const SingleWithAttrib *single = multi->get_element(i);
2380 if (single->get_attribKeyword() != SingleWithAttrib::AT_EXTENSION) continue;
2381 // Parse the extension attribute
2382 // We circumvent parse_extattributes() in coding_attrib_p.y because
2383 // it processes all attributes in the "with" statement and
2384 // doesn't allow the removal on a case-by-case basis.
2385 extatrs = 0;
2386 init_coding_attrib_lex(single->get_attribSpec());
2387 int result = coding_attrib_parse();// 0=OK, 1=error, 2=out of memory
2388 cleanup_coding_attrib_lex();
2389 if (result != 0) {
2390 delete extatrs;
2391 extatrs = 0;
2392 continue;
2393 }
2394
2395 const size_t num_parsed = extatrs->size();
2396 for (size_t a = 0; a < num_parsed; ++a) {
2397 Ttcn::ExtensionAttribute& ex = extatrs->get(0);
2398
2399 switch (ex.get_type()) {
2400 case Ttcn::ExtensionAttribute::VERSION_TEMPLATE:
2401 case Ttcn::ExtensionAttribute::VERSION: {
2402 char* act_product_number;
2403 unsigned int act_suffix, act_rel, act_patch, act_build;
2404 char* extra_junk;
2405 (void)ex.get_id(act_product_number, act_suffix, act_rel, act_patch, act_build, extra_junk);
2406
2407 if (release != UINT_MAX) {
2408 ex.error("Duplicate 'version' attribute");
2409 }
2410 else {
2411 product_number = mcopystr(act_product_number);
2412 suffix = act_suffix;
2413 release = act_rel;
2414 patch = act_patch;
2415 build = act_build;
2416 extra = mcopystr(extra_junk);
2417 }
2418 // Avoid propagating the attribute needlessly
2419 multi->delete_element(i--);
2420 single = 0;
2421 break; }
2422
2423 case Ttcn::ExtensionAttribute::REQUIRES: {
2424 // Imports have already been checked
2425 char* exp_product_number;
2426 unsigned int exp_suffix, exp_rel, exp_patch, exp_build;
2427 char* exp_extra;
2428 Common::Identifier *req_id = ex.get_id(exp_product_number,
2429 exp_suffix, exp_rel, exp_patch, exp_build, exp_extra);
2430 // We own req_id
2431 if (imp->has_impmod_withId(*req_id)) {
2432 Common::Module* m = modules->get_mod_byId(*req_id);
2433 if (m->product_number == NULL && exp_product_number != NULL) {
2434 ex.error("Module '%s' requires module '%s' of product %s"
2435 ", but it is not specified",
2436 this->modid->get_dispname().c_str(), req_id->get_dispname().c_str(),
2437 exp_product_number);
2438 multi->delete_element(i--);
2439 single = 0;
2440 break;
2441 } else if (exp_product_number == NULL &&
2442 m->product_number != NULL && strcmp(m->product_number, "") > 0){
2443 ex.warning("Module '%s' requires module '%s' of any product"
2444 ", while it specifies '%s'",
2445 this->modid->get_dispname().c_str(),
2446 req_id->get_dispname().c_str(), m->product_number);
2447 } else if (m->product_number != NULL && exp_product_number != NULL
2448 && 0 != strcmp(m->product_number, exp_product_number)) {
2449 char *req_product_identifier =
2450 get_product_identifier(exp_product_number,
2451 exp_suffix, exp_rel, exp_patch, exp_build);
2452 char *mod_product_identifier =
2453 get_product_identifier(m->product_number,
2454 m->suffix, m->release, m->patch, m->build);
2455
2456 ex.error("Module '%s' requires version %s of module"
2457 " '%s', but only %s is available",
2458 this->modid->get_dispname().c_str(), req_product_identifier,
2459 req_id->get_dispname().c_str(), mod_product_identifier);
2460 Free(req_product_identifier);
2461 Free(mod_product_identifier);
2462 multi->delete_element(i--);
2463 single = 0;
2464 break;
2465 }
2466 // different suffixes are always incompatible
2467 // unless the special version number is used
2468 if (m->suffix != exp_suffix && (m->suffix != UINT_MAX)) {
2469 char *req_product_identifier =
2470 get_product_identifier(exp_product_number,exp_suffix, exp_rel, exp_patch, exp_build);
2471 char *mod_product_identifier =
2472 get_product_identifier(m->product_number,
2473 m->suffix, m->release, m->patch, m->build);
2474
2475 ex.error("Module '%s' requires version %s of module"
2476 " '%s', but only %s is available",
2477 this->modid->get_dispname().c_str(), req_product_identifier,
2478 req_id->get_dispname().c_str(), mod_product_identifier);
2479 Free(req_product_identifier);
2480 Free(mod_product_identifier);
2481 multi->delete_element(i--);
2482 single = 0;
2483 break;
2484 }
2485 if ( m->release < exp_rel
2486 ||(m->release== exp_rel && m->patch < exp_patch)
2487 ||(m->patch == exp_patch && m->build < exp_build)) {
2488 char *mod_bld_str = buildstr(m->build);
2489 char *exp_bld_str = buildstr(exp_build);
2490 if (mod_bld_str==0 || exp_bld_str==0) FATAL_ERROR(
2491 "Ttcn::Module::chk() invalid build number");
2492 ex.error("Module '%s' requires version R%u%c%s of module"
2493 " '%s', but only R%u%c%s is available",
2494 this->modid->get_dispname().c_str(),
2495 exp_rel, eri(exp_patch), exp_bld_str,
2496 req_id->get_dispname().c_str(),
2497 m->release, eri(m->patch), mod_bld_str);
2498 Free(exp_bld_str);
2499 Free(mod_bld_str);
2500 }
2501 } else {
2502 single->error("No imported module named '%s'",
2503 req_id->get_dispname().c_str());
2504 }
2505 multi->delete_element(i--);
2506 single = 0;
2507 break; }
2508
2509 case Ttcn::ExtensionAttribute::REQ_TITAN: {
2510 char* exp_product_number;
2511 unsigned int exp_suffix, exp_minor, exp_patch, exp_build;
2512 char* exp_extra;
2513 (void)ex.get_id(exp_product_number, exp_suffix, exp_minor, exp_patch, exp_build, exp_extra);
2514 if (exp_product_number != NULL && strcmp(exp_product_number,"CRL 113 200") != 0) {
2515 ex.error("This module needs to be compiled with TITAN, but "
2516 " product number %s is not TITAN"
2517 , exp_product_number);
2518 }
2519 if (0 == exp_suffix) {
2520 exp_suffix = 1; // previous version number format did not list the suffix part
2521 }
2522 // TTCN3_MAJOR is always 1
2523 int expected_version = exp_suffix * 1000000
2524 + exp_minor * 10000 + exp_patch * 100 + exp_build;
2525 if (expected_version > TTCN3_VERSION_MONOTONE) {
2526 char *exp_product_identifier =
2527 get_product_identifier(exp_product_number, exp_suffix, exp_minor, exp_patch, exp_build);
2528 ex.error("This module needs to be compiled with TITAN version"
2529 " %s or higher; version %s detected"
2530 , exp_product_identifier, PRODUCT_NUMBER);
2531 Free(exp_product_identifier);
2532 }
2533 multi->delete_element(i--);
2534 single = 0;
2535 break; }
2536 case Ttcn::ExtensionAttribute::PRINTING: {
2537 ex.error("Attribute 'printing' not allowed at module level");
2538 multi->delete_element(i--);
2539 single = 0;
2540 break;
2541 }
2542
2543 default:
2544 // Let everything else propagate into the module.
2545 // Extension attributes in the module's "with" statement
2546 // may be impractical, but not outright erroneous.
2547 break;
2548 } // switch
2549 } // next a
2550 delete extatrs;
2551 } // next i
2552 }
2553 chk_friends();
2554 chk_groups();
2555 asss->chk_uniq();
2556 asss->chk();
2557 if (controlpart) controlpart->chk();
2558 if (control_ns && !*control_ns) { // set but empty
2559 error("Invalid URI value for control namespace");
2560 }
2561 if (control_ns_prefix && !*control_ns_prefix) { // set but empty
2562 error("Empty NCName for the control namespace prefix is not allowed");
2563 }
2564 // TODO proper URI and NCName validation
2565 }
2566
2567 void Module::chk_friends()
2568 {
2569 map<string, FriendMod> friends_m;
2570
2571 for(size_t i = 0; i < friendmods_v.size(); i++)
2572 {
2573 FriendMod* temp_friend = friendmods_v[i];
2574 const Identifier& friend_id = temp_friend->get_modid();
2575 const string& friend_name = friend_id.get_name();
2576 if(friends_m.has_key(friend_name))
2577 {
2578 temp_friend->error("Duplicate friend module with name `%s'",
2579 friend_id.get_dispname().c_str());
2580 friends_m[friend_name]->note("Friend module `%s' is already defined here",
2581 friend_id.get_dispname().c_str());
2582 } else {
2583 friends_m.add(friend_name, temp_friend);
2584 }
2585
2586 friendmods_v[i]->chk();
2587 }
2588
2589 friends_m.clear();
2590 }
2591
2592 /** \todo revise */
2593 void Module::chk_groups()
2594 {
2595 map<string,Common::Assignment> ass_m;
2596
2597 for(size_t i = 0; i < asss->get_nof_asss(); i++)
2598 {
2599 Common::Assignment *temp_ass = asss->get_ass_byIndex(i);
2600 if(!temp_ass->get_parent_group())
2601 {
2602 const string& ass_name = temp_ass->get_id().get_name();
2603 if (!ass_m.has_key(ass_name)) ass_m.add(ass_name, temp_ass);
2604 }
2605 }
2606
2607 for(size_t i = 0; i < group_v.size(); i++)
2608 {
2609 const Group* group = group_v[i];
2610 const Identifier& group_id = group->get_id();
2611 const string& group_name = group_id.get_name();
2612 if(ass_m.has_key(group_name))
2613 {
2614 group->error("Group name `%s' clashes with a definition",
a38c6d4c 2615 group_id.get_dispname().c_str());
970ed795 2616 ass_m[group_name]->note("Definition of `%s' is here",
a38c6d4c 2617 group_id.get_dispname().c_str());
970ed795
EL
2618 }
2619 if(group_m.has_key(group_name))
2620 {
2621 group->error("Duplicate group with name `%s'",
a38c6d4c 2622 group_id.get_dispname().c_str());
970ed795 2623 group_m[group_name]->note("Group `%s' is already defined here",
a38c6d4c 2624 group_id.get_dispname().c_str());
970ed795
EL
2625 }else{
2626 group_m.add(group_name,group_v[i]);
2627 }
2628 }
2629
2630 ass_m.clear();
2631
2632 for(size_t i = 0; i < group_v.size(); i++)
2633 {
2634 group_v[i]->chk();
2635 }
2636 }
2637
2638 void Module::get_imported_mods(module_set_t& p_imported_mods)
2639 {
2640 imp->get_imported_mods(p_imported_mods);
2641 }
2642
2643 void Module::generate_code_internal(CodeGenHelper& cgh) {
2644 imp->generate_code(cgh);
2645 asss->generate_code(cgh);
2646 if (controlpart)
2647 controlpart->generate_code(cgh.get_outputstruct(modid->get_ttcnname()), this);
2648 }
2649
2650 RunsOnScope *Module::get_runs_on_scope(Type *comptype)
2651 {
2652 RunsOnScope *ret_val = new RunsOnScope(comptype);
2653 runs_on_scopes.add(ret_val);
2654 ret_val->set_parent_scope(asss);
2655 ret_val->chk_uniq();
2656 return ret_val;
2657 }
2658
2659
2660 void Module::dump(unsigned level) const
2661 {
2662 DEBUG(level, "TTCN-3 module: %s", modid->get_dispname().c_str());
2663 level++;
2664 if(imp) imp->dump(level);
2665 if(asss) asss->dump(level);
2666
2667 for(size_t i = 0; i < group_v.size(); i++)
2668 {
2669 group_v[i]->dump(level);
2670 }
2671
2672 if(controlpart) controlpart->dump(level);
2673
2674 if (w_attrib_path) {
2675 MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
2676 if (attrib) {
a38c6d4c 2677 DEBUG(level, "Module Attributes:");
2678 attrib->dump(level + 1);
970ed795
EL
2679 }
2680 }
2681 }
2682
2683 void Module::set_language_spec(const char *p_language_spec)
2684 {
2685 if (language_spec) FATAL_ERROR("Module::set_language_spec()");
2686 if (p_language_spec) language_spec = new string(p_language_spec);
2687 }
2688
2689 void Module::add_ass(Definition* p_ass)
2690 {
2691 asss->add_ass(p_ass);
2692 }
2693
2694 void Module::add_impmod(ImpMod *p_impmod)
2695 {
2696 imp->add_impmod(p_impmod);
2697 }
2698
2699 void Module::add_controlpart(ControlPart* p_controlpart)
2700 {
2701 if (!p_controlpart || controlpart) FATAL_ERROR("Module::add_controlpart()");
2702 controlpart = p_controlpart;
2703 controlpart->set_my_scope(asss);
2704 }
2705
2706 void Module::set_with_attr(MultiWithAttrib* p_attrib)
2707 {
2708 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2709 w_attrib_path->set_with_attr(p_attrib);
2710 }
2711
2712 WithAttribPath* Module::get_attrib_path()
2713 {
2714 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2715 return w_attrib_path;
2716 }
2717
2718 void Module::set_parent_path(WithAttribPath* p_path)
2719 {
2720 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2721 w_attrib_path->set_parent(p_path);
2722 }
2723
2724 bool Module::is_visible(const Identifier& id, visibility_t visibility){
2725
2726 if (visibility== PUBLIC) {
2727 return true;
2728 }
2729 if (visibility== FRIEND) {
2730 for (size_t i = 0; i < friendmods_v.size(); i++) {
2731 if (friendmods_v[i]->get_modid() == id) {
2732 return true;
2733 }
2734 }
2735 }
2736 return false;
2737 }
2738
af710487 2739 void Module::generate_json_schema(JSON_Tokenizer& json, map<Type*, JSON_Tokenizer>& json_refs)
970ed795
EL
2740 {
2741 // add a new property for this module
af710487 2742 json.put_next_token(JSON_TOKEN_NAME, modid->get_ttcnname().c_str());
970ed795
EL
2743
2744 // add type definitions into an object
2745 json.put_next_token(JSON_TOKEN_OBJECT_START);
2746
af710487 2747 // cycle through each type, generate schema segment and reference when needed
970ed795
EL
2748 for (size_t i = 0; i < asss->get_nof_asss(); ++i) {
2749 Def_Type* def = dynamic_cast<Def_Type*>(asss->get_ass_byIndex(i));
2750 if (def != NULL) {
af710487 2751 Type* t = def->get_Type();
2752 if (t->has_encoding(Type::CT_JSON)) {
2753 // insert type's schema segment
2754 t->generate_json_schema(json, false, false);
2755
2756 if (json_refs_for_all_types && !json_refs.has_key(t)) {
2757 // create JSON schema reference for the type
2758 JSON_Tokenizer* json_ref = new JSON_Tokenizer;
2759 json_refs.add(t, json_ref);
2760 t->generate_json_schema_ref(*json_ref);
2761 }
2762 }
970ed795
EL
2763 }
2764 }
2765
2766 // end of type definitions
2767 json.put_next_token(JSON_TOKEN_OBJECT_END);
af710487 2768
2769 // insert function data
970ed795
EL
2770 for (size_t i = 0; i < asss->get_nof_asss(); ++i) {
2771 Def_ExtFunction* def = dynamic_cast<Def_ExtFunction*>(asss->get_ass_byIndex(i));
2772 if (def != NULL) {
2773 def->generate_json_schema_ref(json_refs);
2774 }
2775 }
2776 }
2777
2778 // =================================
2779 // ===== Definition
2780 // =================================
2781
2782 string Definition::get_genname() const
2783 {
2784 if (!genname.empty()) return genname;
2785 else return id->get_name();
2786 }
2787
2788 namedbool Definition::has_implicit_omit_attr() const {
2789 if (w_attrib_path) {
2790 const vector<SingleWithAttrib>& real_attribs =
2791 w_attrib_path->get_real_attrib();
2792 for (size_t in = real_attribs.size(); in > 0; in--) {
2793 if (SingleWithAttrib::AT_OPTIONAL ==
2794 real_attribs[in-1]->get_attribKeyword()) {
2795 if ("implicit omit" ==
2796 real_attribs[in-1]->get_attribSpec().get_spec()) {
2797 return IMPLICIT_OMIT;
2798 } else if ("explicit omit" ==
2799 real_attribs[in-1]->get_attribSpec().get_spec()) {
2800 return NOT_IMPLICIT_OMIT;
2801 } // error reporting for other values is in chk_global_attrib
2802 }
2803 }
2804 }
2805 return NOT_IMPLICIT_OMIT;
2806 }
2807
2808 Definition::~Definition()
2809 {
2810 delete w_attrib_path;
2811 delete erroneous_attrs;
2812 }
2813
2814 void Definition::set_fullname(const string& p_fullname)
2815 {
2816 Common::Assignment::set_fullname(p_fullname);
2817 if (w_attrib_path) w_attrib_path->set_fullname(p_fullname + ".<attribpath>");
2818 if (erroneous_attrs) erroneous_attrs->set_fullname(p_fullname+".<erroneous_attributes>");
2819 }
2820
2821 bool Definition::is_local() const
2822 {
2823 if (!my_scope) FATAL_ERROR("Definition::is_local()");
2824 for (Scope *scope = my_scope; scope; scope = scope->get_parent_scope()) {
2825 if (dynamic_cast<StatementBlock*>(scope)) return true;
2826 }
2827 return false;
2828 }
2829
2830 bool Definition::chk_identical(Definition *)
2831 {
2832 FATAL_ERROR("Definition::chk_identical()");
2833 return false;
2834 }
2835
2836 void Definition::chk_erroneous_attr()
2837 {
2838 if (!w_attrib_path) return;
2839 const Ttcn::MultiWithAttrib* attribs = w_attrib_path->get_local_attrib();
2840 if (!attribs) return;
2841 for (size_t i = 0; i < attribs->get_nof_elements(); i++) {
2842 const Ttcn::SingleWithAttrib* act_attr = attribs->get_element(i);
2843 if (act_attr->get_attribKeyword()==Ttcn::SingleWithAttrib::AT_ERRONEOUS) {
2844 if (!use_runtime_2) {
2845 error("`erroneous' attributes can be used only with the Function Test Runtime");
2846 note("If you need negative testing use the -R flag when generating the makefile");
2847 return;
2848 }
2849 size_t nof_qualifiers = act_attr->get_attribQualifiers() ? act_attr->get_attribQualifiers()->get_nof_qualifiers() : 0;
2850 dynamic_array<Type*> refd_type_array(nof_qualifiers); // only the qualifiers pointing to existing fields will be added to erroneous_attrs objects
2851 if (nof_qualifiers==0) {
2852 act_attr->error("At least one qualifier must be specified for the `erroneous' attribute");
2853 } else {
2854 // check if qualifiers point to existing fields
2855 for (size_t qi=0; qi<nof_qualifiers; qi++) {
2856 Qualifier* act_qual = const_cast<Qualifier*>(act_attr->get_attribQualifiers()->get_qualifier(qi));
2857 act_qual->set_my_scope(get_my_scope());
2858 Type* field_type = get_Type()->get_field_type(act_qual, Type::EXPECTED_CONSTANT);
2859 if (field_type) {
2860 dynamic_array<size_t> subrefs_array;
2861 dynamic_array<Type*> type_array;
2862 bool valid_indexes = get_Type()->get_subrefs_as_array(act_qual, subrefs_array, type_array);
2863 if (!valid_indexes) field_type = NULL;
2864 if (act_qual->refers_to_string_element()) {
2865 act_qual->error("Reference to a string element cannot be used in this context");
2866 field_type = NULL;
2867 }
2868 }
2869 refd_type_array.add(field_type);
2870 }
2871 }
2872 // parse the attr. spec.
2873 ErroneousAttributeSpec* err_attr_spec = ttcn3_parse_erroneous_attr_spec_string(
2874 act_attr->get_attribSpec().get_spec().c_str(), act_attr->get_attribSpec());
2875 if (err_attr_spec) {
2876 if (!erroneous_attrs) erroneous_attrs = new ErroneousAttributes(get_Type());
2877 // attr.spec will be owned by erroneous_attrs object
2878 erroneous_attrs->add_spec(err_attr_spec);
2879 err_attr_spec->set_fullname(get_fullname());
2880 err_attr_spec->set_my_scope(get_my_scope());
2881 err_attr_spec->chk();
2882 // create qualifier - err.attr.spec. pairs
2883 for (size_t qi=0; qi<nof_qualifiers; qi++) {
2884 if (refd_type_array[qi] && (err_attr_spec->get_indicator()!=ErroneousAttributeSpec::I_INVALID)) {
2885 erroneous_attrs->add_pair(act_attr->get_attribQualifiers()->get_qualifier(qi), err_attr_spec);
2886 }
2887 }
2888 }
2889 }
2890 }
2891 if (erroneous_attrs) erroneous_attrs->chk();
2892 }
2893
2894 char* Definition::generate_code_str(char *str)
2895 {
2896 FATAL_ERROR("Definition::generate_code_str()");
2897 return str;
2898 }
2899
2900 void Definition::ilt_generate_code(ILT *)
2901 {
2902 FATAL_ERROR("Definition::ilt_generate_code()");
2903 }
2904
2905 char *Definition::generate_code_init_comp(char *str, Definition *)
2906 {
2907 FATAL_ERROR("Definition::generate_code_init_comp()");
2908 return str;
2909 }
2910
2911 void Definition::set_with_attr(MultiWithAttrib* p_attrib)
2912 {
2913 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2914 w_attrib_path->set_with_attr(p_attrib);
2915 }
2916
2917 WithAttribPath* Definition::get_attrib_path()
2918 {
2919 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2920 return w_attrib_path;
2921 }
2922
2923 void Definition::set_parent_path(WithAttribPath* p_path)
2924 {
2925 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2926 w_attrib_path->set_parent(p_path);
2927 }
2928
2929 void Definition::set_parent_group(Group* p_group)
2930 {
2931 if(parentgroup) // there would be a leak!
2932 FATAL_ERROR("Definition::set_parent_group()");
2933 parentgroup = p_group;
2934 }
2935
2936 Group* Definition::get_parent_group()
2937 {
2938 return parentgroup;
2939 }
2940
2941 void Definition::dump_internal(unsigned level) const
2942 {
2943 DEBUG(level, "Move along, nothing to see here");
2944 }
2945
2946 void Definition::dump(unsigned level) const
2947 {
2948 dump_internal(level);
2949 if (w_attrib_path) {
2950 MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
2951 if (attrib) {
a38c6d4c 2952 DEBUG(level + 1, "Definition Attributes:");
2953 attrib->dump(level + 2);
970ed795
EL
2954 }
2955 }
2956 if (erroneous_attrs) erroneous_attrs->dump(level+1);
2957 }
2958
2959 // =================================
2960 // ===== Def_Type
2961 // =================================
2962
2963 Def_Type::Def_Type(Identifier *p_id, Type *p_type)
2964 : Definition(A_TYPE, p_id), type(p_type)
2965 {
2966 if(!p_type) FATAL_ERROR("Ttcn::Def_Type::Def_Type()");
2967 type->set_ownertype(Type::OT_TYPE_DEF, this);
2968 }
2969
2970 Def_Type::~Def_Type()
2971 {
2972 delete type;
2973 }
2974
2975 Def_Type *Def_Type::clone() const
2976 {
2977 FATAL_ERROR("Def_Type::clone");
2978 }
2979
2980 void Def_Type::set_fullname(const string& p_fullname)
2981 {
2982 Definition::set_fullname(p_fullname);
2983 type->set_fullname(p_fullname);
2984 }
2985
2986 void Def_Type::set_my_scope(Scope *p_scope)
2987 {
2988 bridgeScope.set_parent_scope(p_scope);
2989 bridgeScope.set_scopeMacro_name(id->get_dispname());
2990
2991 Definition::set_my_scope(&bridgeScope);
2992 type->set_my_scope(&bridgeScope);
2993
2994 }
2995
2996 Setting *Def_Type::get_Setting()
2997 {
2998 return get_Type();
2999 }
3000
3001 Type *Def_Type::get_Type()
3002 {
3003 chk();
3004 return type;
3005 }
3006
3007 void Def_Type::chk()
3008 {
3009 if (checked) return;
3010 checked = true;
3011 Error_Context cntxt(this, "In %s definition `%s'",
3012 type->get_typetype() == Type::T_SIGNATURE ? "signature" : "type",
3013 id->get_dispname().c_str());
3014 type->set_genname(get_genname());
3015 if (!semantic_check_only && type->get_typetype() == Type::T_COMPONENT) {
3016 // the prefix of embedded definitions must be set before the checking
3017 type->get_CompBody()->set_genname(get_genname() + "_component_");
3018 }
3019
3020 while (w_attrib_path) { // not a loop, but we can _break_ out of it
3021 w_attrib_path->chk_global_attrib();
3022 w_attrib_path->chk_no_qualif();
3023 if (type->get_typetype() != Type::T_ANYTYPE) break;
3024 // This is the anytype; it must be empty (we're about to add the fields)
3025 if (type->get_nof_comps() > 0) FATAL_ERROR("Def_Type::chk");
3026
3027 Ttcn::ExtensionAttributes *extattrs = parse_extattributes(w_attrib_path);
3028 if (extattrs == 0) break; // NULL means parsing error
3029
3030 size_t num_atrs = extattrs->size();
3031 for (size_t k = 0; k < num_atrs; ++k) {
3032 ExtensionAttribute &ea = extattrs->get(k);
3033 switch (ea.get_type()) {
3034 case ExtensionAttribute::ANYTYPELIST: {
3035 Types *anytypes = ea.get_types();
3036 // List of types to be converted into fields for the anytype.
3037 // Make sure scope is set on all types in the list.
3038 anytypes->set_my_scope(get_my_scope());
3039
3040 // Convert the list of types into field names for the anytype
3041 for (size_t i=0; i < anytypes->get_nof_types(); ++i) {
3042 Type *t = anytypes->extract_type_byIndex(i);
3043 // we are now the owner of the Type.
3044 if (t->get_typetype()==Type::T_ERROR) { // should we give up?
3045 delete t;
3046 continue;
3047 }
3048
3049 string field_name;
3050 const char* btn = Type::get_typename_builtin(t->get_typetype());
3051 if (btn) {
3052 field_name = btn;
3053 }
3054 else if (t->get_typetype() == Type::T_REFD) {
3055 // Extract the identifier
3056 Common::Reference *ref = t->get_Reference();
3057 Ttcn::Reference *tref = dynamic_cast<Ttcn::Reference*>(ref);
3058 if (!tref) FATAL_ERROR("Def_Type::chk, wrong kind of reference");
3059 const Common::Identifier *modid = tref->get_modid();
3060 if (modid) {
3061 ea.error("Qualified name '%s' cannot be added to the anytype",
3062 tref->get_dispname().c_str());
3063 delete t;
3064 continue;
3065 }
3066 field_name = tref->get_id()->get_ttcnname();
3067 }
3068 else {
3069 // Can't happen here
3070 FATAL_ERROR("Unexpected type %d", t->get_typetype());
3071 }
3072
3073 const string& at_field = anytype_field(field_name);
3074 Identifier *field_id = new Identifier(Identifier::ID_TTCN, at_field);
3075 CompField *cf = new CompField(field_id, t, false, 0);
3076 cf->set_location(ea);
3077 cf->set_fullname(get_fullname());
3078 type->add_comp(cf);
3079 } // next i
3080 delete anytypes;
3081 break; }
3082 default:
3083 w_attrib_path->get_with_attr()->error("Type def can only have anytype");
3084 break;
3085 } // switch
3086 } // next attribute
3087
3088 delete extattrs;
3089 break; // do not loop
3090 }
3091
3092 // Now we can check the type
3093 type->chk();
3094 type->chk_constructor_name(*id);
3095 if (id->get_ttcnname() == "address") type->chk_address();
3096 ReferenceChain refch(type, "While checking embedded recursions");
3097 type->chk_recursions(refch);
3098
3099 if (type->get_typetype()==Type::T_FUNCTION
3100 ||type->get_typetype()==Type::T_ALTSTEP
3101 ||type->get_typetype()==Type::T_TESTCASE) {
3102 // TR 922. This is a function/altstep/testcase reference.
3103 // Set this definition as the definition for the formal parameters.
3104 type->get_fat_parameters()->set_my_def(this);
3105 }
3106 }
3107
3108 void Def_Type::generate_code(output_struct *target, bool)
3109 {
3110 type->generate_code(target);
3111 if (type->get_typetype() == Type::T_COMPONENT) {
3112 // the C++ equivalents of embedded component element definitions must be
3113 // generated from outside Type::generate_code() because the function can
3114 // call itself recursively and create invalid (overlapped) initializer
3115 // sequences
3116 type->get_CompBody()->generate_code(target);
3117 }
3118 }
3119
3120 void Def_Type::generate_code(CodeGenHelper& cgh) {
3121 type->generate_code(cgh.get_outputstruct(get_Type()));
3122 if (type->get_typetype() == Type::T_COMPONENT) {
3123 // the C++ equivalents of embedded component element definitions must be
3124 // generated from outside Type::generate_code() because the function can
3125 // call itself recursively and create invalid (overlapped) initializer
3126 // sequences
3127 type->get_CompBody()->generate_code(cgh.get_current_outputstruct());
3128 }
3129 cgh.finalize_generation(get_Type());
3130 }
3131
3132
3133 void Def_Type::dump_internal(unsigned level) const
3134 {
3135 DEBUG(level, "Type def: %s @ %p", id->get_dispname().c_str(), (const void*)this);
3136 type->dump(level + 1);
3137 }
3138
3139 void Def_Type::set_with_attr(MultiWithAttrib* p_attrib)
3140 {
3141 if (!w_attrib_path) {
3142 w_attrib_path = new WithAttribPath();
3143 type->set_parent_path(w_attrib_path);
3144 }
3145 type->set_with_attr(p_attrib);
3146 }
3147
3148 WithAttribPath* Def_Type::get_attrib_path()
3149 {
3150 if (!w_attrib_path) {
3151 w_attrib_path = new WithAttribPath();
3152 type->set_parent_path(w_attrib_path);
3153 }
3154 return w_attrib_path;
3155 }
3156
3157 void Def_Type::set_parent_path(WithAttribPath* p_path)
3158 {
3159 if (!w_attrib_path) {
3160 w_attrib_path = new WithAttribPath();
3161 type->set_parent_path(w_attrib_path);
3162 }
3163 w_attrib_path->set_parent(p_path);
3164 }
970ed795
EL
3165
3166 // =================================
3167 // ===== Def_Const
3168 // =================================
3169
3170 Def_Const::Def_Const(Identifier *p_id, Type *p_type, Value *p_value)
3171 : Definition(A_CONST, p_id)
3172 {
3173 if (!p_type || !p_value) FATAL_ERROR("Ttcn::Def_Const::Def_Const()");
3174 type=p_type;
3175 type->set_ownertype(Type::OT_CONST_DEF, this);
3176 value=p_value;
3177 value_under_check=false;
3178 }
3179
3180 Def_Const::~Def_Const()
3181 {
3182 delete type;
3183 delete value;
3184 }
3185
3186 Def_Const *Def_Const::clone() const
3187 {
3188 FATAL_ERROR("Def_Const::clone");
3189 }
3190
3191 void Def_Const::set_fullname(const string& p_fullname)
3192 {
3193 Definition::set_fullname(p_fullname);
3194 type->set_fullname(p_fullname + ".<type>");
3195 value->set_fullname(p_fullname);
3196 }
3197
3198 void Def_Const::set_my_scope(Scope *p_scope)
3199 {
3200 Definition::set_my_scope(p_scope);
3201 type->set_my_scope(p_scope);
3202 value->set_my_scope(p_scope);
3203 }
3204
3205 Setting *Def_Const::get_Setting()
3206 {
3207 return get_Value();
3208 }
3209
3210 Type *Def_Const::get_Type()
3211 {
3212 chk();
3213 return type;
3214 }
3215
3216
3217 Value *Def_Const::get_Value()
3218 {
3219 chk();
3220 return value;
3221 }
3222
3223 void Def_Const::chk()
3224 {
3225 if(checked) {
3226 if (value_under_check) {
3227 error("Circular reference in constant definition `%s'",
3228 id->get_dispname().c_str());
3229 value_under_check = false; // only report the error once for this definition
3230 }
3231 return;
3232 }
3233 Error_Context cntxt(this, "In constant definition `%s'",
3234 id->get_dispname().c_str());
3235 type->set_genname(_T_, get_genname());
3236 type->chk();
3237 value->set_my_governor(type);
3238 type->chk_this_value_ref(value);
3239 checked=true;
3240 if (w_attrib_path) {
3241 w_attrib_path->chk_global_attrib(true);
3242 switch (type->get_type_refd_last()->get_typetype_ttcn3()) {
3243 case Type::T_SEQ_T:
3244 case Type::T_SET_T:
3245 case Type::T_CHOICE_T:
3246 // These types may have qualified attributes
3247 break;
3248 case Type::T_SEQOF: case Type::T_SETOF:
3249 break;
3250 default:
3251 w_attrib_path->chk_no_qualif();
3252 break;
3253 }
3254 }
3255 Type *t = type->get_type_refd_last();
3256 switch (t->get_typetype()) {
3257 case Type::T_PORT:
3258 error("Constant cannot be defined for port type `%s'",
3259 t->get_fullname().c_str());
3260 break;
3261 case Type::T_SIGNATURE:
3262 error("Constant cannot be defined for signature `%s'",
3263 t->get_fullname().c_str());
3264 break;
3265 default:
3266 value_under_check = true;
3267 type->chk_this_value(value, 0, Type::EXPECTED_CONSTANT, INCOMPLETE_ALLOWED,
3268 OMIT_NOT_ALLOWED, SUB_CHK, has_implicit_omit_attr());
3269 value_under_check = false;
3270 chk_erroneous_attr();
3271 if (erroneous_attrs) value->set_err_descr(erroneous_attrs->get_err_descr());
3272 {
3273 ReferenceChain refch(type, "While checking embedded recursions");
3274 value->chk_recursions(refch);
3275 }
3276 break;
3277 }
3278 if (!semantic_check_only) {
3279 value->set_genname_prefix("const_");
3280 value->set_genname_recursive(get_genname());
3281 value->set_code_section(GovernedSimple::CS_PRE_INIT);
3282 }
3283 }
3284
3285 bool Def_Const::chk_identical(Definition *p_def)
3286 {
3287 chk();
3288 p_def->chk();
3289 if (p_def->get_asstype() != A_CONST) {
3290 const char *dispname_str = id->get_dispname().c_str();
3291 error("Local definition `%s' is a constant, but the definition "
a38c6d4c 3292 "inherited from component type `%s' is a %s", dispname_str,
970ed795
EL
3293 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
3294 p_def->note("The inherited definition of `%s' is here", dispname_str);
3295 return false;
3296 }
3297 Def_Const *p_def_const = dynamic_cast<Def_Const*>(p_def);
3298 if (!p_def_const) FATAL_ERROR("Def_Const::chk_identical()");
3299 if (!type->is_identical(p_def_const->type)) {
3300 const char *dispname_str = id->get_dispname().c_str();
3301 type->error("Local constant `%s' has type `%s', but the constant "
a38c6d4c 3302 "inherited from component type `%s' has type `%s'", dispname_str,
3303 type->get_typename().c_str(),
970ed795 3304 p_def_const->get_my_scope()->get_fullname().c_str(),
a38c6d4c 3305 p_def_const->type->get_typename().c_str());
970ed795
EL
3306 p_def_const->note("The inherited constant `%s' is here", dispname_str);
3307 return false;
3308 } else if (!(*value == *p_def_const->value)) {
3309 const char *dispname_str = id->get_dispname().c_str();
3310 value->error("Local constant `%s' and the constant inherited from "
a38c6d4c 3311 "component type `%s' have different values", dispname_str,
970ed795
EL
3312 p_def_const->get_my_scope()->get_fullname().c_str());
3313 p_def_const->note("The inherited constant `%s' is here", dispname_str);
3314 return false;
3315 } else return true;
3316 }
3317
3318 void Def_Const::generate_code(output_struct *target, bool)
3319 {
3320 type->generate_code(target);
3321 const_def cdef;
3322 Code::init_cdef(&cdef);
3323 type->generate_code_object(&cdef, value);
3324 cdef.init = update_location_object(cdef.init);
3325 cdef.init = value->generate_code_init(cdef.init,
3326 value->get_lhs_name().c_str());
3327 Code::merge_cdef(target, &cdef);
3328 Code::free_cdef(&cdef);
3329 }
3330
3331 void Def_Const::generate_code(Common::CodeGenHelper& cgh) {
3332 // constant definitions always go to its containing module
3333 generate_code(cgh.get_current_outputstruct());
3334 }
3335
3336 char *Def_Const::generate_code_str(char *str)
3337 {
3338 const string& t_genname = get_genname();
3339 const char *genname_str = t_genname.c_str();
3340 if (value->has_single_expr()) {
3341 // the value can be represented by a single C++ expression
3342 // the object is initialized by the constructor
3343 str = mputprintf(str, "%s %s(%s);\n",
3344 type->get_genname_value(my_scope).c_str(), genname_str,
3345 value->get_single_expr().c_str());
3346 } else {
3347 // use the default constructor
3348 str = mputprintf(str, "%s %s;\n",
3349 type->get_genname_value(my_scope).c_str(), genname_str);
3350 // the value is assigned using subsequent statements
3351 str = value->generate_code_init(str, genname_str);
3352 }
3353 return str;
3354 }
3355
3356 void Def_Const::ilt_generate_code(ILT *ilt)
3357 {
3358 const string& t_genname = get_genname();
3359 const char *genname_str = t_genname.c_str();
3360 char*& def=ilt->get_out_def();
3361 char*& init=ilt->get_out_branches();
3362 def = mputprintf(def, "%s %s;\n", type->get_genname_value(my_scope).c_str(),
3363 genname_str);
3364 init = value->generate_code_init(init, genname_str);
3365 }
3366
3367 char *Def_Const::generate_code_init_comp(char *str, Definition *)
3368 {
3369 /* This function actually does nothing as \a this and \a base_defn are
3370 * exactly the same. */
3371 return str;
3372 }
3373
3374 void Def_Const::dump_internal(unsigned level) const
3375 {
3376 DEBUG(level, "Constant: %s @%p", id->get_dispname().c_str(), (const void*)this);
3377 type->dump(level + 1);
3378 value->dump(level + 1);
3379 }
3380
3381 // =================================
3382 // ===== Def_ExtConst
3383 // =================================
3384
3385 Def_ExtConst::Def_ExtConst(Identifier *p_id, Type *p_type)
3386 : Definition(A_EXT_CONST, p_id)
3387 {
3388 if (!p_type) FATAL_ERROR("Ttcn::Def_ExtConst::Def_ExtConst()");
3389 type = p_type;
3390 type->set_ownertype(Type::OT_CONST_DEF, this);
3391 }
3392
3393 Def_ExtConst::~Def_ExtConst()
3394 {
3395 delete type;
3396 }
3397
3398 Def_ExtConst *Def_ExtConst::clone() const
3399 {
3400 FATAL_ERROR("Def_ExtConst::clone");
3401 }
3402
3403 void Def_ExtConst::set_fullname(const string& p_fullname)
3404 {
3405 Definition::set_fullname(p_fullname);
3406 type->set_fullname(p_fullname + ".<type>");
3407 }
3408
3409 void Def_ExtConst::set_my_scope(Scope *p_scope)
3410 {
3411 Definition::set_my_scope(p_scope);
3412 type->set_my_scope(p_scope);
3413 }
3414
3415 Type *Def_ExtConst::get_Type()
3416 {
3417 chk();
3418 return type;
3419 }
3420
3421 void Def_ExtConst::chk()
3422 {
3423 if(checked) return;
3424 Error_Context cntxt(this, "In external constant definition `%s'",
3425 id->get_dispname().c_str());
3426 type->set_genname(_T_, get_genname());
3427 type->chk();
3428 checked=true;
3429 Type *t = type->get_type_refd_last();
3430 switch (t->get_typetype()) {
3431 case Type::T_PORT:
3432 error("External constant cannot be defined for port type `%s'",
3433 t->get_fullname().c_str());
3434 break;
3435 case Type::T_SIGNATURE:
3436 error("External constant cannot be defined for signature `%s'",
3437 t->get_fullname().c_str());
3438 break;
3439 default:
3440 break;
3441 }
3442 if (w_attrib_path) {
3443 w_attrib_path->chk_global_attrib();
3444 switch (type->get_type_refd_last()->get_typetype()) {
3445 case Type::T_SEQ_T:
3446 case Type::T_SET_T:
3447 case Type::T_CHOICE_T:
3448 // These types may have qualified attributes
3449 break;
3450 case Type::T_SEQOF: case Type::T_SETOF:
3451 break;
3452 default:
3453 w_attrib_path->chk_no_qualif();
3454 break;
3455 }
3456 }
3457 }
3458
3459 void Def_ExtConst::generate_code(output_struct *target, bool)
3460 {
3461 type->generate_code(target);
3462 target->header.global_vars = mputprintf(target->header.global_vars,
3463 "extern const %s& %s;\n", type->get_genname_value(my_scope).c_str(),
3464 get_genname().c_str());
3465 }
3466
3467 void Def_ExtConst::generate_code(Common::CodeGenHelper& cgh) {
3468 // constant definitions always go to its containing module
3469 generate_code(cgh.get_current_outputstruct());
3470 }
3471
3472 void Def_ExtConst::dump_internal(unsigned level) const
3473 {
3474 DEBUG(level, "External constant: %s @ %p", id->get_dispname().c_str(), (const void*)this);
3475 type->dump(level + 1);
3476 }
3477
3478 // =================================
3479 // ===== Def_Modulepar
3480 // =================================
3481
3482 Def_Modulepar::Def_Modulepar(Identifier *p_id, Type *p_type, Value *p_defval)
3483 : Definition(A_MODULEPAR, p_id)
3484 {
3485 if (!p_type) FATAL_ERROR("Ttcn::Def_Modulepar::Def_Modulepar()");
3486 type = p_type;
3487 type->set_ownertype(Type::OT_MODPAR_DEF, this);
3488 def_value = p_defval;
3489 }
3490
3491 Def_Modulepar::~Def_Modulepar()
3492 {
3493 delete type;
3494 delete def_value;
3495 }
3496
3497 Def_Modulepar* Def_Modulepar::clone() const
3498 {
3499 FATAL_ERROR("Def_Modulepar::clone");
3500 }
3501
3502 void Def_Modulepar::set_fullname(const string& p_fullname)
3503 {
3504 Definition::set_fullname(p_fullname);
3505 type->set_fullname(p_fullname + ".<type>");
3506 if (def_value) def_value->set_fullname(p_fullname + ".<default_value>");
3507 }
3508
3509 void Def_Modulepar::set_my_scope(Scope *p_scope)
3510 {
3511 Definition::set_my_scope(p_scope);
3512 type->set_my_scope(p_scope);
3513 if (def_value) def_value->set_my_scope(p_scope);
3514 }
3515
3516 Type *Def_Modulepar::get_Type()
3517 {
3518 chk();
3519 return type;
3520 }
3521
3522 void Def_Modulepar::chk()
3523 {
3524 if(checked) return;
3525 Error_Context cntxt(this, "In module parameter definition `%s'",
3526 id->get_dispname().c_str());
3527 type->set_genname(_T_, get_genname());
3528 type->chk();
3529 if (w_attrib_path) {
3530 w_attrib_path->chk_global_attrib();
3531 switch (type->get_type_refd_last()->get_typetype()) {
3532 case Type::T_SEQ_T:
3533 case Type::T_SET_T:
3534 case Type::T_CHOICE_T:
3535 // These types may have qualified attributes
3536 break;
3537 case Type::T_SEQOF: case Type::T_SETOF:
3538 break;
3539 default:
3540 w_attrib_path->chk_no_qualif();
3541 break;
3542 }
3543 }
3544 map<Type*,void> type_chain;
3545 map<Type::typetype_t, void> not_allowed;
3546 not_allowed.add(Type::T_PORT, 0);
970ed795
EL
3547 Type *t = type->get_type_refd_last();
3548 // if the type is valid the original will be returned
3549 Type::typetype_t tt = t->search_for_not_allowed_type(type_chain, not_allowed);
3550 type_chain.clear();
3551 not_allowed.clear();
3552 switch (tt) {
3553 case Type::T_PORT:
3554 error("Type of module parameter cannot be or embed port type `%s'",
3555 t->get_fullname().c_str());
3556 break;
3557 case Type::T_SIGNATURE:
3558 error("Type of module parameter cannot be signature `%s'",
3559 t->get_fullname().c_str());
3560 break;
970ed795
EL
3561 case Type::T_FUNCTION:
3562 case Type::T_ALTSTEP:
3563 case Type::T_TESTCASE:
3564 if (t->get_fat_runs_on_self()) {
3565 error("Type of module parameter cannot be of function reference type"
3566 " `%s' which has runs on self clause", t->get_fullname().c_str());
3567 }
3568 break;
3569 default:
3570#if defined(MINGW)
3571 checked = true;
3572#else
3573 if (def_value) {
3574 Error_Context cntxt2(def_value, "In default value");
3575 def_value->set_my_governor(type);
3576 type->chk_this_value_ref(def_value);
3577 checked = true;
3578 type->chk_this_value(def_value, 0, Type::EXPECTED_CONSTANT, INCOMPLETE_ALLOWED,
3579 OMIT_NOT_ALLOWED, SUB_CHK, has_implicit_omit_attr());
3580 if (!semantic_check_only) {
3581 def_value->set_genname_prefix("modulepar_");
3582 def_value->set_genname_recursive(get_genname());
3583 def_value->set_code_section(GovernedSimple::CS_PRE_INIT);
3584 }
3585 } else checked = true;
3586#endif
3587 break;
3588 }
3589 }
3590
3591 void Def_Modulepar::generate_code(output_struct *target, bool)
3592 {
3593 type->generate_code(target);
3594 const_def cdef;
3595 Code::init_cdef(&cdef);
3596 const string& t_genname = get_genname();
3597 const char *name = t_genname.c_str();
3598 type->generate_code_object(&cdef, my_scope, t_genname, "modulepar_", false);
3599 if (def_value) {
3600 cdef.init = update_location_object(cdef.init);
3601 cdef.init = def_value->generate_code_init(cdef.init, def_value->get_lhs_name().c_str());
3602 }
3603 Code::merge_cdef(target, &cdef);
3604 Code::free_cdef(&cdef);
3605
3606 if (has_implicit_omit_attr()) {
3607 target->functions.post_init = mputprintf(target->functions.post_init,
3608 "modulepar_%s.set_implicit_omit();\n", name);
3609 }
3610
3611 const char *dispname = id->get_dispname().c_str();
3612 target->functions.set_param = mputprintf(target->functions.set_param,
3613 "if (!strcmp(par_name, \"%s\")) {\n"
3614 "modulepar_%s.set_param(param);\n"
3615 "return TRUE;\n"
3616 "} else ", dispname, name);
3abe9331 3617 target->functions.get_param = mputprintf(target->functions.get_param,
3618 "if (!strcmp(par_name, \"%s\")) {\n"
3619 "return modulepar_%s.get_param(param_name);\n"
3620 "} else ", dispname, name);
970ed795
EL
3621
3622 if (target->functions.log_param) {
3623 // this is not the first modulepar
3624 target->functions.log_param = mputprintf(target->functions.log_param,
a38c6d4c 3625 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname);
970ed795
EL
3626 } else {
3627 // this is the first modulepar
3628 target->functions.log_param = mputprintf(target->functions.log_param,
a38c6d4c 3629 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname);
970ed795
EL
3630 }
3631 target->functions.log_param = mputprintf(target->functions.log_param,
3632 "%s.log();\n", name);
3633 }
3634
3635 void Def_Modulepar::generate_code(Common::CodeGenHelper& cgh) {
3636 // module parameter definitions always go to its containing module
3637 generate_code(cgh.get_current_outputstruct());
3638 }
3639
3640 void Def_Modulepar::dump_internal(unsigned level) const
3641 {
3642 DEBUG(level, "Module parameter: %s @ %p", id->get_dispname().c_str(), (const void*)this);
3643 type->dump(level + 1);
3644 if (def_value) def_value->dump(level + 1);
3645 else DEBUG(level + 1, "No default value");
3646 }
3647
3648 // =================================
3649 // ===== Def_Modulepar_Template
3650 // =================================
3651
3652 Def_Modulepar_Template::Def_Modulepar_Template(Identifier *p_id, Type *p_type, Template *p_deftmpl)
3653 : Definition(A_MODULEPAR_TEMP, p_id)
3654 {
3655 if (!p_type) FATAL_ERROR("Ttcn::Def_Modulepar_Template::Def_Modulepar_Template()");
3656 type = p_type;
3657 type->set_ownertype(Type::OT_MODPAR_DEF, this);
3658 def_template = p_deftmpl;
3659 }
3660
3661 Def_Modulepar_Template::~Def_Modulepar_Template()
3662 {
3663 delete type;
3664 delete def_template;
3665 }
3666
3667 Def_Modulepar_Template* Def_Modulepar_Template::clone() const
3668 {
3669 FATAL_ERROR("Def_Modulepar_Template::clone");
3670 }
3671
3672 void Def_Modulepar_Template::set_fullname(const string& p_fullname)
3673 {
3674 Definition::set_fullname(p_fullname);
3675 type->set_fullname(p_fullname + ".<type>");
3676 if (def_template) def_template->set_fullname(p_fullname + ".<default_template>");
3677 }
3678
3679 void Def_Modulepar_Template::set_my_scope(Scope *p_scope)
3680 {
3681 Definition::set_my_scope(p_scope);
3682 type->set_my_scope(p_scope);
3683 if (def_template) def_template->set_my_scope(p_scope);
3684 }
3685
3686 Type *Def_Modulepar_Template::get_Type()
3687 {
3688 chk();
3689 return type;
3690 }
3691
3692 void Def_Modulepar_Template::chk()
3693 {
3694 if(checked) return;
3695 Error_Context cntxt(this, "In template module parameter definition `%s'",
3696 id->get_dispname().c_str());
3697 if (w_attrib_path) {
3698 w_attrib_path->chk_global_attrib();
3699 switch (type->get_type_refd_last()->get_typetype()) {
3700 case Type::T_SEQ_T:
3701 case Type::T_SET_T:
3702 case Type::T_CHOICE_T:
3703 // These types may have qualified attributes
3704 break;
3705 case Type::T_SEQOF: case Type::T_SETOF:
3706 break;
3707 default:
3708 w_attrib_path->chk_no_qualif();
3709 break;
3710 }
3711 }
3712 type->set_genname(_T_, get_genname());
3713 type->chk();
3714 Type *t = type->get_type_refd_last();
3715 switch (t->get_typetype()) {
3716 case Type::T_PORT:
3717 error("Type of template module parameter cannot be port type `%s'",
3718 t->get_fullname().c_str());
3719 break;
3720 case Type::T_SIGNATURE:
3721 error("Type of template module parameter cannot be signature `%s'",
3722 t->get_fullname().c_str());
3723 break;
3724 case Type::T_FUNCTION:
3725 case Type::T_ALTSTEP:
3726 case Type::T_TESTCASE:
3727 if (t->get_fat_runs_on_self()) {
3728 error("Type of template module parameter cannot be of function reference type"
3729 " `%s' which has runs on self clause", t->get_fullname().c_str());
3730 }
3731 break;
3732 default:
3733 if (has_implicit_omit_attr()) {
3734 error("Implicit omit not supported for template module parameters");
3735 }
3736#if defined(MINGW)
3737 checked = true;
3738#else
3739 if (def_template) {
3740 Error_Context cntxt2(def_template, "In default template");
3741 def_template->set_my_governor(type);
3742 def_template->flatten(false);
3743 if (def_template->get_templatetype() == Template::CSTR_PATTERN &&
3744 type->get_type_refd_last()->get_typetype() == Type::T_USTR) {
3745 def_template->set_templatetype(Template::USTR_PATTERN);
3746 def_template->get_ustr_pattern()->set_pattern_type(
3747 PatternString::USTR_PATTERN);
3748 }
3749 type->chk_this_template_ref(def_template);
3750 checked = true;
3751 type->chk_this_template_generic(def_template, INCOMPLETE_ALLOWED,
3752 OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, has_implicit_omit_attr() ? IMPLICIT_OMIT : NOT_IMPLICIT_OMIT, 0);
3753 if (!semantic_check_only) {
3754 def_template->set_genname_prefix("modulepar_");
3755 def_template->set_genname_recursive(get_genname());
3756 def_template->set_code_section(GovernedSimple::CS_PRE_INIT);
3757 }
3758 } else checked = true;
3759#endif
3760 break;
3761 }
3762 }
3763
3764 void Def_Modulepar_Template::generate_code(output_struct *target, bool)
3765 {
3766 type->generate_code(target);
3767 const_def cdef;
3768 Code::init_cdef(&cdef);
3769 const string& t_genname = get_genname();
3770 const char *name = t_genname.c_str();
3771 type->generate_code_object(&cdef, my_scope, t_genname, "modulepar_", true);
3772 if (def_template) {
3773 cdef.init = update_location_object(cdef.init);
3774 cdef.init = def_template->generate_code_init(cdef.init, def_template->get_lhs_name().c_str());
3775 }
3776 Code::merge_cdef(target, &cdef);
3777 Code::free_cdef(&cdef);
3778
3779 if (has_implicit_omit_attr()) {
3780 FATAL_ERROR("Def_Modulepar_Template::generate_code()");
3781 }
3782
3783 const char *dispname = id->get_dispname().c_str();
3784 target->functions.set_param = mputprintf(target->functions.set_param,
3785 "if (!strcmp(par_name, \"%s\")) {\n"
3786 "modulepar_%s.set_param(param);\n"
3787 "return TRUE;\n"
3788 "} else ", dispname, name);
3abe9331 3789 target->functions.get_param = mputprintf(target->functions.get_param,
3790 "if (!strcmp(par_name, \"%s\")) {\n"
3791 "return modulepar_%s.get_param(param_name);\n"
3792 "} else ", dispname, name);
970ed795
EL
3793
3794 if (target->functions.log_param) {
3795 // this is not the first modulepar
3796 target->functions.log_param = mputprintf(target->functions.log_param,
a38c6d4c 3797 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname);
970ed795
EL
3798 } else {
3799 // this is the first modulepar
3800 target->functions.log_param = mputprintf(target->functions.log_param,
a38c6d4c 3801 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname);
970ed795
EL
3802 }
3803 target->functions.log_param = mputprintf(target->functions.log_param,
3804 "%s.log();\n", name);
3805 }
3806
3807 void Def_Modulepar_Template::generate_code(Common::CodeGenHelper& cgh) {
3808 // module parameter definitions always go to its containing module
3809 generate_code(cgh.get_current_outputstruct());
3810 }
3811
3812 void Def_Modulepar_Template::dump_internal(unsigned level) const
3813 {
3814 DEBUG(level, "Module parameter: %s @ %p", id->get_dispname().c_str(), (const void*)this);
3815 type->dump(level + 1);
3816 if (def_template) def_template->dump(level + 1);
3817 else DEBUG(level + 1, "No default template");
3818 }
3819
3820 // =================================
3821 // ===== Def_Template
3822 // =================================
3823
3824 Def_Template::Def_Template(template_restriction_t p_template_restriction,
3825 Identifier *p_id, Type *p_type, FormalParList *p_fpl,
3826 Reference *p_derived_ref, Template *p_body)
3827 : Definition(A_TEMPLATE, p_id), type(p_type), fp_list(p_fpl),
3828 derived_ref(p_derived_ref), base_template(0), recurs_deriv_checked(false),
3829 body(p_body), template_restriction(p_template_restriction),
3830 gen_restriction_check(false)
3831 {
3832 if (!p_type || !p_body) FATAL_ERROR("Ttcn::Def_Template::Def_Template()");
3833 type->set_ownertype(Type::OT_TEMPLATE_DEF, this);
3834 if (fp_list) fp_list->set_my_def(this);
3835 }
3836
3837 Def_Template::~Def_Template()
3838 {
3839 delete type;
3840 delete fp_list;
3841 delete derived_ref;
3842 delete body;
3843 }
3844
3845 Def_Template *Def_Template::clone() const
3846 {
3847 FATAL_ERROR("Def_Template::clone");
3848 }
3849
3850 void Def_Template::set_fullname(const string& p_fullname)
3851 {
3852 Definition::set_fullname(p_fullname);
3853 type->set_fullname(p_fullname + ".<type>");
3854 if (fp_list) fp_list->set_fullname(p_fullname + ".<formal_par_list>");
3855 if (derived_ref)
3856 derived_ref->set_fullname(p_fullname + ".<derived_reference>");
3857 body->set_fullname(p_fullname);
3858 }
3859
3860 void Def_Template::set_my_scope(Scope *p_scope)
3861 {
3862 bridgeScope.set_parent_scope(p_scope);
3863 bridgeScope.set_scopeMacro_name(id->get_dispname());
3864
3865 Definition::set_my_scope(&bridgeScope);
3866 type->set_my_scope(&bridgeScope);
3867 if (derived_ref) derived_ref->set_my_scope(&bridgeScope);
3868 if (fp_list) {
3869 fp_list->set_my_scope(&bridgeScope);
3870 body->set_my_scope(fp_list);
3871 } else body->set_my_scope(&bridgeScope);
3872 }
3873
3874 Setting *Def_Template::get_Setting()
3875 {
3876 return get_Template();
3877 }
3878
3879 Type *Def_Template::get_Type()
3880 {
3881 if (!checked) chk();
3882 return type;
3883 }
3884
3885 Template *Def_Template::get_Template()
3886 {
3887 if (!checked) chk();
3888 return body;
3889 }
3890
3891 FormalParList *Def_Template::get_FormalParList()
3892 {
3893 if (!checked) chk();
3894 return fp_list;
3895 }
3896
3897 void Def_Template::chk()
3898 {
3899 if (checked) return;
3900 Error_Context cntxt(this, "In template definition `%s'",
3901 id->get_dispname().c_str());
3902 const string& t_genname = get_genname();
3903 type->set_genname(_T_, t_genname);
3904 type->chk();
3905 if (w_attrib_path) {
3906 w_attrib_path->chk_global_attrib(true);
3907 switch (type->get_type_refd_last()->get_typetype_ttcn3()) {
3908 case Type::T_SEQ_T:
3909 case Type::T_SET_T:
3910 case Type::T_CHOICE_T:
3911 // These types may have qualified attributes
3912 break;
3913 case Type::T_SEQOF: case Type::T_SETOF:
3914 break;
3915 default:
3916 w_attrib_path->chk_no_qualif();
3917 break;
3918 }
3919 }
3920 if (fp_list) {
3921 chk_default();
3922 fp_list->chk(asstype);
3923 if (local_scope) error("Parameterized local template `%s' not supported",
3924 id->get_dispname().c_str());
3925 }
3926
3927 // Merge the elements of "all from" into the list
3928 body->flatten(false);
3929
3930 body->set_my_governor(type);
3931
3932 if (body->get_templatetype() == Template::CSTR_PATTERN &&
3933 type->get_type_refd_last()->get_typetype() == Type::T_USTR) {
3934 body->set_templatetype(Template::USTR_PATTERN);
3935 body->get_ustr_pattern()->set_pattern_type(PatternString::USTR_PATTERN);
3936 }
3937
3938 type->chk_this_template_ref(body);
3939 checked = true;
3940 Type *t = type->get_type_refd_last();
3941 if (t->get_typetype() == Type::T_PORT) {
3942 error("Template cannot be defined for port type `%s'",
3943 t->get_fullname().c_str());
3944 }
3945 chk_modified();
3946 chk_recursive_derivation();
3947 type->chk_this_template_generic(body, INCOMPLETE_ALLOWED, OMIT_ALLOWED,
3948 ANY_OR_OMIT_ALLOWED, SUB_CHK,
3949 has_implicit_omit_attr() ? IMPLICIT_OMIT : NOT_IMPLICIT_OMIT, 0);
3950
3951 chk_erroneous_attr();
3952 if (erroneous_attrs) body->set_err_descr(erroneous_attrs->get_err_descr());
3953
3954 {
3955 ReferenceChain refch(type, "While checking embedded recursions");
3956 body->chk_recursions(refch);
3957 }
3958 if (template_restriction!=TR_NONE) {
3959 Error_Context ec(this, "While checking template restriction `%s'",
3960 Template::get_restriction_name(template_restriction));
3961 gen_restriction_check =
3abe9331 3962 body->chk_restriction("template definition", template_restriction, body);
970ed795
EL
3963 if (fp_list && template_restriction!=TR_PRESENT) {
3964 size_t nof_fps = fp_list->get_nof_fps();
3965 for (size_t i=0; i<nof_fps; i++) {
3966 FormalPar* fp = fp_list->get_fp_byIndex(i);
3967 // if formal par is not template then skip restriction checking,
3968 // templates can have only `in' parameters
3969 if (fp->get_asstype()!=A_PAR_TEMPL_IN) continue;
3970 template_restriction_t fp_tr = fp->get_template_restriction();
3971 switch (template_restriction) {
3972 case TR_VALUE:
3973 case TR_OMIT:
3974 switch (fp_tr) {
3975 case TR_VALUE:
3976 case TR_OMIT:
3977 // allowed
3978 break;
3979 case TR_PRESENT:
3980 fp->error("Formal parameter with template restriction `%s' "
3981 "not allowed here", Template::get_restriction_name(fp_tr));
3982 break;
3983 case TR_NONE:
3984 fp->error("Formal parameter without template restriction "
3985 "not allowed here");
3986 break;
3987 default:
3988 FATAL_ERROR("Ttcn::Def_Template::chk()");
3989 }
3990 break;
3991 default:
3992 FATAL_ERROR("Ttcn::Def_Template::chk()");
3993 }
3994 }
3995 }
3996 }
3997 if (!semantic_check_only) {
3998 if (fp_list) fp_list->set_genname(t_genname);
3999 body->set_genname_prefix("template_");
4000 body->set_genname_recursive(t_genname);
4001 body->set_code_section(fp_list ? GovernedSimple::CS_INLINE :
4002 GovernedSimple::CS_POST_INIT);
4003 }
4004
4005 }
4006
4007 void Def_Template::chk_default() const
4008 {
4009 if (!fp_list) FATAL_ERROR("Def_Template::chk_default()");
4010 if (!derived_ref) {
4011 if (fp_list->has_notused_defval())
4012 fp_list->error("Only modified templates are allowed to use the not "
4013 "used symbol (`-') as the default parameter");
4014 return;
4015 }
4016 Common::Assignment *ass = derived_ref->get_refd_assignment(false);
4017 if (!ass || ass->get_asstype() != A_TEMPLATE) return; // Work locally.
4018 Def_Template *base = dynamic_cast<Def_Template *>(ass);
4019 if (!base) FATAL_ERROR("Def_Template::chk_default()");
4020 FormalParList *base_fpl = base->get_FormalParList();
4021 size_t nof_base_fps = base_fpl ? base_fpl->get_nof_fps() : 0;
4022 size_t nof_local_fps = fp_list ? fp_list->get_nof_fps() : 0;
4023 size_t min_fps = nof_base_fps;
4024 if (nof_local_fps < nof_base_fps) min_fps = nof_local_fps;
4025 for (size_t i = 0; i < min_fps; i++) {
4026 FormalPar *base_fp = base_fpl->get_fp_byIndex(i);
4027 FormalPar *local_fp = fp_list->get_fp_byIndex(i);
4028 if (local_fp->has_notused_defval()) {
4029 if (base_fp->has_defval()) {
4030 local_fp->set_defval(base_fp->get_defval());
4031 } else {
4032 local_fp->error("Not used symbol (`-') doesn't have the "
4033 "corresponding default parameter in the "
4034 "base template");
4035 }
4036 }
4037 }
4038 // Additional parameters in the derived template with using the not used
4039 // symbol. TODO: Merge the loops.
4040 for (size_t i = nof_base_fps; i < nof_local_fps; i++) {
4041 FormalPar *local_fp = fp_list->get_fp_byIndex(i);
4042 if (local_fp->has_notused_defval())
4043 local_fp->error("Not used symbol (`-') doesn't have the "
4044 "corresponding default parameter in the "
4045 "base template");
4046 }
4047 }
4048
4049 void Def_Template::chk_modified()
4050 {
4051 if (!derived_ref) return;
4052 // Do not check the (non-existent) actual parameter list of the derived
4053 // reference against the formal parameter list of the base template.
4054 // According to TTCN-3 syntax the derived reference cannot have parameters
4055 // even if the base template is parameterized.
4056 Common::Assignment *ass = derived_ref->get_refd_assignment(false);
4057 // Checking the existence and type compatibility of the base template.
4058 if (!ass) return;
4059 if (ass->get_asstype() != A_TEMPLATE) {
4060 derived_ref->error("Reference to a template was expected in the "
4061 "`modifies' definition instead of %s",
4062 ass->get_description().c_str());
4063 return;
4064 }
4065 base_template = dynamic_cast<Def_Template*>(ass);
4066 if (!base_template) FATAL_ERROR("Def_Template::chk_modified()");
4067 Type *base_type = base_template->get_Type();
4068 TypeCompatInfo info_base(my_scope->get_scope_mod(), type, base_type, true,
4069 false, true);
4070 TypeChain l_chain_base;
4071 TypeChain r_chain_base;
4072 if (!type->is_compatible(base_type, &info_base, &l_chain_base,
4073 &r_chain_base)) {
4074 if (info_base.is_subtype_error()) {
4075 type->error("%s", info_base.get_subtype_error().c_str());
4076 } else
4077 if (!info_base.is_erroneous()) {
4078 type->error("The modified template has different type than base "
4079 "template `%s': `%s' was expected instead of `%s'",
4080 ass->get_fullname().c_str(),
4081 base_type->get_typename().c_str(),
4082 type->get_typename().c_str());
4083 } else {
4084 // Always use the format string.
4085 type->error("%s", info_base.get_error_str_str().c_str());
4086 }
4087 } else {
4088 if (info_base.needs_conversion())
4089 body->set_needs_conversion();
4090 }
4091 // Check for restriction.
4092 if (Template::is_less_restrictive(base_template->get_template_restriction(),
4093 template_restriction)) {
4094 error("The template restriction is not the same or more "
4095 "restrictive as of base template `%s'", ass->get_fullname().c_str());
4096 }
4097 // Checking formal parameter lists.
4098 FormalParList *base_fpl = base_template->get_FormalParList();
4099 size_t nof_base_fps = base_fpl ? base_fpl->get_nof_fps() : 0;
4100 size_t nof_local_fps = fp_list ? fp_list->get_nof_fps() : 0;
4101 size_t min_fps;
4102 if (nof_local_fps < nof_base_fps) {
4103 error("The modified template has fewer formal parameters than base "
4104 "template `%s': at least %lu parameter%s expected instead of %lu",
4105 ass->get_fullname().c_str(), (unsigned long)nof_base_fps,
4106 nof_base_fps > 1 ? "s were" : " was", (unsigned long)nof_local_fps);
4107 min_fps = nof_local_fps;
4108 } else min_fps = nof_base_fps;
4109
4110 for (size_t i = 0; i < min_fps; i++) {
4111 FormalPar *base_fp = base_fpl->get_fp_byIndex(i);
4112 FormalPar *local_fp = fp_list->get_fp_byIndex(i);
4113 Error_Context cntxt(local_fp, "In formal parameter #%lu",
4114 (unsigned long)(i + 1));
4115 // Check for parameter kind equivalence (value or template).
4116 if (base_fp->get_asstype() != local_fp->get_asstype())
4117 local_fp->error("The kind of parameter is not the same as in base "
4118 "template `%s': %s was expected instead of %s",
4119 ass->get_fullname().c_str(), base_fp->get_assname(),
4120 local_fp->get_assname());
4121 // Check for type compatibility.
4122 Type *base_fp_type = base_fp->get_Type();
4123 Type *local_fp_type = local_fp->get_Type();
4124 TypeCompatInfo info_par(my_scope->get_scope_mod(), base_fp_type,
4125 local_fp_type, true, false);
4126 TypeChain l_chain_par;
4127 TypeChain r_chain_par;
4128 if (!base_fp_type->is_compatible(local_fp_type, &info_par, &l_chain_par,
4129 &r_chain_par)) {
4130 if (info_par.is_subtype_error()) {
4131 local_fp_type->error("%s", info_par.get_subtype_error().c_str());
4132 } else
4133 if (!info_par.is_erroneous()) {
4134 local_fp_type->error("The type of parameter is not the same as in "
4135 "base template `%s': `%s' was expected instead "
4136 "of `%s'",
4137 ass->get_fullname().c_str(),
4138 base_fp_type->get_typename().c_str(),
4139 local_fp_type->get_typename().c_str());
4140 } else {
4141 local_fp_type->error("%s", info_par.get_error_str_str().c_str());
4142 }
4143 } else {
4144 if (info_par.needs_conversion())
4145 body->set_needs_conversion();
4146 }
4147 // Check for name equivalence.
4148 const Identifier& base_fp_id = base_fp->get_id();
4149 const Identifier& local_fp_id = local_fp->get_id();
4150 if (!(base_fp_id == local_fp_id))
4151 local_fp->error("The name of parameter is not the same as in base "
4152 "template `%s': `%s' was expected instead of `%s'",
4153 ass->get_fullname().c_str(),
4154 base_fp_id.get_dispname().c_str(),
4155 local_fp_id.get_dispname().c_str());
4156 // Check for restrictions: the derived must be same or more restrictive.
4157 if (base_fp->get_asstype()==local_fp->get_asstype() &&
4158 Template::is_less_restrictive(base_fp->get_template_restriction(),
4159 local_fp->get_template_restriction())) {
4160 local_fp->error("The restriction of parameter is not the same or more "
4161 "restrictive as in base template `%s'", ass->get_fullname().c_str());
4162 }
4163 }
4164 // Set the pointer to the body of base template.
4165 body->set_base_template(base_template->get_Template());
4166 }
4167
4168 void Def_Template::chk_recursive_derivation()
4169 {
4170 if (recurs_deriv_checked) return;
4171 if (base_template) {
4172 ReferenceChain refch(this, "While checking the chain of base templates");
4173 refch.add(get_fullname());
4174 for (Def_Template *iter = base_template; iter; iter = iter->base_template)
4175 {
4176 if (iter->recurs_deriv_checked) break;
4177 else if (refch.add(iter->get_fullname()))
a38c6d4c 4178 iter->recurs_deriv_checked = true;
4179 else break;
970ed795
EL
4180 }
4181 }
4182 recurs_deriv_checked = true;
4183 }
4184
4185 void Def_Template::generate_code(output_struct *target, bool)
4186 {
4187 type->generate_code(target);
4188 if (fp_list) {
4189 // Parameterized template. Generate code for a function which returns
4190 // a $(genname)_template and has the appropriate parameters.
4191 const string& t_genname = get_genname();
4192 const char *template_name = t_genname.c_str();
4193 const char *template_dispname = id->get_dispname().c_str();
4194 const string& type_genname = type->get_genname_template(my_scope);
4195 const char *type_genname_str = type_genname.c_str();
4196 char *formal_par_list = fp_list->generate_code(memptystr());
4197 fp_list->generate_code_defval(target);
4198 target->header.function_prototypes =
4199 mputprintf(target->header.function_prototypes,
a38c6d4c 4200 "extern %s %s(%s);\n",
4201 type_genname_str, template_name, formal_par_list);
970ed795
EL
4202 char *function_body = mprintf("%s %s(%s)\n"
4203 "{\n", type_genname_str, template_name, formal_par_list);
4204 function_body = create_location_object(function_body, "TEMPLATE",
4205 template_dispname);
4206 if (base_template) {
4207 // modified template
4208 function_body = mputprintf(function_body, "%s ret_val(%s",
a38c6d4c 4209 type_genname_str,
4210 base_template->get_genname_from_scope(my_scope).c_str());
4211 if (base_template->fp_list) {
4212 // the base template is also parameterized
4213 function_body = mputc(function_body, '(');
4214 size_t nof_base_pars = base_template->fp_list->get_nof_fps();
4215 for (size_t i = 0; i < nof_base_pars; i++) {
4216 if (i > 0) function_body = mputstr(function_body, ", ");
4217 function_body = mputstr(function_body,
4218 fp_list->get_fp_byIndex(i)->get_id().get_name().c_str());
4219 }
4220 function_body = mputc(function_body, ')');
4221 }
4222 function_body = mputstr(function_body, ");\n");
970ed795
EL
4223 } else {
4224 // simple template
4225 function_body = mputprintf(function_body, "%s ret_val;\n",
a38c6d4c 4226 type_genname_str);
970ed795
EL
4227 }
4228 if (erroneous_attrs && erroneous_attrs->get_err_descr()) {
4229 function_body = erroneous_attrs->get_err_descr()->
4230 generate_code_str(function_body, string("ret_val"));
4231 }
4232 function_body = body->generate_code_init(function_body, "ret_val");
4233 if (template_restriction!=TR_NONE && gen_restriction_check)
4234 function_body = Template::generate_restriction_check_code(function_body,
4235 "ret_val", template_restriction);
4236 function_body = mputstr(function_body, "return ret_val;\n"
4237 "}\n\n");
4238 target->source.function_bodies =
4239 mputstr(target->source.function_bodies, function_body);
4240 Free(formal_par_list);
4241 Free(function_body);
4242 } else {
4243 // non-parameterized template
4244 const_def cdef;
4245 Code::init_cdef(&cdef);
4246 type->generate_code_object(&cdef, body);
4247 cdef.init = update_location_object(cdef.init);
4248 if (base_template) {
4249 // modified template
4250 if (base_template->my_scope->get_scope_mod_gen() ==
4251 my_scope->get_scope_mod_gen()) {
4252 // if the base template is in the same module its body has to be
4253 // initialized first
4254 cdef.init = base_template->body->generate_code_init(cdef.init,
4255 base_template->body->get_lhs_name().c_str());
4256 }
4257 if (use_runtime_2 && body->get_needs_conversion()) {
4258 Type *body_type = body->get_my_governor()->get_type_refd_last();
4259 Type *base_type = base_template->body->get_my_governor()
4260 ->get_type_refd_last();
4261 if (!body_type || !base_type)
4262 FATAL_ERROR("Def_Template::generate_code()");
4263 const string& tmp_id = body->get_temporary_id();
4264 const char *tmp_id_str = tmp_id.c_str();
4265 // base template initialization
4266 cdef.init = mputprintf(cdef.init,
4267 "%s %s;\n"
4268 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4269 "and `%s' are not compatible at run-time\");\n"
4270 "%s = %s;\n",
4271 body_type->get_genname_template(my_scope).c_str(), tmp_id_str,
4272 TypeConv::get_conv_func(base_type, body_type, my_scope
4273 ->get_scope_mod()).c_str(), tmp_id_str, base_template
4274 ->get_genname_from_scope(my_scope).c_str(), base_type
4275 ->get_typename().c_str(), body_type->get_typename().c_str(),
4276 body->get_lhs_name().c_str(), tmp_id_str);
4277 } else {
4278 cdef.init = mputprintf(cdef.init, "%s = %s;\n",
4279 body->get_lhs_name().c_str(),
4280 base_template->get_genname_from_scope(my_scope).c_str());
4281 }
4282 }
4283 if (use_runtime_2 && TypeConv::needs_conv_refd(body))
4284 cdef.init = TypeConv::gen_conv_code_refd(cdef.init,
4285 body->get_lhs_name().c_str(), body);
4286 else
4287 cdef.init = body->generate_code_init(cdef.init,
4288 body->get_lhs_name().c_str());
4289 if (template_restriction != TR_NONE && gen_restriction_check)
4290 cdef.init = Template::generate_restriction_check_code(cdef.init,
4291 body->get_lhs_name().c_str(), template_restriction);
4292 target->header.global_vars = mputstr(target->header.global_vars,
4293 cdef.decl);
4294 target->source.global_vars = mputstr(target->source.global_vars,
4295 cdef.def);
4296 target->functions.post_init = mputstr(target->functions.post_init,
4297 cdef.init);
4298 Code::free_cdef(&cdef);
4299 }
4300 }
4301
4302 void Def_Template::generate_code(Common::CodeGenHelper& cgh) {
4303 generate_code(cgh.get_outputstruct(this));
4304 }
4305
4306 char *Def_Template::generate_code_str(char *str)
4307 {
4308 const string& t_genname = get_genname();
4309 const char *genname_str = t_genname.c_str();
4310 const string& type_genname = type->get_genname_template(my_scope);
4311 const char *type_genname_str = type_genname.c_str();
4312 if (fp_list) {
4313 const char *dispname_str = id->get_dispname().c_str();
4314 NOTSUPP("Code generation for parameterized local template `%s'",
4315 dispname_str);
4316 str = mputprintf(str, "/* NOT SUPPORTED: template %s */\n",
4317 dispname_str);
4318 } else {
4319 if (base_template) {
4320 // non-parameterized modified template
4321 if (use_runtime_2 && body->get_needs_conversion()) {
4322 Type *body_type = body->get_my_governor()->get_type_refd_last();
4323 Type *base_type = base_template->body->get_my_governor()
4324 ->get_type_refd_last();
4325 if (!body_type || !base_type)
4326 FATAL_ERROR("Def_Template::generate_code_str()");
4327 const string& tmp_id = body->get_temporary_id();
4328 const char *tmp_id_str = tmp_id.c_str();
4329 str = mputprintf(str,
4330 "%s %s;\n"
4331 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4332 "and `%s' are not compatible at run-time\");\n"
4333 "%s %s(%s);\n",
4334 body_type->get_genname_template(my_scope).c_str(), tmp_id_str,
4335 TypeConv::get_conv_func(base_type, body_type, my_scope
4336 ->get_scope_mod()).c_str(), tmp_id_str, base_template
4337 ->get_genname_from_scope(my_scope).c_str(), base_type
4338 ->get_typename().c_str(), body_type->get_typename().c_str(),
4339 type_genname_str, genname_str, tmp_id_str);
4340 } else {
4341 // the object is initialized from the base template by the
4342 // constructor
4343 str = mputprintf(str, "%s %s(%s);\n", type_genname_str, genname_str,
4344 base_template->get_genname_from_scope(my_scope).c_str());
4345 }
4346 // the modified body is assigned in the subsequent statements
4347 str = body->generate_code_init(str, genname_str);
4348 } else {
4349 // non-parameterized non-modified template
4350 if (body->has_single_expr()) {
4351 // the object is initialized by the constructor
4352 str = mputprintf(str, "%s %s(%s);\n", type_genname_str,
4353 genname_str, body->get_single_expr(false).c_str());
4354 } else {
4355 // the default constructor is used
4356 str = mputprintf(str, "%s %s;\n", type_genname_str, genname_str);
4357 // the body is assigned in the subsequent statements
4358 str = body->generate_code_init(str, genname_str);
4359 }
4360 }
4361 if (template_restriction != TR_NONE && gen_restriction_check)
4362 str = Template::generate_restriction_check_code(str, genname_str,
4363 template_restriction);
4364 }
4365 return str;
4366 }
4367
4368 void Def_Template::ilt_generate_code(ILT *ilt)
4369 {
4370 const string& t_genname = get_genname();
4371 const char *genname_str = t_genname.c_str();
4372 char*& def=ilt->get_out_def();
4373 char*& init=ilt->get_out_branches();
4374 if (fp_list) {
4375 const char *dispname_str = id->get_dispname().c_str();
4376 NOTSUPP("Code generation for parameterized local template `%s'",
a38c6d4c 4377 dispname_str);
970ed795
EL
4378 def = mputprintf(def, "/* NOT SUPPORTED: template %s */\n", dispname_str);
4379 init = mputprintf(init, "/* NOT SUPPORTED: template %s */\n",
a38c6d4c 4380 dispname_str);
970ed795
EL
4381 } else {
4382 // non-parameterized template
4383 // use the default constructor for initialization
4384 def = mputprintf(def, "%s %s;\n",
a38c6d4c 4385 type->get_genname_template(my_scope).c_str(), genname_str);
970ed795 4386 if (base_template) {
a38c6d4c 4387 // copy the base template with an assignment
4388 init = mputprintf(init, "%s = %s;\n", genname_str,
4389 base_template->get_genname_from_scope(my_scope).c_str());
970ed795
EL
4390 }
4391 // finally assign the body
4392 init = body->generate_code_init(init, genname_str);
4393 if (template_restriction!=TR_NONE && gen_restriction_check)
4394 init = Template::generate_restriction_check_code(init, genname_str,
4395 template_restriction);
4396 }
4397 }
4398
4399 void Def_Template::dump_internal(unsigned level) const
4400 {
4401 DEBUG(level, "Template: %s", id->get_dispname().c_str());
4402 if (fp_list) fp_list->dump(level + 1);
4403 if (derived_ref)
4404 DEBUG(level + 1, "modifies: %s", derived_ref->get_dispname().c_str());
4405 if (template_restriction!=TR_NONE)
4406 DEBUG(level + 1, "restriction: %s",
4407 Template::get_restriction_name(template_restriction));
4408 type->dump(level + 1);
4409 body->dump(level + 1);
4410 }
4411
4412 // =================================
4413 // ===== Def_Var
4414 // =================================
4415
4416 Def_Var::Def_Var(Identifier *p_id, Type *p_type, Value *p_initial_value)
4417 : Definition(A_VAR, p_id), type(p_type), initial_value(p_initial_value)
4418 {
4419 if (!p_type) FATAL_ERROR("Ttcn::Def_Var::Def_Var()");
4420 type->set_ownertype(Type::OT_VAR_DEF, this);
4421 }
4422
4423 Def_Var::~Def_Var()
4424 {
4425 delete type;
4426 delete initial_value;
4427 }
4428
4429 Def_Var *Def_Var::clone() const
4430 {
4431 FATAL_ERROR("Def_Var::clone");
4432 }
4433
4434 void Def_Var::set_fullname(const string& p_fullname)
4435 {
4436 Definition::set_fullname(p_fullname);
4437 type->set_fullname(p_fullname + ".<type>");
4438 if (initial_value)
4439 initial_value->set_fullname(p_fullname + ".<initial_value>");
4440 }
4441
4442 void Def_Var::set_my_scope(Scope *p_scope)
4443 {
4444 Definition::set_my_scope(p_scope);
4445 type->set_my_scope(p_scope);
4446 if (initial_value) initial_value->set_my_scope(p_scope);
4447 }
4448
4449 Type *Def_Var::get_Type()
4450 {
4451 chk();
4452 return type;
4453 }
4454
4455 void Def_Var::chk()
4456 {
4457 if(checked) return;
4458 Error_Context cntxt(this, "In variable definition `%s'",
4459 id->get_dispname().c_str());
4460 type->set_genname(_T_, get_genname());
4461 type->chk();
4462 checked = true;
4463 Type *t = type->get_type_refd_last();
4464 switch (t->get_typetype()) {
4465 case Type::T_PORT:
4466 error("Variable cannot be defined for port type `%s'",
4467 t->get_fullname().c_str());
4468 break;
4469 case Type::T_SIGNATURE:
4470 error("Variable cannot be defined for signature `%s'",
4471 t->get_fullname().c_str());
4472 break;
4473 default:
4474 if (initial_value) {
4475 initial_value->set_my_governor(type);
4476 type->chk_this_value_ref(initial_value);
4477 type->chk_this_value(initial_value, this, is_local() ?
4478 Type::EXPECTED_DYNAMIC_VALUE : Type::EXPECTED_STATIC_VALUE,
4479 INCOMPLETE_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK);
4480 if (!semantic_check_only) {
4481 initial_value->set_genname_recursive(get_genname());
4482 initial_value->set_code_section(GovernedSimple::CS_INLINE);
4483 }
4484 }
4485 break;
4486 }
4487
4488 if (w_attrib_path) {
4489 w_attrib_path->chk_global_attrib();
4490 w_attrib_path->chk_no_qualif();
4491 }
4492 }
4493
4494 bool Def_Var::chk_identical(Definition *p_def)
4495 {
4496 chk();
4497 p_def->chk();
4498 if (p_def->get_asstype() != A_VAR) {
4499 const char *dispname_str = id->get_dispname().c_str();
4500 error("Local definition `%s' is a variable, but the definition "
a38c6d4c 4501 "inherited from component type `%s' is a %s", dispname_str,
970ed795
EL
4502 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
4503 p_def->note("The inherited definition of `%s' is here", dispname_str);
4504 return false;
4505 }
4506 Def_Var *p_def_var = dynamic_cast<Def_Var*>(p_def);
4507 if (!p_def_var) FATAL_ERROR("Def_Var::chk_identical()");
4508 if (!type->is_identical(p_def_var->type)) {
4509 const char *dispname_str = id->get_dispname().c_str();
4510 type->error("Local variable `%s' has type `%s', but the variable "
a38c6d4c 4511 "inherited from component type `%s' has type `%s'", dispname_str,
4512 type->get_typename().c_str(),
970ed795 4513 p_def_var->get_my_scope()->get_fullname().c_str(),
a38c6d4c 4514 p_def_var->type->get_typename().c_str());
970ed795
EL
4515 p_def_var->note("The inherited variable `%s' is here", dispname_str);
4516 return false;
4517 }
4518 if (initial_value) {
4519 if (p_def_var->initial_value) {
4520 if (!initial_value->is_unfoldable() &&
a38c6d4c 4521 !p_def_var->initial_value->is_unfoldable() &&
4522 !(*initial_value == *p_def_var->initial_value)) {
4523 const char *dispname_str = id->get_dispname().c_str();
4524 initial_value->warning("Local variable `%s' and the variable "
4525 "inherited from component type `%s' have different initial values",
4526 dispname_str, p_def_var->get_my_scope()->get_fullname().c_str());
4527 p_def_var->note("The inherited variable `%s' is here", dispname_str);
4528 }
970ed795 4529 } else {
a38c6d4c 4530 const char *dispname_str = id->get_dispname().c_str();
4531 initial_value->warning("Local variable `%s' has initial value, but "
4532 "the variable inherited from component type `%s' does not",
4533 dispname_str, p_def_var->get_my_scope()->get_fullname().c_str());
4534 p_def_var->note("The inherited variable `%s' is here", dispname_str);
970ed795
EL
4535 }
4536 } else if (p_def_var->initial_value) {
4537 const char *dispname_str = id->get_dispname().c_str();
4538 warning("Local variable `%s' does not have initial value, but the "
a38c6d4c 4539 "variable inherited from component type `%s' has", dispname_str,
4540 p_def_var->get_my_scope()->get_fullname().c_str());
970ed795
EL
4541 p_def_var->note("The inherited variable `%s' is here", dispname_str);
4542 }
4543 return true;
4544 }
4545
4546 void Def_Var::generate_code(output_struct *target, bool clean_up)
4547 {
4548 type->generate_code(target);
4549 const_def cdef;
4550 Code::init_cdef(&cdef);
4551 type->generate_code_object(&cdef, my_scope, get_genname(), 0, false);
4552 Code::merge_cdef(target, &cdef);
4553 Code::free_cdef(&cdef);
4554 if (initial_value) {
4555 target->functions.init_comp =
4556 initial_value->generate_code_init(target->functions.init_comp,
4557 initial_value->get_lhs_name().c_str());
4558 } else if (clean_up) { // No initial value.
4559 target->functions.init_comp = mputprintf(target->functions.init_comp,
4560 "%s.clean_up();\n", get_genname().c_str());
4561 }
4562 }
4563
4564 void Def_Var::generate_code(CodeGenHelper& cgh)
4565 {
4566 generate_code(cgh.get_outputstruct(this));
4567 }
4568
4569 char *Def_Var::generate_code_str(char *str)
4570 {
4571 const string& t_genname = get_genname();
4572 const char *genname_str = t_genname.c_str();
4573 if (initial_value && initial_value->has_single_expr()) {
4574 // the initial value can be represented by a single C++ expression
4575 // the object is initialized by the constructor
4576 str = mputprintf(str, "%s %s(%s);\n",
a38c6d4c 4577 type->get_genname_value(my_scope).c_str(), genname_str,
4578 initial_value->get_single_expr().c_str());
970ed795
EL
4579 } else {
4580 // use the default constructor
4581 str = mputprintf(str, "%s %s;\n",
a38c6d4c 4582 type->get_genname_value(my_scope).c_str(), genname_str);
970ed795 4583 if (initial_value) {
a38c6d4c 4584 // the initial value is assigned using subsequent statements
4585 str = initial_value->generate_code_init(str, genname_str);
970ed795
EL
4586 }
4587 }
4588 return str;
4589 }
4590
4591 void Def_Var::ilt_generate_code(ILT *ilt)
4592 {
4593 const string& t_genname = get_genname();
4594 const char *genname_str = t_genname.c_str();
4595 char*& def=ilt->get_out_def();
4596 char*& init=ilt->get_out_branches();
4597 def = mputprintf(def, "%s %s;\n", type->get_genname_value(my_scope).c_str(),
4598 genname_str);
4599 if (initial_value)
4600 init = initial_value->generate_code_init(init, genname_str);
4601 }
4602
4603 char *Def_Var::generate_code_init_comp(char *str, Definition *base_defn)
4604 {
4605 if (initial_value) {
4606 str = initial_value->generate_code_init(str,
a38c6d4c 4607 base_defn->get_genname_from_scope(my_scope).c_str());
970ed795
EL
4608 }
4609 return str;
4610 }
4611
4612 void Def_Var::dump_internal(unsigned level) const
4613 {
4614 DEBUG(level, "Variable %s", id->get_dispname().c_str());
4615 type->dump(level + 1);
4616 if (initial_value) initial_value->dump(level + 1);
4617 }
4618
4619 // =================================
4620 // ===== Def_Var_Template
4621 // =================================
4622
4623 Def_Var_Template::Def_Var_Template(Identifier *p_id, Type *p_type,
4624 Template *p_initial_value, template_restriction_t p_template_restriction)
4625 : Definition(A_VAR_TEMPLATE, p_id), type(p_type),
4626 initial_value(p_initial_value), template_restriction(p_template_restriction)
4627 {
4628 if (!p_type) FATAL_ERROR("Ttcn::Def_Var_Template::Def_Var_Template()");
4629 type->set_ownertype(Type::OT_VARTMPL_DEF, this);
4630 }
4631
4632 Def_Var_Template::~Def_Var_Template()
4633 {
4634 delete type;
4635 delete initial_value;
4636 }
4637
4638 Def_Var_Template *Def_Var_Template::clone() const
4639 {
4640 FATAL_ERROR("Def_Var_Template::clone");
4641 }
4642
4643 void Def_Var_Template::set_fullname(const string& p_fullname)
4644 {
4645 Definition::set_fullname(p_fullname);
4646 type->set_fullname(p_fullname + ".<type>");
4647 if (initial_value)
4648 initial_value->set_fullname(p_fullname + ".<initial_value>");
4649 }
4650
4651 void Def_Var_Template::set_my_scope(Scope *p_scope)
4652 {
4653 Definition::set_my_scope(p_scope);
4654 type->set_my_scope(p_scope);
4655 if (initial_value) initial_value->set_my_scope(p_scope);
4656 }
4657
4658 Type *Def_Var_Template::get_Type()
4659 {
4660 chk();
4661 return type;
4662 }
4663
4664 void Def_Var_Template::chk()
4665 {
4666 if(checked) return;
4667 Error_Context cntxt(this, "In template variable definition `%s'",
4668 id->get_dispname().c_str());
4669 type->set_genname(_T_, get_genname());
4670 type->chk();
4671 checked = true;
4672 Type *t = type->get_type_refd_last();
4673 if (t->get_typetype() == Type::T_PORT) {
4674 error("Template variable cannot be defined for port type `%s'",
4675 t->get_fullname().c_str());
4676 }
4677
4678 if (initial_value) {
4679 initial_value->set_my_governor(type);
4680 initial_value->flatten(false);
4681
4682 if (initial_value->get_templatetype() == Template::CSTR_PATTERN &&
4683 type->get_type_refd_last()->get_typetype() == Type::T_USTR) {
4684 initial_value->set_templatetype(Template::USTR_PATTERN);
4685 initial_value->get_ustr_pattern()->set_pattern_type(
4686 PatternString::USTR_PATTERN);
4687 }
4688
4689 type->chk_this_template_ref(initial_value);
4690 // temporary hack: to allow incomplete body as initial value
4691 // checking as a modified template, but without a base template
4692 type->chk_this_template_generic(initial_value, INCOMPLETE_ALLOWED,
4693 OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, IMPLICIT_OMIT, 0);
4694 gen_restriction_check =
4695 initial_value->chk_restriction("template variable definition",
3abe9331 4696 template_restriction, initial_value);
970ed795
EL
4697 if (!semantic_check_only) {
4698 initial_value->set_genname_recursive(get_genname());
4699 initial_value->set_code_section(GovernedSimple::CS_INLINE);
4700 }
4701 }
4702 if (w_attrib_path) {
4703 w_attrib_path->chk_global_attrib();
4704 w_attrib_path->chk_no_qualif();
4705 }
4706 }
4707
4708 bool Def_Var_Template::chk_identical(Definition *p_def)
4709 {
4710 chk();
4711 p_def->chk();
4712 if (p_def->get_asstype() != A_VAR_TEMPLATE) {
4713 const char *dispname_str = id->get_dispname().c_str();
4714 error("Local definition `%s' is a template variable, but the definition "
a38c6d4c 4715 "inherited from component type `%s' is a %s", dispname_str,
970ed795
EL
4716 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
4717 p_def->note("The inherited definition of `%s' is here", dispname_str);
4718 return false;
4719 }
4720 Def_Var_Template *p_def_var_template =
4721 dynamic_cast<Def_Var_Template*>(p_def);
4722 if (!p_def_var_template) FATAL_ERROR("Def_Var_Template::chk_identical()");
4723 if (!type->is_identical(p_def_var_template->type)) {
4724 const char *dispname_str = id->get_dispname().c_str();
4725 type->error("Local template variable `%s' has type `%s', but the "
a38c6d4c 4726 "template variable inherited from component type `%s' has type `%s'",
4727 dispname_str, type->get_typename().c_str(),
970ed795 4728 p_def_var_template->get_my_scope()->get_fullname().c_str(),
a38c6d4c 4729 p_def_var_template->type->get_typename().c_str());
970ed795 4730 p_def_var_template->note("The inherited template variable `%s' is here",
a38c6d4c 4731 dispname_str);
970ed795
EL
4732 return false;
4733 }
4734 if (initial_value) {
4735 if (!p_def_var_template->initial_value) {
a38c6d4c 4736 const char *dispname_str = id->get_dispname().c_str();
4737 initial_value->warning("Local template variable `%s' has initial "
4738 "value, but the template variable inherited from component type "
4739 "`%s' does not", dispname_str,
4740 p_def_var_template->get_my_scope()->get_fullname().c_str());
4741 p_def_var_template->note("The inherited template variable `%s' is here",
4742 dispname_str);
970ed795
EL
4743 }
4744 } else if (p_def_var_template->initial_value) {
4745 const char *dispname_str = id->get_dispname().c_str();
4746 warning("Local template variable `%s' does not have initial value, but "
a38c6d4c 4747 "the template variable inherited from component type `%s' has",
4748 dispname_str,
4749 p_def_var_template->get_my_scope()->get_fullname().c_str());
970ed795 4750 p_def_var_template->note("The inherited template variable `%s' is here",
a38c6d4c 4751 dispname_str);
970ed795
EL
4752 }
4753 return true;
4754 }
4755
4756 void Def_Var_Template::generate_code(output_struct *target, bool clean_up)
4757 {
4758 type->generate_code(target);
4759 const_def cdef;
4760 Code::init_cdef(&cdef);
4761 type->generate_code_object(&cdef, my_scope, get_genname(), 0, true);
4762 Code::merge_cdef(target, &cdef);
4763 Code::free_cdef(&cdef);
4764 if (initial_value) {
4765 if (Common::Type::T_SEQOF == initial_value->get_my_governor()->get_typetype() ||
4766 Common::Type::T_ARRAY == initial_value->get_my_governor()->get_typetype()) {
4767 target->functions.init_comp = mputprintf(target->functions.init_comp,
4768 "%s.remove_all_permutations();\n", initial_value->get_lhs_name().c_str());
4769 }
4770 target->functions.init_comp =
4771 initial_value->generate_code_init(target->functions.init_comp,
4772 initial_value->get_lhs_name().c_str());
4773 if (template_restriction!=TR_NONE && gen_restriction_check)
4774 target->functions.init_comp = Template::generate_restriction_check_code(
4775 target->functions.init_comp, initial_value->get_lhs_name().c_str(),
4776 template_restriction);
4777 } else if (clean_up) { // No initial value.
4778 // Always reset component variables/variable templates on component
4779 // reinitialization. Fix for HM79493.
4780 target->functions.init_comp = mputprintf(target->functions.init_comp,
4781 "%s.clean_up();\n", get_genname().c_str());
4782 }
4783 }
4784
4785 void Def_Var_Template::generate_code(CodeGenHelper& cgh)
4786 {
4787 generate_code(cgh.get_outputstruct(this));
4788 }
4789
4790 char *Def_Var_Template::generate_code_str(char *str)
4791 {
4792 const string& t_genname = get_genname();
4793 const char *genname_str = t_genname.c_str();
4794 if (initial_value && initial_value->has_single_expr()) {
4795 // The initial value can be represented by a single C++ expression
4796 // the object is initialized by the constructor.
4797 str = mputprintf(str, "%s %s(%s);\n",
4798 type->get_genname_template(my_scope).c_str(), genname_str,
4799 initial_value->get_single_expr(false).c_str());
4800 } else {
4801 // Use the default constructor.
4802 str = mputprintf(str, "%s %s;\n",
4803 type->get_genname_template(my_scope).c_str(), genname_str);
4804 if (initial_value) {
4805 // The initial value is assigned using subsequent statements.
4806 if (use_runtime_2 && TypeConv::needs_conv_refd(initial_value))
4807 str = TypeConv::gen_conv_code_refd(str, genname_str, initial_value);
4808 else str = initial_value->generate_code_init(str, genname_str);
4809 }
4810 }
4811 if (initial_value && template_restriction != TR_NONE
4812 && gen_restriction_check)
4813 str = Template::generate_restriction_check_code(str, genname_str,
4814 template_restriction);
4815 return str;
4816 }
4817
4818 void Def_Var_Template::ilt_generate_code(ILT *ilt)
4819 {
4820 const string& t_genname = get_genname();
4821 const char *genname_str = t_genname.c_str();
4822 char*& def=ilt->get_out_def();
4823 char*& init=ilt->get_out_branches();
4824 def = mputprintf(def, "%s %s;\n",
4825 type->get_genname_template(my_scope).c_str(), genname_str);
4826 if (initial_value) {
4827 init = initial_value->generate_code_init(init, genname_str);
4828 if (template_restriction!=TR_NONE && gen_restriction_check)
4829 init = Template::generate_restriction_check_code(init, genname_str,
4830 template_restriction);
4831 }
4832 }
4833
4834 char *Def_Var_Template::generate_code_init_comp(char *str,
4835 Definition *base_defn)
4836 {
4837 if (initial_value) {
4838 str = initial_value->generate_code_init(str,
a38c6d4c 4839 base_defn->get_genname_from_scope(my_scope).c_str());
970ed795
EL
4840 if (template_restriction != TR_NONE && gen_restriction_check)
4841 str = Template::generate_restriction_check_code(str,
4842 base_defn->get_genname_from_scope(my_scope).c_str(),
4843 template_restriction);
4844 }
4845 return str;
4846 }
4847
4848 void Def_Var_Template::dump_internal(unsigned level) const
4849 {
4850 DEBUG(level, "Template variable %s", id->get_dispname().c_str());
4851 if (template_restriction!=TR_NONE)
4852 DEBUG(level + 1, "restriction: %s",
4853 Template::get_restriction_name(template_restriction));
4854 type->dump(level + 1);
4855 if (initial_value) initial_value->dump(level + 1);
4856 }
4857
4858 // =================================
4859 // ===== Def_Timer
4860 // =================================
4861
4862 Def_Timer::~Def_Timer()
4863 {
4864 delete dimensions;
4865 delete default_duration;
4866 }
4867
4868 Def_Timer *Def_Timer::clone() const
4869 {
4870 FATAL_ERROR("Def_Timer::clone");
4871 }
4872
4873 void Def_Timer::set_fullname(const string& p_fullname)
4874 {
4875 Definition::set_fullname(p_fullname);
4876 if (dimensions) dimensions->set_fullname(p_fullname + ".<dimensions>");
4877 if (default_duration)
4878 default_duration->set_fullname(p_fullname + ".<default_duration>");
4879 }
4880
4881 void Def_Timer::set_my_scope(Scope *p_scope)
4882 {
4883 Definition::set_my_scope(p_scope);
4884 if (dimensions) dimensions->set_my_scope(p_scope);
4885 if (default_duration) default_duration->set_my_scope(p_scope);
4886 }
4887
4888 ArrayDimensions *Def_Timer::get_Dimensions()
4889 {
4890 if (!checked) chk();
4891 return dimensions;
4892 }
4893
4894 void Def_Timer::chk()
4895 {
4896 if(checked) return;
4897 Error_Context cntxt(this, "In timer definition `%s'",
4898 id->get_dispname().c_str());
4899 if (dimensions) dimensions->chk();
4900 if (default_duration) {
4901 Error_Context cntxt2(default_duration, "In default duration");
4902 if (dimensions) chk_array_duration(default_duration);
4903 else chk_single_duration(default_duration);
4904 if (!semantic_check_only) {
4905 default_duration->set_code_section(GovernedSimple::CS_POST_INIT);
4906 }
4907 }
4908 checked = true;
4909 if (w_attrib_path) {
4910 w_attrib_path->chk_global_attrib();
4911 w_attrib_path->chk_no_qualif();
4912 }
4913 }
4914
4915 bool Def_Timer::chk_identical(Definition *p_def)
4916 {
4917 chk();
4918 p_def->chk();
4919 if (p_def->get_asstype() != A_TIMER) {
4920 const char *dispname_str = id->get_dispname().c_str();
4921 error("Local definition `%s' is a timer, but the definition inherited "
a38c6d4c 4922 "from component type `%s' is a %s", dispname_str,
970ed795
EL
4923 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
4924 p_def->note("The inherited definition of `%s' is here", dispname_str);
4925 return false;
4926 }
4927 Def_Timer *p_def_timer = dynamic_cast<Def_Timer*>(p_def);
4928 if (!p_def_timer) FATAL_ERROR("Def_Timer::chk_identical()");
4929 if (dimensions) {
4930 if (p_def_timer->dimensions) {
4931 if (!dimensions->is_identical(p_def_timer->dimensions)) {
a38c6d4c 4932 const char *dispname_str = id->get_dispname().c_str();
4933 error("Local timer `%s' and the timer inherited from component type "
4934 "`%s' have different array dimensions", dispname_str,
970ed795 4935 p_def_timer->get_my_scope()->get_fullname().c_str());
a38c6d4c 4936 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4937 return false;
4938 }
970ed795 4939 } else {
a38c6d4c 4940 const char *dispname_str = id->get_dispname().c_str();
4941 error("Local definition `%s' is a timer array, but the definition "
4942 "inherited from component type `%s' is a single timer", dispname_str,
970ed795 4943 p_def_timer->get_my_scope()->get_fullname().c_str());
a38c6d4c 4944 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4945 return false;
970ed795
EL
4946 }
4947 } else if (p_def_timer->dimensions) {
4948 const char *dispname_str = id->get_dispname().c_str();
4949 error("Local definition `%s' is a single timer, but the definition "
a38c6d4c 4950 "inherited from component type `%s' is a timer array", dispname_str,
970ed795
EL
4951 p_def_timer->get_my_scope()->get_fullname().c_str());
4952 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4953 return false;
4954 }
4955 if (default_duration) {
4956 if (p_def_timer->default_duration) {
4957 if (!default_duration->is_unfoldable() &&
a38c6d4c 4958 !p_def_timer->default_duration->is_unfoldable() &&
4959 !(*default_duration == *p_def_timer->default_duration)) {
4960 const char *dispname_str = id->get_dispname().c_str();
4961 default_duration->warning("Local timer `%s' and the timer inherited "
4962 "from component type `%s' have different default durations",
4963 dispname_str, p_def_timer->get_my_scope()->get_fullname().c_str());
4964 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4965 }
970ed795 4966 } else {
a38c6d4c 4967 const char *dispname_str = id->get_dispname().c_str();
4968 default_duration->error("Local timer `%s' has default duration, but "
4969 "the timer inherited from component type `%s' does not", dispname_str,
970ed795 4970 p_def_timer->get_my_scope()->get_fullname().c_str());
a38c6d4c 4971 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4972 return false;
970ed795
EL
4973 }
4974 } else if (p_def_timer->default_duration) {
4975 const char *dispname_str = id->get_dispname().c_str();
4976 error("Local timer `%s' does not have default duration, but the timer "
a38c6d4c 4977 "inherited from component type `%s' has", dispname_str,
4978 p_def_timer->get_my_scope()->get_fullname().c_str());
970ed795
EL
4979 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4980 return false;
4981 }
4982 return true;
4983 }
4984
4985 bool Def_Timer::has_default_duration(FieldOrArrayRefs *p_subrefs)
4986 {
4987 // return true in case of any uncertainity
4988 if (!default_duration) return false;
4989 else if (!dimensions || !p_subrefs) return true;
4990 Value *v = default_duration;
4991 size_t nof_dims = dimensions->get_nof_dims();
4992 size_t nof_refs = p_subrefs->get_nof_refs();
4993 size_t upper_limit = nof_dims < nof_refs ? nof_dims : nof_refs;
4994 for (size_t i = 0; i < upper_limit; i++) {
4995 v = v->get_value_refd_last();
4996 if (v->get_valuetype() != Value::V_SEQOF) break;
4997 FieldOrArrayRef *ref = p_subrefs->get_ref(i);
4998 if (ref->get_type() != FieldOrArrayRef::ARRAY_REF) return true;
4999 Value *v_index = ref->get_val()->get_value_refd_last();
5000 if (v_index->get_valuetype() != Value::V_INT) return true;
5001 Int index = v_index->get_val_Int()->get_val()
5002 - dimensions->get_dim_byIndex(i)->get_offset();
5003 if (index >= 0 && index < static_cast<Int>(v->get_nof_comps()))
5004 v = v->get_comp_byIndex(index);
5005 else return true;
5006 }
5007 return v->get_valuetype() != Value::V_NOTUSED;
5008 }
5009
5010 void Def_Timer::chk_single_duration(Value *dur)
5011 {
5012 dur->chk_expr_float(is_local() ?
5013 Type::EXPECTED_DYNAMIC_VALUE : Type::EXPECTED_STATIC_VALUE);
5014 Value *v = dur->get_value_refd_last();
5015 if (v->get_valuetype() == Value::V_REAL) {
5016 ttcn3float v_real = v->get_val_Real();
5017 if ( (v_real<0.0) || isSpecialFloatValue(v_real) ) {
5018 dur->error("A non-negative float value was expected "
5019 "as timer duration instead of `%s'", Real2string(v_real).c_str());
5020 }
5021 }
5022 }
5023
5024 void Def_Timer::chk_array_duration(Value *dur, size_t start_dim)
5025 {
5026 ArrayDimension *dim = dimensions->get_dim_byIndex(start_dim);
5027 bool array_size_known = !dim->get_has_error();
5028 size_t array_size = 0;
5029 if (array_size_known) array_size = dim->get_size();
5030 Value *v = dur->get_value_refd_last();
5031 switch (v->get_valuetype()) {
5032 case Value::V_ERROR:
5033 return;
5034 case Value::V_SEQOF: {
5035 size_t nof_vs = v->get_nof_comps();
5036 // Value-list notation.
5037 if (!v->is_indexed()) {
5038 if (array_size_known) {
5039 if (array_size > nof_vs) {
5040 dur->error("Too few elements in the default duration of timer "
5041 "array: %lu was expected instead of %lu",
5042 (unsigned long)array_size, (unsigned long)nof_vs);
5043 } else if (array_size < nof_vs) {
5044 dur->error("Too many elements in the default duration of timer "
5045 "array: %lu was expected instead of %lu",
5046 (unsigned long)array_size, (unsigned long)nof_vs);
5047 }
5048 }
5049 bool last_dimension = start_dim + 1 >= dimensions->get_nof_dims();
5050 for (size_t i = 0; i < nof_vs; i++) {
5051 Value *array_v = v->get_comp_byIndex(i);
5052 if (array_v->get_valuetype() == Value::V_NOTUSED) continue;
5053 if (last_dimension) chk_single_duration(array_v);
5054 else chk_array_duration(array_v, start_dim + 1);
5055 }
5056 } else {
5057 // Indexed-notation.
5058 bool last_dimension = start_dim + 1 >= dimensions->get_nof_dims();
5059 map<Int, Int> index_map;
5060 for (size_t i = 0; i < nof_vs; i++) {
5061 Value *array_v = v->get_comp_byIndex(i);
5062 if (array_v->get_valuetype() == Value::V_NOTUSED) continue;
5063 if (last_dimension) chk_single_duration(array_v);
5064 else chk_array_duration(array_v, start_dim + 1);
5065 Error_Context cntxt(this, "In timer array element %lu",
5066 (unsigned long)(i + 1));
5067 Value *index = v->get_index_byIndex(i);
5068 dim->chk_index(index, Type::EXPECTED_DYNAMIC_VALUE);
5069 if (index->get_value_refd_last()->get_valuetype() == Value::V_INT) {
5070 const int_val_t *index_int = index->get_value_refd_last()
5071 ->get_val_Int();
5072 if (*index_int > INT_MAX) {
5073 index->error("An integer value less than `%d' was expected for "
5074 "indexing timer array instead of `%s'", INT_MAX,
5075 (index_int->t_str()).c_str());
5076 index->set_valuetype(Value::V_ERROR);
5077 } else {
5078 Int index_val = index_int->get_val();
5079 if (index_map.has_key(index_val)) {
5080 index->error("Duplicate index value `%s' for timer array "
5081 "elements `%s' and `%s'",
5082 Int2string(index_val).c_str(),
5083 Int2string((Int)i + 1).c_str(),
5084 Int2string(*index_map[index_val]).c_str());
5085 index->set_valuetype(Value::V_ERROR);
5086 } else {
5087 index_map.add(index_val, new Int((Int)i + 1));
5088 }
5089 }
5090 }
5091 }
5092 // It's not possible to have "index_map.size() > array_size", since we
5093 // add only correct constant-index values into the map. It's possible
5094 // to create partially initialized timer arrays.
5095 for (size_t i = 0; i < index_map.size(); i++)
5096 delete index_map.get_nth_elem(i);
5097 index_map.clear();
5098 }
5099 break; }
5100 default:
5101 if (array_size_known) {
5102 dur->error("An array value (with %lu elements) was expected as "
5103 "default duration of timer array",
5104 (unsigned long)array_size);
5105 } else {
5106 dur->error("An array value was expected as default duration of timer "
5107 "array");
5108 }
5109 dur->set_valuetype(Value::V_ERROR);
5110 return;
5111 }
5112 }
5113
5114 void Def_Timer::generate_code(output_struct *target, bool)
5115 {
5116 const string& t_genname = get_genname();
5117 const char *genname_str = t_genname.c_str();
5118 const string& dispname = id->get_dispname();
5119 if (dimensions) {
5120 // timer array
5121 const string& array_type = dimensions->get_timer_type();
5122 const char *array_type_str = array_type.c_str();
5123 target->header.global_vars = mputprintf(target->header.global_vars,
a38c6d4c 5124 "extern %s %s;\n", array_type_str, genname_str);
970ed795 5125 target->source.global_vars = mputprintf(target->source.global_vars,
a38c6d4c 5126 "%s %s;\n", array_type_str, genname_str);
970ed795 5127 target->functions.pre_init = mputstr(target->functions.pre_init, "{\n"
a38c6d4c 5128 "static const char * const timer_name = \"");
970ed795 5129 target->functions.pre_init = mputstr(target->functions.pre_init,
a38c6d4c 5130 dispname.c_str());
970ed795 5131 target->functions.pre_init = mputprintf(target->functions.pre_init,
a38c6d4c 5132 "\";\n"
970ed795 5133 "%s.set_name(timer_name);\n"
a38c6d4c 5134 "}\n", genname_str);
970ed795 5135 if (default_duration) target->functions.post_init =
a38c6d4c 5136 generate_code_array_duration(target->functions.post_init, genname_str,
5137 default_duration);
970ed795
EL
5138 } else {
5139 // single timer
5140 target->header.global_vars = mputprintf(target->header.global_vars,
a38c6d4c 5141 "extern TIMER %s;\n", genname_str);
970ed795 5142 if (default_duration) {
a38c6d4c 5143 // has default duration
5144 Value *v = default_duration->get_value_refd_last();
5145 if (v->get_valuetype() == Value::V_REAL) {
5146 // duration is known at compilation time -> set in the constructor
5147 target->source.global_vars = mputprintf(target->source.global_vars,
5148 "TIMER %s(\"%s\", %s);\n", genname_str, dispname.c_str(),
5149 v->get_single_expr().c_str());
5150 } else {
5151 // duration is known only at runtime -> set in post_init
5152 target->source.global_vars = mputprintf(target->source.global_vars,
5153 "TIMER %s(\"%s\");\n", genname_str, dispname.c_str());
5154 expression_struct expr;
5155 Code::init_expr(&expr);
5156 expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
5157 genname_str);
5158 default_duration->generate_code_expr(&expr);
5159 expr.expr = mputc(expr.expr, ')');
5160 target->functions.post_init =
5161 Code::merge_free_expr(target->functions.post_init, &expr);
5162 }
970ed795 5163 } else {
a38c6d4c 5164 // does not have default duration
5165 target->source.global_vars = mputprintf(target->source.global_vars,
5166 "TIMER %s(\"%s\");\n", genname_str, dispname.c_str());
970ed795
EL
5167 }
5168 }
5169 }
5170
5171 void Def_Timer::generate_code(CodeGenHelper& cgh) {
5172 generate_code(cgh.get_current_outputstruct());
5173 }
5174
5175 char *Def_Timer::generate_code_array_duration(char *str,
5176 const char *object_name, Value *dur, size_t start_dim)
5177 {
5178 ArrayDimension *dim = dimensions->get_dim_byIndex(start_dim);
5179 size_t dim_size = dim->get_size();
5180 Value *v = dur->get_value_refd_last();
5181 if (v->get_valuetype() != Value::V_SEQOF
5182 || (v->get_nof_comps() != dim_size && !v->is_indexed()))
5183 FATAL_ERROR("Def_Timer::generate_code_array_duration()");
5184 // Value-list notation.
5185 if (!v->is_indexed()) {
5186 if (start_dim + 1 < dimensions->get_nof_dims()) {
5187 // There are more dimensions, the elements of "v" are arrays a
5188 // temporary reference shall be introduced if the next dimension has
5189 // more than 1 elements.
5190 bool temp_ref_needed =
5191 dimensions->get_dim_byIndex(start_dim + 1)->get_size() > 1;
5192 for (size_t i = 0; i < dim_size; i++) {
5193 Value *v_elem = v->get_comp_byIndex(i);
5194 if (v_elem->get_valuetype() == Value::V_NOTUSED) continue;
5195 if (temp_ref_needed) {
5196 const string& tmp_id = my_scope->get_scope_mod_gen()
5197 ->get_temporary_id();
5198 const char *tmp_str = tmp_id.c_str();
5199 str = mputprintf(str, "{\n"
5200 "%s& %s = %s.array_element(%lu);\n",
5201 dimensions->get_timer_type(start_dim + 1).c_str(),
5202 tmp_str, object_name, (unsigned long)i);
5203 str = generate_code_array_duration(str, tmp_str, v_elem,
5204 start_dim + 1);
5205 str = mputstr(str, "}\n");
5206 } else {
5207 char *tmp_str = mprintf("%s.array_element(%lu)", object_name,
5208 (unsigned long)i);
5209 str = generate_code_array_duration(str, tmp_str, v_elem,
5210 start_dim + 1);
5211 Free(tmp_str);
5212 }
5213 }
5214 } else {
5215 // We are in the last dimension, the elements of "v" are floats.
5216 for (size_t i = 0; i < dim_size; i++) {
5217 Value *v_elem = v->get_comp_byIndex(i);
5218 if (v_elem->get_valuetype() == Value::V_NOTUSED) continue;
5219 expression_struct expr;
5220 Code::init_expr(&expr);
5221 expr.expr = mputprintf(expr.expr,
5222 "%s.array_element(%lu).set_default_duration(",
5223 object_name, (unsigned long)i);
5224 v_elem->generate_code_expr(&expr);
5225 expr.expr = mputc(expr.expr, ')');
5226 str = Code::merge_free_expr(str, &expr);
5227 }
5228 }
5229 // Indexed-list notation.
5230 } else {
5231 if (start_dim + 1 < dimensions->get_nof_dims()) {
5232 bool temp_ref_needed =
5233 dimensions->get_dim_byIndex(start_dim + 1)->get_size() > 1;
5234 for (size_t i = 0; i < v->get_nof_comps(); i++) {
5235 Value *v_elem = v->get_comp_byIndex(i);
5236 if (v_elem->get_valuetype() == Value::V_NOTUSED) continue;
5237 if (temp_ref_needed) {
5238 const string& tmp_id = my_scope->get_scope_mod_gen()
5239 ->get_temporary_id();
5240 const string& idx_id = my_scope->get_scope_mod_gen()
5241 ->get_temporary_id();
5242 const char *tmp_str = tmp_id.c_str();
5243 str = mputstr(str, "{\n");
5244 str = mputprintf(str, "int %s;\n", idx_id.c_str());
5245 str = v->get_index_byIndex(i)->generate_code_init(str,
5246 idx_id.c_str());
5247 str = mputprintf(str, "%s& %s = %s.array_element(%s);\n",
5248 dimensions->get_timer_type(start_dim + 1).c_str(),
5249 tmp_str, object_name, idx_id.c_str());
5250 str = generate_code_array_duration(str, tmp_str, v_elem,
5251 start_dim + 1);
5252 str = mputstr(str, "}\n");
5253 } else {
5254 const string& idx_id = my_scope->get_scope_mod_gen()
5255 ->get_temporary_id();
5256 str = mputstr(str, "{\n");
5257 str = mputprintf(str, "int %s;\n", idx_id.c_str());
5258 str = v->get_index_byIndex(i)->generate_code_init(str,
5259 idx_id.c_str());
5260 char *tmp_str = mprintf("%s.array_element(%s)", object_name,
5261 idx_id.c_str());
5262 str = generate_code_array_duration(str, tmp_str, v_elem,
5263 start_dim + 1);
5264 str = mputstr(str, "}\n");
5265 Free(tmp_str);
5266 }
5267 }
5268 } else {
5269 for (size_t i = 0; i < v->get_nof_comps(); i++) {
5270 Value *v_elem = v->get_comp_byIndex(i);
5271 if (v_elem->get_valuetype() == Value::V_NOTUSED) continue;
5272 expression_struct expr;
5273 Code::init_expr(&expr);
5274 str = mputstr(str, "{\n");
5275 const string& idx_id = my_scope->get_scope_mod_gen()
5276 ->get_temporary_id();
5277 str = mputprintf(str, "int %s;\n", idx_id.c_str());
5278 str = v->get_index_byIndex(i)->generate_code_init(str,
5279 idx_id.c_str());
5280 str = mputprintf(str,
5281 "%s.array_element(%s).set_default_duration(",
5282 object_name, idx_id.c_str());
5283 v_elem->generate_code_expr(&expr);
5284 expr.expr = mputc(expr.expr, ')');
5285 str = Code::merge_free_expr(str, &expr);
5286 str = mputstr(str, "}\n");
5287 }
5288 }
5289 }
5290 return str;
5291 }
5292
5293 char *Def_Timer::generate_code_str(char *str)
5294 {
5295 const string& t_genname = get_genname();
5296 const char *genname_str = t_genname.c_str();
5297 const string& dispname = id->get_dispname();
5298 if (dimensions) {
5299 // timer array
5300 const string& array_type = dimensions->get_timer_type();
5301 const char *array_type_str = array_type.c_str();
5302 str = mputprintf(str, "%s %s;\n", array_type_str, genname_str);
5303 str = mputstr(str, "{\n"
a38c6d4c 5304 "static const char * const timer_name = \"");
970ed795
EL
5305 str = mputstr(str, dispname.c_str());
5306 str = mputprintf(str, "\";\n"
5307 "%s.set_name(timer_name);\n"
a38c6d4c 5308 "}\n", genname_str);
970ed795 5309 if (default_duration) str = generate_code_array_duration(str,
a38c6d4c 5310 genname_str, default_duration);
970ed795
EL
5311 } else {
5312 // single timer
5313 if (default_duration && default_duration->has_single_expr()) {
a38c6d4c 5314 // the default duration can be passed to the constructor
5315 str = mputprintf(str, "TIMER %s(\"%s\", %s);\n", genname_str,
5316 dispname.c_str(), default_duration->get_single_expr().c_str());
970ed795 5317 } else {
a38c6d4c 5318 // only the name is passed to the constructor
5319 str = mputprintf(str, "TIMER %s(\"%s\");\n", genname_str,
5320 dispname.c_str());
5321 if (default_duration) {
5322 // the default duration is set explicitly
5323 expression_struct expr;
5324 Code::init_expr(&expr);
5325 expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
5326 genname_str);
5327 default_duration->generate_code_expr(&expr);
5328 expr.expr = mputc(expr.expr, ')');
5329 str = Code::merge_free_expr(str, &expr);
5330 }
970ed795
EL
5331 }
5332 }
5333 return str;
5334 }
5335
5336 void Def_Timer::ilt_generate_code(ILT *ilt)
5337 {
5338 const string& t_genname = get_genname();
5339 const char *genname_str = t_genname.c_str();
5340 const string& dispname = id->get_dispname();
5341
5342 char*& def = ilt->get_out_def();
5343 char*& init = ilt->get_out_branches();
5344
5345 if (dimensions) {
5346 // timer array
5347 const string& array_type = dimensions->get_timer_type();
5348 const char *array_type_str = array_type.c_str();
5349 def = mputprintf(def, "%s %s;\n", array_type_str, genname_str);
5350 def = mputstr(def, "{\n"
a38c6d4c 5351 "static const char * const timer_names[] = { ");
970ed795
EL
5352 def = dimensions->generate_element_names(def, dispname);
5353 def = mputprintf(def, " };\n"
5354 "%s.set_name(%lu, timer_names);\n"
a38c6d4c 5355 "}\n", genname_str, (unsigned long) dimensions->get_array_size());
970ed795 5356 if (default_duration) init = generate_code_array_duration(init,
a38c6d4c 5357 genname_str, default_duration);
970ed795
EL
5358 } else {
5359 // single timer
5360 if (default_duration) {
a38c6d4c 5361 // has default duration
5362 Value *v = default_duration->get_value_refd_last();
5363 if (v->get_valuetype() == Value::V_REAL) {
5364 // duration is known at compilation time -> set in the constructor
5365 def = mputprintf(def, "TIMER %s(\"%s\", %s);\n", genname_str,
5366 dispname.c_str(), v->get_single_expr().c_str());
5367 } else {
5368 // duration is known only at runtime -> set when control reaches the
5369 // timer definition
5370 def = mputprintf(def, "TIMER %s(\"%s\");\n", genname_str,
5371 dispname.c_str());
970ed795
EL
5372 expression_struct expr;
5373 Code::init_expr(&expr);
a38c6d4c 5374 expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
5375 genname_str);
5376 default_duration->generate_code_expr(&expr);
5377 expr.expr = mputc(expr.expr, ')');
5378 init = Code::merge_free_expr(init, &expr);
5379 }
970ed795 5380 } else {
a38c6d4c 5381 // does not have default duration
5382 def = mputprintf(def, "TIMER %s(\"%s\");\n", genname_str,
5383 dispname.c_str());
970ed795
EL
5384 }
5385 }
5386 }
5387
5388 char *Def_Timer::generate_code_init_comp(char *str, Definition *base_defn)
5389 {
5390 if (default_duration) {
5391 Def_Timer *base_timer_defn = dynamic_cast<Def_Timer*>(base_defn);
5392 if (!base_timer_defn || !base_timer_defn->default_duration)
a38c6d4c 5393 FATAL_ERROR("Def_Timer::generate_code_init_comp()");
970ed795
EL
5394 // initializer is not needed if the default durations are the same
5395 // constants in both timers
5396 if (default_duration->is_unfoldable() ||
a38c6d4c 5397 base_timer_defn->default_duration->is_unfoldable() ||
5398 !(*default_duration == *base_timer_defn->default_duration)) {
5399 if (dimensions) {
5400 str = generate_code_array_duration(str,
5401 base_timer_defn->get_genname_from_scope(my_scope).c_str(),
5402 default_duration);
5403 } else {
5404 expression_struct expr;
5405 Code::init_expr(&expr);
5406 expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
5407 base_timer_defn->get_genname_from_scope(my_scope).c_str());
5408 default_duration->generate_code_expr(&expr);
5409 expr.expr = mputc(expr.expr, ')');
5410 str = Code::merge_free_expr(str, &expr);
5411 }
970ed795
EL
5412 }
5413 }
5414 return str;
5415 }
5416
5417 void Def_Timer::dump_internal(unsigned level) const
5418 {
5419 DEBUG(level, "Timer: %s", id->get_dispname().c_str());
5420 if (dimensions) dimensions->dump(level + 1);
5421 if (default_duration) {
5422 DEBUG(level + 1, "Default duration:");
5423 default_duration->dump(level + 1);
5424 }
5425 }
5426
5427 // =================================
5428 // ===== Def_Port
5429 // =================================
5430
5431 Def_Port::Def_Port(Identifier *p_id, Reference *p_tref,
5432 ArrayDimensions *p_dims)
5433 : Definition(A_PORT, p_id), type_ref(p_tref), port_type(0),
5434 dimensions(p_dims)
5435 {
5436 if (!p_tref) FATAL_ERROR("Def_Port::Def_Port()");
5437 }
5438
5439 Def_Port::~Def_Port()
5440 {
5441 delete type_ref;
5442 delete dimensions;
5443 }
5444
5445 Def_Port *Def_Port::clone() const
5446 {
5447 FATAL_ERROR("Def_Port::clone");
5448 }
5449
5450 void Def_Port::set_fullname(const string& p_fullname)
5451 {
5452 Definition::set_fullname(p_fullname);
5453 type_ref->set_fullname(p_fullname + ".<type_ref>");
5454 if (dimensions) dimensions->set_fullname(p_fullname);
5455 }
5456
5457 void Def_Port::set_my_scope(Scope *p_scope)
5458 {
5459 Definition::set_my_scope(p_scope);
5460 type_ref->set_my_scope(p_scope);
5461 if (dimensions) dimensions->set_my_scope(p_scope);
5462 }
5463
5464 Type *Def_Port::get_Type()
5465 {
5466 chk();
5467 return port_type;
5468 }
5469
5470 ArrayDimensions *Def_Port::get_Dimensions()
5471 {
5472 if (!checked) chk();
5473 return dimensions;
5474 }
5475
5476 void Def_Port::chk()
5477 {
5478 if (checked) return;
5479 checked = true;
5480 Error_Context cntxt(this, "In port definition `%s'",
5481 id->get_dispname().c_str());
5482 Common::Assignment *ass = type_ref->get_refd_assignment();
5483 if (ass) {
5484 if (ass->get_asstype() == A_TYPE) {
5485 Type *t = ass->get_Type()->get_type_refd_last();
a38c6d4c 5486 if (t->get_typetype() == Type::T_PORT) port_type = t;
5487 else type_ref->error("Type reference `%s' does not refer to a "
5488 "port type", type_ref->get_dispname().c_str());
970ed795
EL
5489 } else type_ref->error("Reference `%s' does not refer to a "
5490 "type", type_ref->get_dispname().c_str());
5491 }
5492 if (dimensions) dimensions->chk();
5493 if (w_attrib_path) {
5494 w_attrib_path->chk_global_attrib();
5495 w_attrib_path->chk_no_qualif();
5496 }
5497 }
5498
5499 bool Def_Port::chk_identical(Definition *p_def)
5500 {
5501 chk();
5502 p_def->chk();
5503 if (p_def->get_asstype() != A_PORT) {
5504 const char *dispname_str = id->get_dispname().c_str();
5505 error("Local definition `%s' is a port, but the definition inherited "
a38c6d4c 5506 "from component type `%s' is a %s", dispname_str,
970ed795
EL
5507 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
5508 p_def->note("The inherited definition of `%s' is here", dispname_str);
5509 return false;
5510 }
5511 Def_Port *p_def_port = dynamic_cast<Def_Port*>(p_def);
5512 if (!p_def_port) FATAL_ERROR("Def_Port::chk_identical()");
5513 if (port_type && p_def_port->port_type &&
a38c6d4c 5514 port_type != p_def_port->port_type) {
970ed795
EL
5515 const char *dispname_str = id->get_dispname().c_str();
5516 type_ref->error("Local port `%s' has type `%s', but the port inherited "
a38c6d4c 5517 "from component type `%s' has type `%s'", dispname_str,
5518 port_type->get_typename().c_str(),
970ed795 5519 p_def_port->get_my_scope()->get_fullname().c_str(),
a38c6d4c 5520 p_def_port->port_type->get_typename().c_str());
970ed795
EL
5521 p_def_port->note("The inherited port `%s' is here", dispname_str);
5522 return false;
5523 }
5524 if (dimensions) {
5525 if (p_def_port->dimensions) {
5526 if (!dimensions->is_identical(p_def_port->dimensions)) {
a38c6d4c 5527 const char *dispname_str = id->get_dispname().c_str();
5528 error("Local port `%s' and the port inherited from component type "
5529 "`%s' have different array dimensions", dispname_str,
970ed795 5530 p_def_port->get_my_scope()->get_fullname().c_str());
a38c6d4c 5531 p_def_port->note("The inherited port `%s' is here", dispname_str);
5532 return false;
5533 }
970ed795 5534 } else {
a38c6d4c 5535 const char *dispname_str = id->get_dispname().c_str();
5536 error("Local definition `%s' is a port array, but the definition "
5537 "inherited from component type `%s' is a single port", dispname_str,
970ed795 5538 p_def_port->get_my_scope()->get_fullname().c_str());
a38c6d4c 5539 p_def_port->note("The inherited port `%s' is here", dispname_str);
5540 return false;
970ed795
EL
5541 }
5542 } else if (p_def_port->dimensions) {
5543 const char *dispname_str = id->get_dispname().c_str();
5544 error("Local definition `%s' is a single port, but the definition "
a38c6d4c 5545 "inherited from component type `%s' is a port array", dispname_str,
970ed795
EL
5546 p_def_port->get_my_scope()->get_fullname().c_str());
5547 p_def_port->note("The inherited port `%s' is here", dispname_str);
5548 return false;
5549 }
5550 return true;
5551 }
5552
5553 void Def_Port::generate_code(output_struct *target, bool)
5554 {
5555 const string& t_genname = get_genname();
5556 const char *genname_str = t_genname.c_str();
5557 const string& type_genname = port_type->get_genname_value(my_scope);
5558 const string& dispname = id->get_dispname();
5559 if (dimensions) {
5560 // port array
5561 const string& array_type = dimensions->get_port_type(type_genname);
5562 const char *array_type_str = array_type.c_str();
5563 target->header.global_vars = mputprintf(target->header.global_vars,
a38c6d4c 5564 "extern %s %s;\n", array_type_str, genname_str);
970ed795 5565 target->source.global_vars = mputprintf(target->source.global_vars,
a38c6d4c 5566 "%s %s;\n", array_type_str, genname_str);
970ed795 5567 target->functions.pre_init = mputstr(target->functions.pre_init, "{\n"
a38c6d4c 5568 "static const char * const port_name = \"");
970ed795 5569 target->functions.pre_init = mputstr(target->functions.pre_init,
a38c6d4c 5570 dispname.c_str());
970ed795 5571 target->functions.pre_init = mputprintf(target->functions.pre_init,
a38c6d4c 5572 "\";\n"
970ed795 5573 "%s.set_name(port_name);\n"
a38c6d4c 5574 "}\n", genname_str);
970ed795
EL
5575 } else {
5576 // single port
5577 const char *type_genname_str = type_genname.c_str();
5578 target->header.global_vars = mputprintf(target->header.global_vars,
a38c6d4c 5579 "extern %s %s;\n", type_genname_str, genname_str);
970ed795 5580 target->source.global_vars = mputprintf(target->source.global_vars,
a38c6d4c 5581 "%s %s(\"%s\");\n", type_genname_str, genname_str, dispname.c_str());
970ed795
EL
5582 }
5583 target->functions.init_comp = mputprintf(target->functions.init_comp,
5584 "%s.activate_port();\n", genname_str);
5585 }
5586
5587 void Def_Port::generate_code(CodeGenHelper& cgh) {
5588 generate_code(cgh.get_current_outputstruct());
5589 }
5590
5591 char *Def_Port::generate_code_init_comp(char *str, Definition *base_defn)
5592 {
5593 return mputprintf(str, "%s.activate_port();\n",
5594 base_defn->get_genname_from_scope(my_scope).c_str());
5595 }
5596
5597 void Def_Port::dump_internal(unsigned level) const
5598 {
5599 DEBUG(level, "Port: %s", id->get_dispname().c_str());
5600 DEBUG(level + 1, "Port type:");
5601 type_ref->dump(level + 2);
5602 if (dimensions) dimensions->dump(level + 1);
5603 }
5604
5605 // =================================
5606 // ===== Def_Function_Base
5607 // =================================
5608
5609 Def_Function_Base::asstype_t Def_Function_Base::determine_asstype(
5610 bool is_external, bool has_return_type, bool returns_template)
5611 {
5612 if (is_external) {
5613 if (has_return_type) {
a38c6d4c 5614 if (returns_template) return A_EXT_FUNCTION_RTEMP;
5615 else return A_EXT_FUNCTION_RVAL;
970ed795 5616 } else {
a38c6d4c 5617 if (returns_template)
5618 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5619 return A_EXT_FUNCTION;
970ed795
EL
5620 }
5621 } else { // not an external function
5622 if (has_return_type) {
a38c6d4c 5623 if (returns_template) return A_FUNCTION_RTEMP;
5624 else return A_FUNCTION_RVAL;
970ed795 5625 } else {
a38c6d4c 5626 if (returns_template)
5627 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5628 return A_FUNCTION;
970ed795
EL
5629 }
5630 }
5631 }
5632
5633 Def_Function_Base::Def_Function_Base(const Def_Function_Base& p)
5634 : Definition(p), prototype(PROTOTYPE_NONE), input_type(0), output_type(0)
5635 {
5636 fp_list = p.fp_list->clone();
5637 fp_list->set_my_def(this);
5638 return_type = p.return_type ? p.return_type->clone() : 0;
5639 template_restriction = p.template_restriction;
5640 }
5641
5642 Def_Function_Base::Def_Function_Base(bool is_external, Identifier *p_id,
5643 FormalParList *p_fpl, Type *p_return_type, bool returns_template,
5644 template_restriction_t p_template_restriction)
5645 : Definition(determine_asstype(is_external, p_return_type != 0,
a38c6d4c 5646 returns_template), p_id), fp_list(p_fpl), return_type(p_return_type),
5647 prototype(PROTOTYPE_NONE), input_type(0), output_type(0),
970ed795
EL
5648 template_restriction(p_template_restriction)
5649 {
5650 if (!p_fpl) FATAL_ERROR("Def_Function_Base::Def_Function_Base()");
5651 fp_list->set_my_def(this);
5652 if (return_type) return_type->set_ownertype(Type::OT_FUNCTION_DEF, this);
5653 }
5654
5655 Def_Function_Base::~Def_Function_Base()
5656 {
5657 delete fp_list;
5658 delete return_type;
5659 }
5660
5661 void Def_Function_Base::set_fullname(const string& p_fullname)
5662 {
5663 Definition::set_fullname(p_fullname);
5664 fp_list->set_fullname(p_fullname + ".<formal_par_list>");
5665 if (return_type) return_type->set_fullname(p_fullname + ".<return_type>");
5666 }
5667
5668 void Def_Function_Base::set_my_scope(Scope *p_scope)
5669 {
5670 Definition::set_my_scope(p_scope);
5671 fp_list->set_my_scope(p_scope);
5672 if (return_type) return_type->set_my_scope(p_scope);
5673 }
5674
5675 Type *Def_Function_Base::get_Type()
5676 {
5677 if (!checked) chk();
5678 return return_type;
5679 }
5680
5681 FormalParList *Def_Function_Base::get_FormalParList()
5682 {
5683 if (!checked) chk();
5684 return fp_list;
5685 }
5686
5687 const char *Def_Function_Base::get_prototype_name() const
5688 {
5689 switch (prototype) {
5690 case PROTOTYPE_NONE:
5691 return "<no prototype>";
5692 case PROTOTYPE_CONVERT:
5693 return "convert";
5694 case PROTOTYPE_FAST:
5695 return "fast";
5696 case PROTOTYPE_BACKTRACK:
5697 return "backtrack";
5698 case PROTOTYPE_SLIDING:
5699 return "sliding";
5700 default:
5701 return "<unknown prototype>";
5702 }
5703 }
5704
5705 void Def_Function_Base::chk_prototype()
5706 {
5707 switch (prototype) {
5708 case PROTOTYPE_NONE:
5709 // return immediately
5710 return;
5711 case PROTOTYPE_CONVERT:
5712 case PROTOTYPE_FAST:
5713 case PROTOTYPE_BACKTRACK:
5714 case PROTOTYPE_SLIDING:
5715 // perform the checks below
5716 break;
5717 default:
5718 FATAL_ERROR("Def_Function_Base::chk_prototype()");
5719 }
5720 // checking the formal parameter list
5721 if (prototype == PROTOTYPE_CONVERT) {
5722 if (fp_list->get_nof_fps() == 1) {
a38c6d4c 5723 FormalPar *par = fp_list->get_fp_byIndex(0);
5724 if (par->get_asstype() == A_PAR_VAL_IN) {
5725 input_type = par->get_Type();
5726 } else {
5727 par->error("The parameter must be an `in' value parameter for "
5728 "attribute `prototype(%s)' instead of %s", get_prototype_name(),
5729 par->get_assname());
5730 }
970ed795 5731 } else {
a38c6d4c 5732 fp_list->error("The function must have one parameter instead of %lu "
5733 "for attribute `prototype(%s)'", (unsigned long) fp_list->get_nof_fps(),
5734 get_prototype_name());
970ed795
EL
5735 }
5736 } else { // not PROTOTYPE_CONVERT
5737 if (fp_list->get_nof_fps() == 2) {
a38c6d4c 5738 FormalPar *first_par = fp_list->get_fp_byIndex(0);
5739 if (prototype == PROTOTYPE_SLIDING) {
5740 if (first_par->get_asstype() == A_PAR_VAL_INOUT) {
5741 Type *first_par_type = first_par->get_Type();
5742 switch (first_par_type->get_type_refd_last()
5743 ->get_typetype_ttcn3()) {
5744 case Type::T_ERROR:
5745 case Type::T_OSTR:
5746 case Type::T_CSTR:
5747 case Type::T_BSTR:
5748 input_type = first_par_type;
5749 break;
5750 default:
5751 first_par_type->error("The type of the first parameter must be "
5752 "`octetstring' or `charstring' or `bitstring' for attribute "
5753 "`prototype(%s)' instead of `%s'", get_prototype_name(),
5754 first_par_type->get_typename().c_str());
5755 }
5756 } else {
5757 first_par->error("The first parameter must be an `inout' value "
5758 "parameter for attribute `prototype(%s)' instead of %s",
5759 get_prototype_name(), first_par->get_assname());
5760 }
5761 } else {
5762 if (first_par->get_asstype() == A_PAR_VAL_IN) {
5763 input_type = first_par->get_Type();
5764 } else {
5765 first_par->error("The first parameter must be an `in' value "
5766 "parameter for attribute `prototype(%s)' instead of %s",
5767 get_prototype_name(), first_par->get_assname());
5768 }
5769 }
5770 FormalPar *second_par = fp_list->get_fp_byIndex(1);
5771 if (second_par->get_asstype() == A_PAR_VAL_OUT) {
5772 output_type = second_par->get_Type();
5773 } else {
5774 second_par->error("The second parameter must be an `out' value "
5775 "parameter for attribute `prototype(%s)' instead of %s",
5776 get_prototype_name(), second_par->get_assname());
5777 }
970ed795 5778 } else {
a38c6d4c 5779 fp_list->error("The function must have two parameters for attribute "
5780 "`prototype(%s)' instead of %lu", get_prototype_name(),
5781 (unsigned long) fp_list->get_nof_fps());
970ed795
EL
5782 }
5783 }
5784 // checking the return type
5785 if (prototype == PROTOTYPE_FAST) {
5786 if (return_type) {
a38c6d4c 5787 return_type->error("The function cannot have return type for "
5788 "attribute `prototype(%s)'", get_prototype_name());
970ed795
EL
5789 }
5790 } else {
5791 if (return_type) {
a38c6d4c 5792 if (asstype == A_FUNCTION_RTEMP || asstype == A_EXT_FUNCTION_RTEMP)
5793 return_type->error("The function must return a value instead of a "
5794 "template for attribute `prototype(%s)'", get_prototype_name());
5795 if (prototype == PROTOTYPE_CONVERT) {
5796 output_type = return_type;
5797 } else {
5798 switch (return_type->get_type_refd_last()->get_typetype_ttcn3()) {
5799 case Type::T_ERROR:
5800 case Type::T_INT:
5801 break;
5802 default:
5803 return_type->error("The return type of the function must be "
5804 "`integer' instead of `%s' for attribute `prototype(%s)'",
5805 return_type->get_typename().c_str(), get_prototype_name());
5806 }
5807 }
970ed795 5808 } else {
a38c6d4c 5809 error("The function must have return type for attribute "
5810 "`prototype(%s)'", get_prototype_name());
970ed795
EL
5811 }
5812 }
5813 // checking the 'runs on' clause
5814 if (get_RunsOnType()) {
5815 error("The function cannot have `runs on' clause for attribute "
a38c6d4c 5816 "`prototype(%s)'", get_prototype_name());
970ed795
EL
5817 }
5818 }
5819
5820 Type *Def_Function_Base::get_input_type()
5821 {
5822 if (!checked) chk();
5823 return input_type;
5824 }
5825
5826 Type *Def_Function_Base::get_output_type()
5827 {
5828 if (!checked) chk();
5829 return output_type;
5830 }
5831
5832
5833 // =================================
5834 // ===== Def_Function
5835 // =================================
5836
5837 Def_Function::Def_Function(Identifier *p_id, FormalParList *p_fpl,
5838 Reference *p_runs_on_ref, Type *p_return_type,
5839 bool returns_template,
5840 template_restriction_t p_template_restriction,
5841 StatementBlock *p_block)
5842 : Def_Function_Base(false, p_id, p_fpl, p_return_type, returns_template,
5843 p_template_restriction),
a38c6d4c 5844 runs_on_ref(p_runs_on_ref), runs_on_type(0), block(p_block),
5845 is_startable(false), transparent(false)
970ed795
EL
5846 {
5847 if (!p_block) FATAL_ERROR("Def_Function::Def_Function()");
5848 block->set_my_def(this);
5849 }
5850
5851 Def_Function::~Def_Function()
5852 {
5853 delete runs_on_ref;
5854 delete block;
5855 }
5856
5857 Def_Function *Def_Function::clone() const
5858 {
5859 FATAL_ERROR("Def_Function::clone");
5860 }
5861
5862 void Def_Function::set_fullname(const string& p_fullname)
5863 {
5864 Def_Function_Base::set_fullname(p_fullname);
5865 if (runs_on_ref) runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>");
5866 block->set_fullname(p_fullname + ".<statement_block>");
5867 }
5868
5869 void Def_Function::set_my_scope(Scope *p_scope)
5870 {
5871 bridgeScope.set_parent_scope(p_scope);
5872 bridgeScope.set_scopeMacro_name(id->get_dispname());
5873
5874 Def_Function_Base::set_my_scope(&bridgeScope);
5875 if (runs_on_ref) runs_on_ref->set_my_scope(&bridgeScope);
5876 block->set_my_scope(fp_list);
5877 }
5878
5879 Type *Def_Function::get_RunsOnType()
5880 {
5881 if (!checked) chk();
5882 return runs_on_type;
5883 }
5884
5885 RunsOnScope *Def_Function::get_runs_on_scope(Type *comptype)
5886 {
5887 Module *my_module = dynamic_cast<Module*>(my_scope->get_scope_mod());
5888 if (!my_module) FATAL_ERROR("Def_Function::get_runs_on_scope()");
5889 return my_module->get_runs_on_scope(comptype);
5890 }
5891
5892 void Def_Function::chk()
5893 {
5894 if (checked) return;
5895 checked = true;
5896 Error_Context cntxt(this, "In function definition `%s'",
5897 id->get_dispname().c_str());
5898 // checking the `runs on' clause
5899 if (runs_on_ref) {
5900 Error_Context cntxt2(runs_on_ref, "In `runs on' clause");
5901 runs_on_type = runs_on_ref->chk_comptype_ref();
5902 // override the scope of the formal parameter list
5903 if (runs_on_type) {
5904 Scope *runs_on_scope = get_runs_on_scope(runs_on_type);
5905 runs_on_scope->set_parent_scope(my_scope);
5906 fp_list->set_my_scope(runs_on_scope);
5907 }
5908 }
5909 // checking the formal parameter list
5910 fp_list->chk(asstype);
5911 // checking of return type
5912 if (return_type) {
5913 Error_Context cntxt2(return_type, "In return type");
5914 return_type->chk();
5915 return_type->chk_as_return_type(asstype == A_FUNCTION_RVAL,"function");
5916 }
5917 // decision of startability
5918 is_startable = runs_on_ref != 0;
5919 if (is_startable && !fp_list->get_startability()) is_startable = false;
5920 if (is_startable && return_type && return_type->is_component_internal())
a38c6d4c 5921 is_startable = false;
970ed795
EL
5922 // checking of statement block
5923 block->chk();
5924 if (return_type) {
5925 // checking the presence of return statements
5926 switch (block->has_return()) {
5927 case StatementBlock::RS_NO:
5928 error("The function has return type, but it does not have any return "
a38c6d4c 5929 "statement");
970ed795
EL
5930 break;
5931 case StatementBlock::RS_MAYBE:
a38c6d4c 5932 error("The function has return type, but control might leave it "
5933 "without reaching a return statement");
970ed795 5934 default:
a38c6d4c 5935 break;
970ed795
EL
5936 }
5937 }
5938 if (!semantic_check_only) {
5939 fp_list->set_genname(get_genname());
5940 block->set_code_section(GovernedSimple::CS_INLINE);
5941 }
5942 if (w_attrib_path) {
5943 w_attrib_path->chk_global_attrib();
5944 w_attrib_path->chk_no_qualif();
5945 Ttcn::ExtensionAttributes * extattrs = parse_extattributes(w_attrib_path);
5946 if (extattrs != 0) { // NULL means parsing error
5947 size_t num_atrs = extattrs->size();
5948 for (size_t i=0; i < num_atrs; ++i) {
5949 ExtensionAttribute &ea = extattrs->get(i);
5950 switch (ea.get_type()) {
5951 case ExtensionAttribute::PROTOTYPE: {
5952 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE) {
5953 ea.error("Duplicate attribute `prototype'");
5954 }
5955 Def_Function_Base::prototype_t proto = ea.get_proto();
5956 set_prototype(proto);
5957 break; }
5958
5959 case ExtensionAttribute::ANYTYPELIST: // ignore it
5960 case ExtensionAttribute::NONE: // erroneous, do not issue an error
5961 break;
5962
5963 case ExtensionAttribute::TRANSPARENT:
5964 transparent = true;
5965 break;
5966
5967 case ExtensionAttribute::ENCODE:
5968 case ExtensionAttribute::DECODE:
5969 case ExtensionAttribute::ERRORBEHAVIOR:
5970 case ExtensionAttribute::PRINTING:
5971 ea.error("Extension attribute 'encode', 'decode', 'errorbehavior'"
5972 " or 'printing' can only be applied to external functions");
5973 // fall through
5974
5975 default: // complain
5976 ea.error("Function definition can only have the 'prototype'"
5977 " extension attribute");
5978 break;
5979 }
5980 }
5981 delete extattrs;
5982 }
5983 }
5984 chk_prototype();
5985 }
5986
5987 bool Def_Function::chk_startable()
5988 {
5989 if (!checked) chk();
5990 if (is_startable) return true;
5991 if (!runs_on_ref) error("Function `%s' cannot be started on a parallel "
5992 "test component because it does not have `runs on' clause",
5993 get_fullname().c_str());
5994 fp_list->chk_startability("Function", get_fullname().c_str());
5995 if (return_type && return_type->is_component_internal()) {
5996 map<Type*,void> type_chain;
5997 char* err_str = mprintf("the return type or embedded in the return type "
5998 "of function `%s' if it is started on a parallel test component",
5999 get_fullname().c_str());
6000 return_type->chk_component_internal(type_chain, err_str);
6001 Free(err_str);
6002 }
6003 return false;
6004 }
6005
6006 void Def_Function::generate_code(output_struct *target, bool)
6007 {
6008 transparency_holder glass(*this);
6009 const string& t_genname = get_genname();
6010 const char *genname_str = t_genname.c_str();
6011 const char *dispname_str = id->get_dispname().c_str();
6012 string return_type_name;
6013 switch (asstype) {
6014 case A_FUNCTION:
6015 return_type_name = "void";
6016 break;
6017 case A_FUNCTION_RVAL:
6018 return_type_name = return_type->get_genname_value(my_scope);
6019 break;
6020 case A_FUNCTION_RTEMP:
6021 return_type_name = return_type->get_genname_template(my_scope);
6022 break;
6023 default:
6024 FATAL_ERROR("Def_Function::generate_code()");
6025 }
6026 const char *return_type_str = return_type_name.c_str();
6027 char *formal_par_list = fp_list->generate_code(memptystr());
6028 fp_list->generate_code_defval(target);
6029 // function prototype
6030 target->header.function_prototypes =
6031 mputprintf(target->header.function_prototypes, "extern %s %s(%s);\n",
a38c6d4c 6032 return_type_str, genname_str, formal_par_list);
970ed795
EL
6033
6034 // function body
6035 char *body = mprintf("%s %s(%s)\n"
6036 "{\n", return_type_str, genname_str, formal_par_list);
6037 body = create_location_object(body, "FUNCTION", dispname_str);
6038 if (!enable_set_bound_out_param)
6039 body = fp_list->generate_code_set_unbound(body); // conform the standard out parameter is unbound
6040 body = fp_list->generate_shadow_objects(body);
6041 body = block->generate_code(body);
6042 body = mputstr(body, "}\n\n");
6043 target->source.function_bodies = mputstr(target->source.function_bodies,
6044 body);
6045 Free(body);
6046
6047 if (is_startable) {
6048 size_t nof_fps = fp_list->get_nof_fps();
6049 // starter function (stub)
a38c6d4c 6050 // function prototype
6051 target->header.function_prototypes =
6052 mputprintf(target->header.function_prototypes,
6053 "extern void start_%s(const COMPONENT& component_reference%s%s);\n",
6054 genname_str, nof_fps>0?", ":"", formal_par_list);
6055 // function body
6056 body = mprintf("void start_%s(const COMPONENT& component_reference%s"
6057 "%s)\n"
6058 "{\n"
6059 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6060 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6061 genname_str, nof_fps>0?", ":"", formal_par_list, dispname_str);
6062 for (size_t i = 0; i < nof_fps; i++) {
6063 if (i > 0) body = mputstr(body,
970ed795 6064 "TTCN_Logger::log_event_str(\", \");\n");
a38c6d4c 6065 body = mputprintf(body, "%s.log();\n",
6066 fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
6067 }
6068 body = mputprintf(body,
6069 "TTCN_Logger::log_event_str(\") on component \");\n"
6070 "component_reference.log();\n"
6071 "TTCN_Logger::log_char('.');\n"
6072 "TTCN_Logger::end_event();\n"
6073 "Text_Buf text_buf;\n"
6074 "TTCN_Runtime::prepare_start_component(component_reference, "
6075 "\"%s\", \"%s\", text_buf);\n",
6076 my_scope->get_scope_mod()->get_modid().get_dispname().c_str(),
6077 dispname_str);
6078 for (size_t i = 0; i < nof_fps; i++) {
6079 body = mputprintf(body, "%s.encode_text(text_buf);\n",
6080 fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
6081 }
6082 body = mputstr(body, "TTCN_Runtime::send_start_component(text_buf);\n"
6083 "}\n\n");
6084 target->source.function_bodies = mputstr(target->source.function_bodies,
6085 body);
6086 Free(body);
970ed795
EL
6087
6088 // an entry in start_ptc_function
6089 body = mprintf("if (!strcmp(function_name, \"%s\")) {\n",
a38c6d4c 6090 dispname_str);
970ed795 6091 if (nof_fps > 0) {
a38c6d4c 6092 body = fp_list->generate_code_object(body, "", ' ');
6093 for (size_t i = 0; i < nof_fps; i++) {
6094 body = mputprintf(body, "%s.decode_text(function_arguments);\n",
6095 fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
6096 }
6097 body = mputprintf(body,
6098 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6099 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6100 dispname_str);
6101 for (size_t i = 0; i < nof_fps; i++) {
6102 if (i > 0) body = mputstr(body,
970ed795 6103 "TTCN_Logger::log_event_str(\", \");\n");
a38c6d4c 6104 body = mputprintf(body, "%s.log();\n",
6105 fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
6106 }
6107 body = mputstr(body, "TTCN_Logger::log_event_str(\").\");\n"
6108 "TTCN_Logger::end_event();\n");
970ed795 6109 } else {
a38c6d4c 6110 body = mputprintf(body,
6111 "TTCN_Logger::log_str(TTCN_Logger::PARALLEL_PTC, \"Starting function "
970ed795
EL
6112 "%s().\");\n", dispname_str);
6113 }
6114 body = mputstr(body,
a38c6d4c 6115 "TTCN_Runtime::function_started(function_arguments);\n");
970ed795 6116 char *actual_par_list =
a38c6d4c 6117 fp_list->generate_code_actual_parlist(memptystr(), "");
970ed795
EL
6118 bool return_value_kept = false;
6119 if (asstype == A_FUNCTION_RVAL) {
a38c6d4c 6120 // the return value is kept only if the function returns a value
6121 // (rather than a template) and the return type has the "done"
6122 // extension attribute
6123 for (Type *t = return_type; ; t = t->get_type_refd()) {
6124 if (t->has_done_attribute()) {
6125 return_value_kept = true;
6126 break;
6127 } else if (!t->is_ref()) break;
6128 }
970ed795
EL
6129 }
6130 if (return_value_kept) {
a38c6d4c 6131 const string& return_type_dispname = return_type->get_typename();
6132 const char *return_type_dispname_str = return_type_dispname.c_str();
6133 body = mputprintf(body, "%s ret_val(%s(%s));\n"
6134 "TTCN_Logger::begin_event(TTCN_PARALLEL);\n"
6135 "TTCN_Logger::log_event_str(\"Function %s returned %s : \");\n"
6136 "ret_val.log();\n"
6137 "Text_Buf text_buf;\n"
6138 "TTCN_Runtime::prepare_function_finished(\"%s\", text_buf);\n"
6139 "ret_val.encode_text(text_buf);\n"
6140 "TTCN_Runtime::send_function_finished(text_buf);\n",
6141 return_type_str, genname_str, actual_par_list, dispname_str,
6142 return_type_dispname_str, return_type_dispname_str);
970ed795 6143 } else {
a38c6d4c 6144 body = mputprintf(body, "%s(%s);\n"
6145 "TTCN_Runtime::function_finished(\"%s\");\n",
6146 genname_str, actual_par_list, dispname_str);
970ed795
EL
6147 }
6148 Free(actual_par_list);
6149 body = mputstr(body, "return TRUE;\n"
a38c6d4c 6150 "} else ");
970ed795
EL
6151 target->functions.start = mputstr(target->functions.start, body);
6152 Free(body);
6153 }
6154 Free(formal_par_list);
6155
6156 target->functions.pre_init = mputprintf(target->functions.pre_init,
6157 "%s.add_function(\"%s\", (genericfunc_t)&%s, ", get_module_object_name(),
6158 dispname_str, genname_str);
6159 if(is_startable)
6160 target->functions.pre_init = mputprintf(target->functions.pre_init,
6161 "(genericfunc_t)&start_%s);\n", genname_str);
6162 else
6163 target->functions.pre_init = mputstr(target->functions.pre_init,
6164 "NULL);\n");
6165 }
6166
6167 void Def_Function::generate_code(CodeGenHelper& cgh) {
6168 generate_code(cgh.get_current_outputstruct());
6169 }
6170
6171 void Def_Function::dump_internal(unsigned level) const
6172 {
6173 DEBUG(level, "Function: %s", id->get_dispname().c_str());
6174 DEBUG(level + 1, "Parameters:");
6175 fp_list->dump(level + 1);
6176 if (runs_on_ref) {
6177 DEBUG(level + 1, "Runs on clause:");
6178 runs_on_ref->dump(level + 2);
6179 }
6180 if (return_type) {
6181 DEBUG(level + 1, "Return type:");
6182 return_type->dump(level + 2);
6183 if (asstype == A_FUNCTION_RTEMP) DEBUG(level + 1, "Returns template");
6184 }
6185 if (prototype != PROTOTYPE_NONE)
6186 DEBUG(level + 1, "Prototype: %s", get_prototype_name());
6187 //DEBUG(level + 1, "Statement block:");
6188 block->dump(level + 1);
6189 }
6190
6191 void Def_Function::set_parent_path(WithAttribPath* p_path) {
6192 Def_Function_Base::set_parent_path(p_path);
6193 block->set_parent_path(w_attrib_path);
6194 }
6195
6196 // =================================
6197 // ===== Def_ExtFunction
6198 // =================================
6199
6200 Def_ExtFunction::~Def_ExtFunction()
6201 {
6202 delete encoding_options;
6203 delete eb_list;
6204 if (NULL != json_printing) {
6205 delete json_printing;
6206 }
6207 }
6208
6209 Def_ExtFunction *Def_ExtFunction::clone() const
6210 {
6211 FATAL_ERROR("Def_ExtFunction::clone");
6212 }
6213
6214 void Def_ExtFunction::set_fullname(const string& p_fullname)
6215 {
6216 Def_Function_Base::set_fullname(p_fullname);
6217 if (eb_list) eb_list->set_fullname(p_fullname + ".<errorbehavior_list>");
6218 }
6219
6220 void Def_ExtFunction::set_encode_parameters(Type::MessageEncodingType_t
6221 p_encoding_type, string *p_encoding_options)
6222 {
6223 function_type = EXTFUNC_ENCODE;
6224 encoding_type = p_encoding_type;
6225 delete encoding_options;
6226 encoding_options = p_encoding_options;
6227 }
6228
6229 void Def_ExtFunction::set_decode_parameters(Type::MessageEncodingType_t
6230 p_encoding_type, string *p_encoding_options)
6231 {
6232 function_type = EXTFUNC_DECODE;
6233 encoding_type = p_encoding_type;
6234 delete encoding_options;
6235 encoding_options = p_encoding_options;
6236 }
6237
6238 void Def_ExtFunction::add_eb_list(Ttcn::ErrorBehaviorList *p_eb_list)
6239 {
6240 if (!p_eb_list) FATAL_ERROR("Def_ExtFunction::add_eb_list()");
6241 if (eb_list) {
6242 eb_list->steal_ebs(p_eb_list);
6243 delete p_eb_list;
6244 } else {
6245 eb_list = p_eb_list;
6246 eb_list->set_fullname(get_fullname() + ".<errorbehavior_list>");
6247 }
6248 }
6249
6250 void Def_ExtFunction::chk_function_type()
6251 {
6252 switch (function_type) {
6253 case EXTFUNC_MANUAL:
6254 if (eb_list) {
a38c6d4c 6255 eb_list->error("Attribute `errorbehavior' can only be used together "
6256 "with `encode' or `decode'");
6257 eb_list->chk();
970ed795
EL
6258 }
6259 break;
6260 case EXTFUNC_ENCODE:
6261 switch (prototype) {
6262 case PROTOTYPE_NONE:
a38c6d4c 6263 error("Attribute `encode' cannot be used without `prototype'");
6264 break;
970ed795
EL
6265 case PROTOTYPE_BACKTRACK:
6266 case PROTOTYPE_SLIDING:
a38c6d4c 6267 error("Attribute `encode' cannot be used with `prototype(%s)'",
6268 get_prototype_name());
970ed795
EL
6269 default: /* CONVERT and FAST allowed */
6270 break;
6271 }
6272
6273 if (input_type) {
6274 if (!input_type->has_encoding(encoding_type)) {
6275 input_type->error("Input type `%s' does not support %s encoding",
6276 input_type->get_typename().c_str(),
6277 Type::get_encoding_name(encoding_type));
6278 }
6279 if (Common::Type::CT_XER == encoding_type
6280 && input_type->get_type_refd_last()->is_untagged()) {
6281 // "untagged" on the (toplevel) input type will have no effect.
6282 warning("UNTAGGED encoding attribute is ignored on top-level type");
6283 }
6284 }
6285 if (output_type) {
a38c6d4c 6286 if(encoding_type == Common::Type::CT_TEXT){ // the TEXT encoding support both octetstring ans charstring stream type
6287 Type *stream_type = Type::get_stream_type(encoding_type,0);
6288 Type *stream_type2 = Type::get_stream_type(encoding_type,1);
6289 if ( (!stream_type->is_identical(output_type)) && (!stream_type2->is_identical(output_type)) ) {
6290 input_type->error("The output type of %s encoding should be `%s' or `%s' "
6291 "instead of `%s'", Type::get_encoding_name(encoding_type),
6292 stream_type->get_typename().c_str(),
6293 stream_type2->get_typename().c_str(),
6294 input_type->get_typename().c_str());
6295 }
6296 } else {
6297 Type *stream_type = Type::get_stream_type(encoding_type);
6298 if (!stream_type->is_identical(output_type)) {
6299 input_type->error("The output type of %s encoding should be `%s' "
6300 "instead of `%s'", Type::get_encoding_name(encoding_type),
6301 stream_type->get_typename().c_str(),
6302 input_type->get_typename().c_str());
6303 }
6304 }
970ed795
EL
6305 }
6306 if (eb_list) eb_list->chk();
6307 chk_allowed_encode();
6308 break;
6309 case EXTFUNC_DECODE:
6310 if (prototype == PROTOTYPE_NONE) {
a38c6d4c 6311 error("Attribute `decode' cannot be used without `prototype'");
970ed795
EL
6312 }
6313 if (input_type) {
a38c6d4c 6314 if(encoding_type == Common::Type::CT_TEXT){ // the TEXT encoding support both octetstring ans charstring stream type
6315 Type *stream_type = Type::get_stream_type(encoding_type,0);
6316 Type *stream_type2 = Type::get_stream_type(encoding_type,1);
6317 if ( (!stream_type->is_identical(input_type)) && (!stream_type2->is_identical(input_type)) ) {
6318 input_type->error("The input type of %s encoding should be `%s' or `%s' "
6319 "instead of `%s'", Type::get_encoding_name(encoding_type),
6320 stream_type->get_typename().c_str(),
6321 stream_type2->get_typename().c_str(),
6322 input_type->get_typename().c_str());
6323 }
6324 } else {
6325 Type *stream_type = Type::get_stream_type(encoding_type);
6326 if (!stream_type->is_identical(input_type)) {
6327 input_type->error("The input type of %s encoding should be `%s' "
6328 "instead of `%s'", Type::get_encoding_name(encoding_type),
6329 stream_type->get_typename().c_str(),
6330 input_type->get_typename().c_str());
6331 }
6332 }
6333
970ed795
EL
6334 }
6335 if (output_type && !output_type->has_encoding(encoding_type)) {
a38c6d4c 6336 output_type->error("Output type `%s' does not support %s encoding",
6337 output_type->get_typename().c_str(),
6338 Type::get_encoding_name(encoding_type));
970ed795
EL
6339 }
6340 if (eb_list) eb_list->chk();
6341 chk_allowed_encode();
6342 break;
6343 default:
6344 FATAL_ERROR("Def_ExtFunction::chk()");
6345 }
6346 }
6347
6348 void Def_ExtFunction::chk_allowed_encode()
6349 {
6350 switch (encoding_type) {
6351 case Type::CT_BER:
6352 if (enable_ber()) return; // ok
6353 break;
6354 case Type::CT_RAW:
6355 if (enable_raw()) return; // ok
6356 break;
6357 case Type::CT_TEXT:
6358 if (enable_text()) return; // ok
6359 break;
6360 case Type::CT_XER:
6361 if (enable_xer()) return; // ok
6362 break;
6363 case Type::CT_PER:
6364 if (enable_per()) return; // ok?
6365 break;
6366 case Type::CT_JSON:
6367 if (enable_json()) return;
6368 break;
6369 default:
6370 FATAL_ERROR("Def_ExtFunction::chk_allowed_encode");
6371 break;
6372 }
6373
6374 error("%s encoding is disallowed by license or commandline options",
6375 Type::get_encoding_name(encoding_type));
6376 }
6377
6378 void Def_ExtFunction::chk()
6379 {
6380 if (checked) return;
6381 checked = true;
6382 Error_Context cntxt(this, "In external function definition `%s'",
6383 id->get_dispname().c_str());
6384 fp_list->chk(asstype);
6385 if (return_type) {
6386 Error_Context cntxt2(return_type, "In return type");
6387 return_type->chk();
6388 return_type->chk_as_return_type(asstype == A_EXT_FUNCTION_RVAL,
a38c6d4c 6389 "external function");
970ed795
EL
6390 }
6391 if (!semantic_check_only) fp_list->set_genname(get_genname());
6392 if (w_attrib_path) {
6393 w_attrib_path->chk_global_attrib();
6394 w_attrib_path->chk_no_qualif();
6395 const Ttcn::ExtensionAttributes * extattrs = parse_extattributes(w_attrib_path);
6396 if (extattrs != 0) {
6397 size_t num_atrs = extattrs->size();
6398 for (size_t i=0; i < num_atrs; ++i) {
6399 ExtensionAttribute &ea = extattrs->get(i);
6400 switch (ea.get_type()) {
6401 case ExtensionAttribute::PROTOTYPE: {
6402 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE) {
6403 ea.error("Duplicate attribute `prototype'");
6404 }
6405 Def_Function_Base::prototype_t proto = ea.get_proto();
6406 set_prototype(proto);
6407 break; }
6408
6409 case ExtensionAttribute::ENCODE: {
6410 switch (get_function_type()) {
6411 case Def_ExtFunction::EXTFUNC_MANUAL:
6412 break;
6413 case Def_ExtFunction::EXTFUNC_ENCODE: {
6414 ea.error("Duplicate attribute `encode'");
6415 break; }
6416 case Def_ExtFunction::EXTFUNC_DECODE: {
6417 ea.error("Attributes `decode' and `encode' "
6418 "cannot be used at the same time");
6419 break; }
6420 default:
6421 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6422 }
6423 Type::MessageEncodingType_t et;
6424 string *opt;
6425 ea.get_encdec_parameters(et, opt);
6426 set_encode_parameters(et, opt);
6427 break; }
6428
6429 case ExtensionAttribute::ERRORBEHAVIOR: {
6430 add_eb_list(ea.get_eb_list());
6431 break; }
6432
6433 case ExtensionAttribute::DECODE: {
6434 switch (get_function_type()) {
6435 case Def_ExtFunction::EXTFUNC_MANUAL:
6436 break;
6437 case Def_ExtFunction::EXTFUNC_ENCODE: {
6438 ea.error("Attributes `encode' and `decode' "
6439 "cannot be used at the same time");
6440 break; }
6441 case Def_ExtFunction::EXTFUNC_DECODE: {
6442 ea.error("Duplicate attribute `decode'");
6443 break; }
6444 default:
6445 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6446 }
6447 Type::MessageEncodingType_t et;
6448 string *opt;
6449 ea.get_encdec_parameters(et, opt);
6450 set_decode_parameters(et, opt);
6451 break; }
6452
6453 case ExtensionAttribute::PRINTING: {
6454 json_printing = ea.get_printing();
6455 break; }
6456
6457 case ExtensionAttribute::ANYTYPELIST:
6458 // ignore, because we can't distinguish between a local
6459 // "extension anytype" (which is bogus) and an inherited one
6460 // (which was meant for a type definition)
6461 break;
6462
6463 case ExtensionAttribute::NONE:
6464 // Ignore, do not issue "wrong type" error
6465 break;
6466
6467 default:
6468 ea.error(
6469 "Only the following extension attributes may be applied to "
6470 "external functions: 'prototype', 'encode', 'decode', 'errorbehavior'");
6471 break;
6472 } // switch type
6473 } // next attribute
6474 delete extattrs;
6475 } // if extatrs
6476 }
6477 chk_prototype();
6478 chk_function_type();
6479
6480 if (NULL != json_printing && (EXTFUNC_ENCODE != function_type ||
6481 Type::CT_JSON != encoding_type)) {
6482 error("Attribute 'printing' is only allowed for JSON encoding functions.");
6483 }
6484 }
6485
6486 char *Def_ExtFunction::generate_code_encode(char *str)
6487 {
6488 const char *function_name = id->get_dispname().c_str();
6489 const char *first_par_name =
6490 fp_list->get_fp_byIndex(0)->get_id().get_name().c_str();
6491 // producing debug printout of the input PDU
6492 str = mputprintf(str,
6493#ifndef NDEBUG
6494 "// written by %s in " __FILE__ " at %d\n"
6495#endif
6496 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6497 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6498 "TTCN_Logger::log_event_str(\"%s(): Encoding %s: \");\n"
6499 "%s.log();\n"
6500 "TTCN_Logger::end_event();\n"
6501 "}\n"
6502#ifndef NDEBUG
6503 , __FUNCTION__, __LINE__
6504#endif
6505 , function_name, input_type->get_typename().c_str(), first_par_name);
6506 // setting error behavior
6507 if (eb_list) str = eb_list->generate_code(str);
6508 else str = mputstr(str, "TTCN_EncDec::set_error_behavior("
6509 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6510 // encoding PDU into the buffer
6511 str = mputstr(str, "TTCN_Buffer ttcn_buffer;\n");
6512 str = mputprintf(str, "%s.encode(%s_descr_, ttcn_buffer, TTCN_EncDec::CT_%s",
6513 first_par_name,
6514 input_type->get_genname_typedescriptor(my_scope).c_str(),
6515 Type::get_encoding_name(encoding_type));
6516 if (encoding_type == Type::CT_JSON) {
6517 if (json_printing != NULL) {
6518 str = json_printing->generate_code(str);
6519 } else {
6520 str = mputstr(str, ", 0");
6521 }
6522 }
6523 if (encoding_options) str = mputprintf(str, ", %s",
6524 encoding_options->c_str());
6525 str = mputstr(str, ");\n");
6526 const char *result_name;
6527 switch (prototype) {
6528 case PROTOTYPE_CONVERT:
6529 result_name = "ret_val";
6530 // creating a local variable for the result stream
6531 str = mputprintf(str, "%s ret_val;\n",
a38c6d4c 6532 output_type->get_genname_value(my_scope).c_str());
970ed795
EL
6533 break;
6534 case PROTOTYPE_FAST:
6535 result_name = fp_list->get_fp_byIndex(1)->get_id().get_name().c_str();
6536 break;
6537 default:
6538 FATAL_ERROR("Def_ExtFunction::generate_code_encode()");
6539 result_name = 0;
6540 }
6541 // taking the result from the buffer and producing debug printout
6542 str = mputprintf(str, "ttcn_buffer.get_string(%s);\n"
6543 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6544 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6545 "TTCN_Logger::log_event_str(\"%s(): Stream after encoding: \");\n"
6546 "%s.log();\n"
6547 "TTCN_Logger::end_event();\n"
6548 "}\n", result_name, function_name, result_name);
6549 // returning the result stream if necessary
6550 if (prototype == PROTOTYPE_CONVERT) str = mputstr(str, "return ret_val;\n");
6551 return str;
6552 }
6553
6554 char *Def_ExtFunction::generate_code_decode(char *str)
6555 {
6556 const char *function_name = id->get_dispname().c_str();
6557 const char *first_par_name =
6558 fp_list->get_fp_byIndex(0)->get_id().get_name().c_str();
6559 // producing debug printout of the input stream
6560 str = mputprintf(str,
6561#ifndef NDEBUG
6562 "// written by %s in " __FILE__ " at %d\n"
6563#endif
6564 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6565 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6566 "TTCN_Logger::log_event_str(\"%s(): Stream before decoding: \");\n"
6567 "%s.log();\n"
6568 "TTCN_Logger::end_event();\n"
6569 "}\n"
6570#ifndef NDEBUG
6571 , __FUNCTION__, __LINE__
6572#endif
6573 , function_name, first_par_name);
6574 // setting error behavior
6575 if (eb_list) str = eb_list->generate_code(str);
6576 else if (prototype == PROTOTYPE_BACKTRACK || prototype == PROTOTYPE_SLIDING) {
a38c6d4c 6577 str = mputstr(str, "TTCN_EncDec::set_error_behavior("
970ed795
EL
6578 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);\n");
6579 } else str = mputstr(str, "TTCN_EncDec::set_error_behavior("
6580 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6581 // creating a buffer from the input stream
6582 str = mputprintf(str, "TTCN_EncDec::clear_error();\n"
6583 "TTCN_Buffer ttcn_buffer(%s);\n", first_par_name);
6584 const char *result_name;
6585 if (prototype == PROTOTYPE_CONVERT) {
6586 // creating a local variable for the result
6587 str = mputprintf(str, "%s ret_val;\n",
a38c6d4c 6588 output_type->get_genname_value(my_scope).c_str());
970ed795
EL
6589 result_name = "ret_val";
6590 } else {
6591 result_name = fp_list->get_fp_byIndex(1)->get_id().get_name().c_str();
6592 }
6593 if(encoding_type==Type::CT_TEXT){
6594 str = mputprintf(str,
6595 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6596 " TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_LOG_MATCHING, TTCN_EncDec::EB_WARNING);\n"
6597 "}\n");
6598 }
6599 str = mputprintf(str, "%s.decode(%s_descr_, ttcn_buffer, "
6600 "TTCN_EncDec::CT_%s", result_name,
6601 output_type->get_genname_typedescriptor(my_scope).c_str(),
6602 Type::get_encoding_name(encoding_type));
6603 if (encoding_options) str = mputprintf(str, ", %s",
6604 encoding_options->c_str());
6605 str = mputstr(str, ");\n");
6606 // producing debug printout of the result PDU
6607 str = mputprintf(str,
6608 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6609 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6610 "TTCN_Logger::log_event_str(\"%s(): Decoded %s: \");\n"
6611 "%s.log();\n"
6612 "TTCN_Logger::end_event();\n"
6613 "}\n", function_name, output_type->get_typename().c_str(), result_name);
6614 if (prototype != PROTOTYPE_SLIDING) {
6615 // checking for remaining data in the buffer if decoding was successful
6616 str = mputprintf(str, "if (TTCN_EncDec::get_last_error_type() == "
a38c6d4c 6617 "TTCN_EncDec::ET_NONE) {\n"
6618 "if (ttcn_buffer.get_pos() < ttcn_buffer.get_len()-1 && "
6619 "TTCN_Logger::log_this_event(TTCN_WARNING)) {\n"
6620 "ttcn_buffer.cut();\n"
6621 "%s remaining_stream;\n"
6622 "ttcn_buffer.get_string(remaining_stream);\n"
6623 "TTCN_Logger::begin_event(TTCN_WARNING);\n"
6624 "TTCN_Logger::log_event_str(\"%s(): Warning: Data remained at the end "
6625 "of the stream after successful decoding: \");\n"
6626 "remaining_stream.log();\n"
6627 "TTCN_Logger::end_event();\n"
6628 "}\n", input_type->get_genname_value(my_scope).c_str(), function_name);
970ed795
EL
6629 // closing the block and returning the appropriate result or status code
6630 if (prototype == PROTOTYPE_BACKTRACK) {
a38c6d4c 6631 str = mputstr(str, "return 0;\n"
6632 "} else return 1;\n");
970ed795 6633 } else {
a38c6d4c 6634 str = mputstr(str, "}\n");
6635 if (prototype == PROTOTYPE_CONVERT)
970ed795
EL
6636 str = mputstr(str, "return ret_val;\n");
6637 }
6638 } else {
6639 // result handling and debug printout for sliding decoders
6640 str = mputprintf(str, "switch (TTCN_EncDec::get_last_error_type()) {\n"
a38c6d4c 6641 "case TTCN_EncDec::ET_NONE:\n"
6642 // TTCN_Buffer::get_string will call OCTETSTRING::clean_up()
6643 "ttcn_buffer.cut();\n"
6644 "ttcn_buffer.get_string(%s);\n"
6645 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6646 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6647 "TTCN_Logger::log_event_str(\"%s(): Stream after decoding: \");\n"
6648 "%s.log();\n"
6649 "TTCN_Logger::end_event();\n"
6650 "}\n"
6651 "return 0;\n"
970ed795 6652 "case TTCN_EncDec::ET_INCOMPL_MSG:\n"
a38c6d4c 6653 "case TTCN_EncDec::ET_LEN_ERR:\n"
6654 "return 2;\n"
6655 "default:\n"
6656 "return 1;\n"
6657 "}\n", first_par_name, function_name, first_par_name);
970ed795
EL
6658 }
6659 return str;
6660 }
6661
6662 void Def_ExtFunction::generate_code(output_struct *target, bool)
6663 {
6664 const string& t_genname = get_genname();
6665 const char *genname_str = t_genname.c_str();
6666 string return_type_name;
6667 switch (asstype) {
6668 case A_EXT_FUNCTION:
6669 return_type_name = "void";
6670 break;
6671 case A_EXT_FUNCTION_RVAL:
6672 return_type_name = return_type->get_genname_value(my_scope);
6673 break;
6674 case A_EXT_FUNCTION_RTEMP:
6675 return_type_name = return_type->get_genname_template(my_scope);
6676 break;
6677 default:
6678 FATAL_ERROR("Def_ExtFunction::generate_code()");
6679 }
6680 const char *return_type_str = return_type_name.c_str();
6681 char *formal_par_list = fp_list->generate_code(memptystr());
6682 fp_list->generate_code_defval(target);
6683 // function prototype
6684 target->header.function_prototypes =
6685 mputprintf(target->header.function_prototypes, "extern %s %s(%s);\n",
a38c6d4c 6686 return_type_str, genname_str, formal_par_list);
970ed795
EL
6687
6688 if (function_type != EXTFUNC_MANUAL) {
6689 // function body written by the compiler
6690 char *body = 0;
6691#ifndef NDEBUG
6692 body = mprintf("// written by %s in " __FILE__ " at %d\n"
6693 , __FUNCTION__, __LINE__);
6694#endif
6695 body = mputprintf(body,
a38c6d4c 6696 "%s %s(%s)\n"
6697 "{\n"
6698 , return_type_str, genname_str, formal_par_list);
970ed795
EL
6699 switch (function_type) {
6700 case EXTFUNC_ENCODE:
6701 body = generate_code_encode(body);
a38c6d4c 6702 break;
970ed795
EL
6703 case EXTFUNC_DECODE:
6704 body = generate_code_decode(body);
a38c6d4c 6705 break;
970ed795
EL
6706 default:
6707 FATAL_ERROR("Def_ExtFunction::generate_code()");
6708 }
6709 body = mputstr(body, "}\n\n");
6710 target->source.function_bodies = mputstr(target->source.function_bodies,
a38c6d4c 6711 body);
970ed795
EL
6712 Free(body);
6713 }
6714
6715 Free(formal_par_list);
6716
6717 target->functions.pre_init = mputprintf(target->functions.pre_init,
6718 "%s.add_function(\"%s\", (genericfunc_t)&%s, NULL);\n",
6719 get_module_object_name(), id->get_dispname().c_str(), genname_str);
6720 }
6721
6722 void Def_ExtFunction::generate_code(CodeGenHelper& cgh) {
6723 generate_code(cgh.get_current_outputstruct());
6724 }
6725
6726 void Def_ExtFunction::dump_internal(unsigned level) const
6727 {
6728 DEBUG(level, "External function: %s", id->get_dispname().c_str());
6729 DEBUG(level + 1, "Parameters:");
6730 fp_list->dump(level + 2);
6731 if (return_type) {
6732 DEBUG(level + 1, "Return type:");
6733 return_type->dump(level + 2);
6734 if(asstype == A_EXT_FUNCTION_RTEMP) DEBUG(level + 1, "Returns template");
6735 }
6736 if (prototype != PROTOTYPE_NONE)
6737 DEBUG(level + 1, "Prototype: %s", get_prototype_name());
6738 if (function_type != EXTFUNC_MANUAL) {
6739 DEBUG(level + 1, "Automatically generated: %s",
a38c6d4c 6740 function_type == EXTFUNC_ENCODE ? "encoder" : "decoder");
970ed795 6741 DEBUG(level + 2, "Encoding type: %s",
a38c6d4c 6742 Type::get_encoding_name(encoding_type));
970ed795 6743 if (encoding_options)
a38c6d4c 6744 DEBUG(level + 2, "Encoding options: %s", encoding_options->c_str());
970ed795
EL
6745 }
6746 if (eb_list) eb_list->dump(level + 1);
6747 }
6748
6749 void Def_ExtFunction::generate_json_schema_ref(map<Type*, JSON_Tokenizer>& json_refs)
6750 {
6751 // only do anything if this is a JSON encoding or decoding function
6752 if (encoding_type == Type::CT_JSON &&
6753 (function_type == EXTFUNC_ENCODE || function_type == EXTFUNC_DECODE)) {
6754 // retrieve the encoded type
6755 Type* type = NULL;
6756 if (function_type == EXTFUNC_ENCODE) {
6757 // for encoding functions it's always the first parameter
6758 type = fp_list->get_fp_byIndex(0)->get_Type();
6759 } else {
6760 // for decoding functions it depends on the prototype
6761 switch (prototype) {
6762 case PROTOTYPE_CONVERT:
6763 type = return_type;
6764 break;
6765 case PROTOTYPE_FAST:
6766 case PROTOTYPE_BACKTRACK:
6767 case PROTOTYPE_SLIDING:
6768 type = fp_list->get_fp_byIndex(1)->get_Type();
6769 break;
6770 default:
6771 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
6772 }
6773 }
6774
6775 // step over the type reference created for this function
6776 type = type->get_type_refd();
6777
6778 JSON_Tokenizer* json = NULL;
6779 if (json_refs.has_key(type)) {
6780 // the schema segment containing the type's reference already exists
6781 json = json_refs[type];
6782 } else {
6783 // the schema segment doesn't exist yet, create it and insert the reference
6784 json = new JSON_Tokenizer;
6785 json_refs.add(type, json);
af710487 6786 type->generate_json_schema_ref(*json);
970ed795
EL
6787 }
6788
6789 // insert a property to specify which function this is (encoding or decoding)
6790 json->put_next_token(JSON_TOKEN_NAME, (function_type == EXTFUNC_ENCODE) ?
6791 "encoding" : "decoding");
6792
6793 // place the function's info in an object
6794 json->put_next_token(JSON_TOKEN_OBJECT_START);
6795
6796 // insert information related to the function's prototype in an array
6797 json->put_next_token(JSON_TOKEN_NAME, "prototype");
6798 json->put_next_token(JSON_TOKEN_ARRAY_START);
6799
6800 // 1st element: external function prototype name (as string)
6801 switch(prototype) {
6802 case PROTOTYPE_CONVERT:
6803 json->put_next_token(JSON_TOKEN_STRING, "\"convert\"");
6804 break;
6805 case PROTOTYPE_FAST:
6806 json->put_next_token(JSON_TOKEN_STRING, "\"fast\"");
6807 break;
6808 case PROTOTYPE_BACKTRACK:
6809 json->put_next_token(JSON_TOKEN_STRING, "\"backtrack\"");
6810 break;
6811 case PROTOTYPE_SLIDING:
6812 json->put_next_token(JSON_TOKEN_STRING, "\"sliding\"");
6813 break;
6814 default:
6815 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
6816 }
6817
6818 // 2nd element: external function name
6819 char* func_name_str = mprintf("\"%s\"", id->get_dispname().c_str());
6820 json->put_next_token(JSON_TOKEN_STRING, func_name_str);
6821 Free(func_name_str);
6822
6823 // the rest of the elements contain the names of the function's parameters (1 or 2)
6824 for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
6825 char* param_str = mprintf("\"%s\"",
6826 fp_list->get_fp_byIndex(i)->get_id().get_dispname().c_str());
6827 json->put_next_token(JSON_TOKEN_STRING, param_str);
6828 Free(param_str);
6829 }
6830
6831 // end of the prototype's array
6832 json->put_next_token(JSON_TOKEN_ARRAY_END);
6833
6834 // insert error behavior data
6835 if (eb_list != NULL) {
6836 json->put_next_token(JSON_TOKEN_NAME, "errorBehavior");
6837 json->put_next_token(JSON_TOKEN_OBJECT_START);
6838
6839 // add each error behavior modification as a property
6840 for (size_t i = 0; i < eb_list->get_nof_ebs(); ++i) {
6841 ErrorBehaviorSetting* eb = eb_list->get_ebs_byIndex(i);
6842 json->put_next_token(JSON_TOKEN_NAME, eb->get_error_type().c_str());
6843 char* handling_str = mprintf("\"%s\"", eb->get_error_handling().c_str());
6844 json->put_next_token(JSON_TOKEN_STRING, handling_str);
6845 Free(handling_str);
6846 }
6847
6848 json->put_next_token(JSON_TOKEN_OBJECT_END);
6849 }
6850
6851 // insert printing type
6852 if (json_printing != NULL) {
6853 json->put_next_token(JSON_TOKEN_NAME, "printing");
6854 json->put_next_token(JSON_TOKEN_STRING,
6855 (json_printing->get_printing() == PrintingType::PT_PRETTY) ?
6856 "\"pretty\"" : "\"compact\"");
6857 }
6858
6859 // end of this function's object
6860 json->put_next_token(JSON_TOKEN_OBJECT_END);
6861 }
6862 }
6863
6864 // =================================
6865 // ===== Def_Altstep
6866 // =================================
6867
6868 Def_Altstep::Def_Altstep(Identifier *p_id, FormalParList *p_fpl,
6869 Reference *p_runs_on_ref, StatementBlock *p_sb,
6870 AltGuards *p_ags)
6871 : Definition(A_ALTSTEP, p_id), fp_list(p_fpl), runs_on_ref(p_runs_on_ref),
6872 runs_on_type(0), sb(p_sb), ags(p_ags)
6873 {
6874 if (!p_fpl || !p_sb || !p_ags)
6875 FATAL_ERROR("Def_Altstep::Def_Altstep()");
6876 fp_list->set_my_def(this);
6877 sb->set_my_def(this);
6878 ags->set_my_def(this);
6879 ags->set_my_sb(sb, 0);
6880 }
6881
6882 Def_Altstep::~Def_Altstep()
6883 {
6884 delete fp_list;
6885 delete runs_on_ref;
6886 delete sb;
6887 delete ags;
6888 }
6889
6890 Def_Altstep *Def_Altstep::clone() const
6891 {
6892 FATAL_ERROR("Def_Altstep::clone");
6893 }
6894
6895 void Def_Altstep::set_fullname(const string& p_fullname)
6896 {
6897 Definition::set_fullname(p_fullname);
6898 fp_list->set_fullname(p_fullname + ".<formal_par_list>");
6899 if (runs_on_ref) runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>");
6900 sb->set_fullname(p_fullname+".<block>");
6901 ags->set_fullname(p_fullname + ".<guards>");
6902 }
6903
6904 void Def_Altstep::set_my_scope(Scope *p_scope)
6905 {
6906 bridgeScope.set_parent_scope(p_scope);
6907 bridgeScope.set_scopeMacro_name(id->get_dispname());
6908
6909 Definition::set_my_scope(&bridgeScope);
6910 // the scope of the parameter list is set during checking
6911 if (runs_on_ref) runs_on_ref->set_my_scope(&bridgeScope);
6912 sb->set_my_scope(fp_list);
6913 ags->set_my_scope(sb);
6914 }
6915
6916 Type *Def_Altstep::get_RunsOnType()
6917 {
6918 if (!checked) chk();
6919 return runs_on_type;
6920 }
6921
6922 FormalParList *Def_Altstep::get_FormalParList()
6923 {
6924 if (!checked) chk();
6925 return fp_list;
6926 }
6927
6928 RunsOnScope *Def_Altstep::get_runs_on_scope(Type *comptype)
6929 {
6930 Module *my_module = dynamic_cast<Module*>(my_scope->get_scope_mod());
6931 if (!my_module) FATAL_ERROR("Def_Altstep::get_runs_on_scope()");
6932 return my_module->get_runs_on_scope(comptype);
6933 }
6934
6935 void Def_Altstep::chk()
6936 {
6937 if (checked) return;
6938 checked = true;
6939 Error_Context cntxt(this, "In altstep definition `%s'",
6940 id->get_dispname().c_str());
6941 Scope *parlist_scope = my_scope;
6942 if (runs_on_ref) {
6943 Error_Context cntxt2(runs_on_ref, "In `runs on' clause");
6944 runs_on_type = runs_on_ref->chk_comptype_ref();
6945 if (runs_on_type) {
6946 Scope *runs_on_scope = get_runs_on_scope(runs_on_type);
6947 runs_on_scope->set_parent_scope(my_scope);
6948 parlist_scope = runs_on_scope;
6949 }
6950 }
6951 fp_list->set_my_scope(parlist_scope);
6952 fp_list->chk(asstype);
6953 sb->chk();
6954 ags->set_is_altstep();
6955 ags->set_my_ags(ags);
6956 ags->set_my_laic_stmt(ags, 0);
6957 ags->chk();
6958 if (!semantic_check_only) {
6959 fp_list->set_genname(get_genname());
6960 sb->set_code_section(GovernedSimple::CS_INLINE);
6961 ags->set_code_section(GovernedSimple::CS_INLINE);
6962 }
6963 if (w_attrib_path) {
6964 w_attrib_path->chk_global_attrib();
6965 w_attrib_path->chk_no_qualif();
6966 }
6967 }
6968
6969 void Def_Altstep::generate_code(output_struct *target, bool)
6970 {
6971 const string& t_genname = get_genname();
6972 const char *genname_str = t_genname.c_str();
6973 const char *dispname_str = id->get_dispname().c_str();
6974 char *formal_par_list = fp_list->generate_code(memptystr());
6975 fp_list->generate_code_defval(target);
6976
6977 // function for altstep instance: prototype
6978 target->header.function_prototypes =
6979 mputprintf(target->header.function_prototypes,
a38c6d4c 6980 "extern alt_status %s_instance(%s);\n", genname_str, formal_par_list);
970ed795
EL
6981
6982 // function for altstep instance: body
6983 char *str = mprintf("alt_status %s_instance(%s)\n"
6984 "{\n", genname_str, formal_par_list);
6985 str = create_location_object(str, "ALTSTEP", dispname_str);
6986 str = fp_list->generate_shadow_objects(str);
6987 str = sb->generate_code(str);
6988 str = ags->generate_code_altstep(str);
6989 str = mputstr(str, "}\n\n");
6990 target->source.function_bodies = mputstr(target->source.function_bodies,
6991 str);
6992 Free(str);
6993
6994 char *actual_par_list =
6995 fp_list->generate_code_actual_parlist(memptystr(), "");
6996
6997 // wrapper function for stand-alone instantiation: prototype
6998 target->header.function_prototypes =
6999 mputprintf(target->header.function_prototypes,
a38c6d4c 7000 "extern void %s(%s);\n", genname_str, formal_par_list);
970ed795
EL
7001
7002 // wrapper function for stand-alone instantiation: body
7003 target->source.function_bodies =
7004 mputprintf(target->source.function_bodies, "void %s(%s)\n"
a38c6d4c 7005 "{\n"
7006 "altstep_begin:\n"
7007 "boolean block_flag = FALSE;\n"
7008 "alt_status altstep_flag = ALT_UNCHECKED, "
7009 "default_flag = ALT_UNCHECKED;\n"
7010 "for ( ; ; ) {\n"
7011 "TTCN_Snapshot::take_new(block_flag);\n"
7012 "if (altstep_flag != ALT_NO) {\n"
7013 "altstep_flag = %s_instance(%s);\n"
7014 "if (altstep_flag == ALT_YES || altstep_flag == ALT_BREAK) return;\n"
7015 "else if (altstep_flag == ALT_REPEAT) goto altstep_begin;\n"
7016 "}\n"
7017 "if (default_flag != ALT_NO) {\n"
7018 "default_flag = TTCN_Default::try_altsteps();\n"
7019 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) return;\n"
7020 "else if (default_flag == ALT_REPEAT) goto altstep_begin;\n"
7021 "}\n"
7022 "if (altstep_flag == ALT_NO && default_flag == ALT_NO) "
7023 "TTCN_error(\"None of the branches can be chosen in altstep %s.\");\n"
7024 "else block_flag = TRUE;\n"
7025 "}\n"
7026 "}\n\n", genname_str, formal_par_list, genname_str, actual_par_list,
7027 dispname_str);
970ed795
EL
7028
7029 // class for keeping the altstep in the default context
7030 // the class is for internal use, we do not need to publish it in the
7031 // header file
7032 str = mprintf("class %s_Default : public Default_Base {\n", genname_str);
7033 str = fp_list->generate_code_object(str, "par_");
7034 str = mputprintf(str, "public:\n"
7035 "%s_Default(%s);\n"
7036 "alt_status call_altstep();\n"
7037 "};\n\n", genname_str, formal_par_list);
7038 target->source.class_defs = mputstr(target->source.class_defs, str);
7039 Free(str);
7040 // member functions of the class
7041 str = mprintf("%s_Default::%s_Default(%s)\n"
a38c6d4c 7042 " : Default_Base(\"%s\")", genname_str, genname_str, formal_par_list,
7043 dispname_str);
970ed795
EL
7044 for (size_t i = 0; i < fp_list->get_nof_fps(); i++) {
7045 const char *fp_name_str =
a38c6d4c 7046 fp_list->get_fp_byIndex(i)->get_id().get_name().c_str();
970ed795
EL
7047 str = mputprintf(str, ", par_%s(%s)", fp_name_str, fp_name_str);
7048 }
7049 str = mputstr(str, "\n{\n}\n\n");
7050 char *actual_par_list_prefixed =
7051 fp_list->generate_code_actual_parlist(memptystr(), "par_");
7052 str = mputprintf(str, "alt_status %s_Default::call_altstep()\n"
7053 "{\n"
7054 "return %s_instance(%s);\n"
7055 "}\n\n", genname_str, genname_str, actual_par_list_prefixed);
7056 Free(actual_par_list_prefixed);
7057 target->source.methods = mputstr(target->source.methods, str);
7058 Free(str);
7059
7060 // function for default activation: prototype
7061 target->header.function_prototypes =
7062 mputprintf(target->header.function_prototypes,
a38c6d4c 7063 "extern Default_Base *activate_%s(%s);\n", genname_str,
7064 formal_par_list);
970ed795
EL
7065
7066 // function for default activation: body
7067 str = mprintf("Default_Base *activate_%s(%s)\n"
7068 "{\n", genname_str, formal_par_list);
7069 str = mputprintf(str, "return new %s_Default(%s);\n"
7070 "}\n\n", genname_str, actual_par_list);
7071 target->source.function_bodies = mputstr(target->source.function_bodies,
7072 str);
7073 Free(str);
7074
7075 Free(formal_par_list);
7076 Free(actual_par_list);
7077
7078 target->functions.pre_init = mputprintf(target->functions.pre_init,
7079 "%s.add_altstep(\"%s\", (genericfunc_t)&%s_instance, (genericfunc_t )&activate_%s, "
a38c6d4c 7080 "(genericfunc_t )&%s);\n", get_module_object_name(), dispname_str, genname_str,
970ed795
EL
7081 genname_str, genname_str);
7082 }
7083
7084 void Def_Altstep::generate_code(CodeGenHelper& cgh) {
7085 generate_code(cgh.get_current_outputstruct());
7086 }
7087
7088 void Def_Altstep::dump_internal(unsigned level) const
7089 {
7090 DEBUG(level, "Altstep: %s", id->get_dispname().c_str());
7091 DEBUG(level + 1, "Parameters:");
7092 fp_list->dump(level + 1);
7093 if (runs_on_ref) {
7094 DEBUG(level + 1, "Runs on clause:");
7095 runs_on_ref->dump(level + 2);
7096 }
7097 /*
7098 DEBUG(level + 1, "Local definitions:");
7099 sb->dump(level + 2);
7100 */
7101 DEBUG(level + 1, "Guards:");
7102 ags->dump(level + 2);
7103 }
7104
7105 void Def_Altstep::set_parent_path(WithAttribPath* p_path) {
7106 Definition::set_parent_path(p_path);
7107 sb->set_parent_path(w_attrib_path);
7108 }
7109
7110 // =================================
7111 // ===== Def_Testcase
7112 // =================================
7113
7114 Def_Testcase::Def_Testcase(Identifier *p_id, FormalParList *p_fpl,
7115 Reference *p_runs_on_ref, Reference *p_system_ref,
7116 StatementBlock *p_block)
7117 : Definition(A_TESTCASE, p_id), fp_list(p_fpl), runs_on_ref(p_runs_on_ref),
7118 runs_on_type(0), system_ref(p_system_ref), system_type(0), block(p_block)
7119 {
7120 if (!p_fpl || !p_runs_on_ref || !p_block)
7121 FATAL_ERROR("Def_Testcase::Def_Testcase()");
7122 fp_list->set_my_def(this);
7123 block->set_my_def(this);
7124 }
7125
7126 Def_Testcase::~Def_Testcase()
7127 {
7128 delete fp_list;
7129 delete runs_on_ref;
7130 delete system_ref;
7131 delete block;
7132 }
7133
7134 Def_Testcase *Def_Testcase::clone() const
7135 {
7136 FATAL_ERROR("Def_Testcase::clone");
7137 }
7138
7139 void Def_Testcase::set_fullname(const string& p_fullname)
7140 {
7141 Definition::set_fullname(p_fullname);
7142 fp_list->set_fullname(p_fullname + ".<formal_par_list>");
7143 runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>");
7144 if (system_ref) system_ref->set_fullname(p_fullname + ".<system_type>");
7145 block->set_fullname(p_fullname + ".<statement_block>");
7146 }
7147
7148 void Def_Testcase::set_my_scope(Scope *p_scope)
7149 {
7150 bridgeScope.set_parent_scope(p_scope);
7151 bridgeScope.set_scopeMacro_name(id->get_dispname());
7152
7153 Definition::set_my_scope(&bridgeScope);
7154 // the scope of the parameter list is set during checking
7155 runs_on_ref->set_my_scope(&bridgeScope);
7156 if (system_ref) system_ref->set_my_scope(&bridgeScope);
7157 block->set_my_scope(fp_list);
7158 }
7159
7160 Type *Def_Testcase::get_RunsOnType()
7161 {
7162 if (!checked) chk();
7163 return runs_on_type;
7164 }
7165
7166 Type *Def_Testcase::get_SystemType()
7167 {
7168 if (!checked) chk();
7169 return system_type;
7170 }
7171
7172 FormalParList *Def_Testcase::get_FormalParList()
7173 {
7174 if (!checked) chk();
7175 return fp_list;
7176 }
7177
7178 RunsOnScope *Def_Testcase::get_runs_on_scope(Type *comptype)
7179 {
7180 Module *my_module = dynamic_cast<Module*>(my_scope->get_scope_mod());
7181 if (!my_module) FATAL_ERROR("Def_Testcase::get_runs_on_scope()");
7182 return my_module->get_runs_on_scope(comptype);
7183 }
7184
7185 void Def_Testcase::chk()
7186 {
7187 if (checked) return;
7188 checked = true;
7189 Error_Context cntxt(this, "In testcase definition `%s'",
7190 id->get_dispname().c_str());
7191 Scope *parlist_scope = my_scope;
7192 {
7193 Error_Context cntxt2(runs_on_ref, "In `runs on' clause");
7194 runs_on_type = runs_on_ref->chk_comptype_ref();
7195 if (runs_on_type) {
7196 Scope *runs_on_scope = get_runs_on_scope(runs_on_type);
7197 runs_on_scope->set_parent_scope(my_scope);
7198 parlist_scope = runs_on_scope;
7199 }
7200 }
7201 if (system_ref) {
7202 Error_Context cntxt2(system_ref, "In `system' clause");
7203 system_type = system_ref->chk_comptype_ref();;
7204 }
7205 fp_list->set_my_scope(parlist_scope);
7206 fp_list->chk(asstype);
7207 block->chk();
7208 if (!semantic_check_only) {
7209 fp_list->set_genname(get_genname());
7210 block->set_code_section(GovernedSimple::CS_INLINE);
7211 }
7212 if (w_attrib_path) {
7213 w_attrib_path->chk_global_attrib();
7214 w_attrib_path->chk_no_qualif();
7215 }
7216 }
7217
7218 void Def_Testcase::generate_code(output_struct *target, bool)
7219 {
7220 const string& t_genname = get_genname();
7221 const char *genname_str = t_genname.c_str();
7222 const char *dispname_str = id->get_dispname().c_str();
7223 // formal parameter list
7224 char *formal_par_list = fp_list->generate_code(memptystr());
7225 fp_list->generate_code_defval(target);
7226 if (fp_list->get_nof_fps() > 0)
7227 formal_par_list = mputstr(formal_par_list, ", ");
7228 formal_par_list = mputstr(formal_par_list,
7229 "boolean has_timer, double timer_value");
7230
7231 // function prototype
7232 target->header.function_prototypes =
7233 mputprintf(target->header.function_prototypes,
a38c6d4c 7234 "extern verdicttype testcase_%s(%s);\n", genname_str, formal_par_list);
970ed795
EL
7235
7236 // function body
7237 char *body = mprintf("verdicttype testcase_%s(%s)\n"
7238 "{\n", genname_str, formal_par_list);
7239 Free(formal_par_list);
7240 // Checking whether the testcase was invoked from another one.
7241 // At this point the location information should refer to the execute()
7242 // statement rather than this testcase.
7243 body = mputstr(body, "TTCN_Runtime::check_begin_testcase(has_timer, "
a38c6d4c 7244 "timer_value);\n");
970ed795
EL
7245 body = create_location_object(body, "TESTCASE", dispname_str);
7246 body = fp_list->generate_shadow_objects(body);
7247 body = mputprintf(body, "try {\n"
7248 "TTCN_Runtime::begin_testcase(\"%s\", \"%s\", ",
7249 my_scope->get_scope_mod()->get_modid().get_dispname().c_str(),
7250 dispname_str);
7251 ComponentTypeBody *runs_on_body = runs_on_type->get_CompBody();
7252 body = runs_on_body->generate_code_comptype_name(body);
7253 body = mputstr(body, ", ");
7254 if (system_type)
7255 body = system_type->get_CompBody()->generate_code_comptype_name(body);
7256 else body = runs_on_body->generate_code_comptype_name(body);
7257 body = mputstr(body, ", has_timer, timer_value);\n");
7258 body = block->generate_code(body);
7259 body = mputprintf(body,
7260 "} catch (const TC_Error& tc_error) {\n"
7261 "} catch (const TC_End& tc_end) {\n"
7262 "TTCN_Logger::log_str(TTCN_FUNCTION, \"Test case %s was stopped.\");\n"
7263 "}\n", dispname_str);
7264 body = mputstr(body, "return TTCN_Runtime::end_testcase();\n"
7265 "}\n\n");
7266 target->source.function_bodies = mputstr(target->source.function_bodies,
7267 body);
7268 Free(body);
7269
7270 if (fp_list->get_nof_fps() == 0) {
7271 // adding to the list of startable testcases
7272 target->functions.pre_init = mputprintf(target->functions.pre_init,
a38c6d4c 7273 "%s.add_testcase_nonpard(\"%s\", testcase_%s);\n",
7274 get_module_object_name(), dispname_str, genname_str);
970ed795
EL
7275 } else {
7276 target->functions.pre_init = mputprintf(target->functions.pre_init,
7277 "%s.add_testcase_pard(\"%s\", (genericfunc_t)&testcase_%s);\n",
7278 get_module_object_name(), dispname_str, genname_str);
7279
7280 // If every formal parameter has a default value, the testcase
7281 // might be callable after all.
7282 bool callable = true;
7283 for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
7284 FormalPar *fp = fp_list->get_fp_byIndex(i);
7285 if (!fp->has_defval()) {
7286 callable = false;
7287 break;
7288 }
7289 }
7290
7291 if (callable) {
7292 // Write a wrapper, which acts as a no-param testcase
7293 // by calling the parameterized testcase with the default values.
7294 target->header.function_prototypes =
7295 mputprintf(target->header.function_prototypes,
7296 "extern verdicttype testcase_%s_defparams(boolean has_timer, double timer_value);\n",
7297 genname_str);
7298 target->source.function_bodies = mputprintf(target->source.function_bodies,
7299 "verdicttype testcase_%s_defparams(boolean has_timer, double timer_value) {\n"
7300 " return testcase_%s(",
7301 genname_str, genname_str);
7302
7303 for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
7304 FormalPar *fp = fp_list->get_fp_byIndex(i);
7305 ActualPar *ap = fp->get_defval();
7306 switch (ap->get_selection()) {
7307 case ActualPar::AP_VALUE:
7308 target->source.function_bodies = mputstr(target->source.function_bodies,
7309 ap->get_Value()->get_genname_own(my_scope).c_str());
7310 break;
7311 case ActualPar::AP_TEMPLATE:
7312 target->source.function_bodies = mputstr(target->source.function_bodies,
7313 ap->get_TemplateInstance()->get_Template()->get_genname_own(my_scope).c_str());
7314 break;
7315 case ActualPar::AP_REF:
7316 target->source.function_bodies = mputstr(target->source.function_bodies,
7317 ap->get_Ref()->get_refd_assignment()->get_genname_from_scope(my_scope).c_str());
7318 break;
7319 case ActualPar::AP_DEFAULT:
7320 // Can't happen. This ActualPar was created by
7321 // Ttcn::FormalPar::chk_actual_par as the default value for
7322 // a FormalPar, and it only ever creates vale, template or ref.
7323 // no break
7324 default:
7325 FATAL_ERROR("Def_Testcase::generate_code()");
7326 }
7327
7328 // always append a comma, because has_timer and timer_value follows
7329 target->source.function_bodies = mputstrn(target->source.function_bodies,
7330 ", ", 2);
7331 }
7332
7333 target->source.function_bodies = mputstr(target->source.function_bodies,
7334 "has_timer, timer_value);\n"
7335 "}\n\n");
7336 // Add the non-parameterized wrapper *after* the parameterized one,
7337 // with the same name. Linear search will always find the first
7338 // (user-visible, parameterized) testcase.
7339 // TTCN_Module::execute_testcase knows that if after a parameterized
7340 // testcase another testcase with the same name follows,
7341 // it's the callable, non-parameterized wrapper.
7342 //
7343 // TTCN_Module::list_testcases skips parameterized testcases;
7344 // it will now list the non-parameterized wrapper.
7345 target->functions.pre_init = mputprintf(target->functions.pre_init,
7346 "%s.add_testcase_nonpard(\"%s\", testcase_%s_defparams);\n",
7347 get_module_object_name(), dispname_str, genname_str);
7348 }
7349 } // has formal parameters
7350 }
7351
7352 void Def_Testcase::generate_code(CodeGenHelper& cgh) {
7353 generate_code(cgh.get_current_outputstruct());
7354 }
7355
7356 void Def_Testcase::dump_internal(unsigned level) const
7357 {
7358 DEBUG(level, "Testcase: %s", id->get_dispname().c_str());
7359 DEBUG(level + 1, "Parameters:");
7360 fp_list->dump(level + 1);
7361 DEBUG(level + 1, "Runs on clause:");
7362 runs_on_ref->dump(level + 2);
7363 if (system_ref) {
7364 DEBUG(level + 1, "System clause:");
7365 system_ref->dump(level + 2);
7366 }
7367 DEBUG(level + 1, "Statement block:");
7368 block->dump(level + 2);
7369 }
7370
7371 void Def_Testcase::set_parent_path(WithAttribPath* p_path) {
7372 Definition::set_parent_path(p_path);
7373 if (block)
7374 block->set_parent_path(w_attrib_path);
7375 }
7376
7377 // =================================
7378 // ===== FormalPar
7379 // =================================
7380
7381 FormalPar::FormalPar(asstype_t p_asstype, Type *p_type, Identifier* p_name,
7382 TemplateInstance *p_defval, bool p_lazy_eval)
7383 : Definition(p_asstype, p_name), type(p_type), my_parlist(0),
7384 used_as_lvalue(false), template_restriction(TR_NONE),
51fa56b9 7385 lazy_eval(p_lazy_eval), defval_generated(false)
970ed795
EL
7386 {
7387 switch (p_asstype) {
7388 case A_PAR_VAL:
7389 case A_PAR_VAL_IN:
7390 case A_PAR_VAL_OUT:
7391 case A_PAR_VAL_INOUT:
7392 case A_PAR_TEMPL_IN:
7393 case A_PAR_TEMPL_OUT:
7394 case A_PAR_TEMPL_INOUT:
7395 case A_PAR_PORT:
7396 break;
7397 default:
7398 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7399 }
7400 if (!p_type)
7401 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7402 type->set_ownertype(Type::OT_FORMAL_PAR, this);
7403 defval.ti = p_defval;
7404 }
7405
7406 FormalPar::FormalPar(asstype_t p_asstype,
7407 template_restriction_t p_template_restriction, Type *p_type,
7408 Identifier* p_name, TemplateInstance *p_defval, bool p_lazy_eval)
7409 : Definition(p_asstype, p_name), type(p_type), my_parlist(0),
7410 used_as_lvalue(false), template_restriction(p_template_restriction),
51fa56b9 7411 lazy_eval(p_lazy_eval), defval_generated(false)
970ed795
EL
7412 {
7413 switch (p_asstype) {
7414 case A_PAR_TEMPL_IN:
7415 case A_PAR_TEMPL_OUT:
7416 case A_PAR_TEMPL_INOUT:
7417 break;
7418 default:
7419 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): parameter not template");
7420 }
7421 if (!p_type)
7422 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7423 type->set_ownertype(Type::OT_FORMAL_PAR, this);
7424 defval.ti = p_defval;
7425 }
7426
7427 FormalPar::FormalPar(asstype_t p_asstype, Identifier* p_name,
7428 TemplateInstance *p_defval)
7429 : Definition(p_asstype, p_name), type(0), my_parlist(0),
51fa56b9 7430 used_as_lvalue(false), template_restriction(TR_NONE), lazy_eval(false),
7431 defval_generated(false)
970ed795
EL
7432 {
7433 if (p_asstype != A_PAR_TIMER)
7434 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7435 defval.ti = p_defval;
7436 }
7437
7438 FormalPar::~FormalPar()
7439 {
7440 delete type;
7441 if (checked) delete defval.ap;
7442 else delete defval.ti;
7443 }
7444
7445 FormalPar* FormalPar::clone() const
7446 {
7447 FATAL_ERROR("FormalPar::clone");
7448 }
7449
7450 void FormalPar::set_fullname(const string& p_fullname)
7451 {
7452 Definition::set_fullname(p_fullname);
7453 if (type) type->set_fullname(p_fullname + ".<type>");
7454 if (checked) {
7455 if (defval.ap) defval.ap->set_fullname(p_fullname + ".<default_value>");
7456 } else {
7457 if (defval.ti) defval.ti->set_fullname(p_fullname + ".<default_value>");
7458 }
7459 }
7460
7461 void FormalPar::set_my_scope(Scope *p_scope)
7462 {
7463 Definition::set_my_scope(p_scope);
7464 if (type) type->set_my_scope(p_scope);
7465 if (checked) {
7466 if (defval.ap) defval.ap->set_my_scope(p_scope);
7467 } else {
7468 if (defval.ti) defval.ti->set_my_scope(p_scope);
7469 }
7470 }
7471
7472 bool FormalPar::is_local() const
7473 {
7474 return true;
7475 }
7476
7477 Type *FormalPar::get_Type()
7478 {
7479 if (!checked) chk();
7480 if (!type) FATAL_ERROR("FormalPar::get_Type()");
7481 return type;
7482 }
7483
7484 void FormalPar::chk()
7485 {
7486 if (checked) return;
7487 checked = true;
7488 TemplateInstance *default_value = defval.ti;
7489 defval.ti = 0;
7490 if (type) {
7491 type->chk();
7492 Type *t = type->get_type_refd_last();
7493 // checks for forbidden type <-> parameter combinations
7494 switch (t->get_typetype()) {
7495 case Type::T_PORT:
7496 switch (asstype) {
a38c6d4c 7497 case A_PAR_VAL:
7498 case A_PAR_VAL_INOUT:
7499 asstype = A_PAR_PORT;
7500 break;
7501 default:
7502 error("Port type `%s' cannot be used as %s",
7503 t->get_fullname().c_str(), get_assname());
7504 }
7505 break;
970ed795
EL
7506 case Type::T_SIGNATURE:
7507 switch (asstype) {
a38c6d4c 7508 case A_PAR_TEMPL_IN:
7509 case A_PAR_TEMPL_OUT:
7510 case A_PAR_TEMPL_INOUT:
7511 break;
7512 default:
7513 error("Signature `%s' cannot be used as %s",
7514 t->get_fullname().c_str(), get_assname());
7515 }
7516 break;
970ed795
EL
7517 default:
7518 switch (asstype) {
a38c6d4c 7519 case A_PAR_PORT:
7520 case A_PAR_TIMER:
7521 FATAL_ERROR("FormalPar::chk()");
7522 case A_PAR_VAL:
7523 asstype = A_PAR_VAL_IN;
7524 default:
970ed795 7525 break;
a38c6d4c 7526 }
970ed795
EL
7527 }
7528 } else if (asstype != A_PAR_TIMER) FATAL_ERROR("FormalPar::chk()");
7529
7530 if (default_value) {
7531 Error_Context cntxt(default_value, "In default value");
7532 defval.ap = chk_actual_par(default_value, Type::EXPECTED_STATIC_VALUE);
7533 delete default_value;
7534 if (!semantic_check_only)
a38c6d4c 7535 defval.ap->set_code_section(GovernedSimple::CS_POST_INIT);
970ed795
EL
7536 }
7537 }
7538
7539 bool FormalPar::has_defval() const
7540 {
7541 if (checked) return defval.ap != 0;
7542 else return defval.ti != 0;
7543 }
7544
7545 bool FormalPar::has_notused_defval() const
7546 {
7547 if (checked) FATAL_ERROR("FormalPar::has_notused_defval");
7548 if (!defval.ti || !defval.ti->get_Template())
7549 return false;
7550 return defval.ti->get_Template()->get_templatetype()
7551 == Template::TEMPLATE_NOTUSED;
7552 }
7553
7554 ActualPar *FormalPar::get_defval() const
7555 {
7556 if (!checked) FATAL_ERROR("FormalPar::get_defval()");
7557 return defval.ap;
7558 }
7559
7560 // Extract the TemplateInstance from an ActualPar.
7561 void FormalPar::set_defval(ActualPar *defpar)
7562 {
7563 // ActualPar::clone() is not implemented, since we need such a function
7564 // only here only for AP_{VALUE,TEMPLATE} parameters. AP_ERROR can also
7565 // happen for Def_Template nodes, but they will be errors later.
7566 // FIXME: This function is Def_Template specific.
7567 if (!defval.ti->get_Template() || defval.ti->get_Template()
7568 ->get_templatetype() != Template::TEMPLATE_NOTUSED)
7569 FATAL_ERROR("FormalPar::set_defval()");
7570 TemplateInstance *reversed_ti = 0;
7571 switch (defpar->get_selection()) {
7572 case ActualPar::AP_VALUE:
7573 reversed_ti = new TemplateInstance(type->clone(), 0, new Template
7574 (defpar->get_Value()->clone())); // Trust the clone().
7575 break;
7576 case ActualPar::AP_TEMPLATE:
7577 reversed_ti = defpar->get_TemplateInstance()->clone();
7578 break;
7579 case ActualPar::AP_ERROR:
7580 break; // Can happen, but let it go.
7581 case ActualPar::AP_REF:
7582 case ActualPar::AP_DEFAULT:
7583 default:
7584 FATAL_ERROR("FormalPar::set_defval()");
7585 }
7586 if (reversed_ti) {
7587 delete defval.ti;
7588 reversed_ti->set_my_scope(get_my_scope());
7589 defval.ti = reversed_ti;
7590 }
7591 }
7592
7593 ActualPar *FormalPar::chk_actual_par(TemplateInstance *actual_par,
7594 Type::expected_value_t exp_val)
7595 {
7596 if (!checked) chk();
7597 switch (asstype) {
7598 case A_PAR_VAL:
7599 case A_PAR_VAL_IN:
7600 return chk_actual_par_value(actual_par, exp_val);
7601 case A_PAR_VAL_OUT:
7602 case A_PAR_VAL_INOUT:
7603 return chk_actual_par_by_ref(actual_par, false, exp_val);
7604 case A_PAR_TEMPL_IN:
7605 return chk_actual_par_template(actual_par, exp_val);
7606 case A_PAR_TEMPL_OUT:
7607 case A_PAR_TEMPL_INOUT:
7608 return chk_actual_par_by_ref(actual_par, true, exp_val);
7609 case A_PAR_TIMER:
7610 return chk_actual_par_timer(actual_par, exp_val);
7611 case A_PAR_PORT:
7612 return chk_actual_par_port(actual_par, exp_val);
7613 default:
7614 FATAL_ERROR("FormalPar::chk_actual_par()");
7615 }
7616 return 0; // to avoid warnings
7617 }
7618
7619 ActualPar *FormalPar::chk_actual_par_value(TemplateInstance *actual_par,
7620 Type::expected_value_t exp_val)
7621 {
7622 actual_par->chk_Type(type);
7623 Ref_base *derived_ref = actual_par->get_DerivedRef();
7624 if (derived_ref) {
7625 derived_ref->error("An in-line modified template cannot be used as %s",
7626 get_assname());
7627 actual_par->chk_DerivedRef(type);
7628 }
7629 Template *ap_template = actual_par->get_Template();
7630 if (ap_template->is_Value()) {
7631 Value *v = ap_template->get_Value();
7632 v->set_my_governor(type);
7633 type->chk_this_value_ref(v);
7634 type->chk_this_value(v, 0, exp_val, INCOMPLETE_NOT_ALLOWED,
7635 OMIT_NOT_ALLOWED, SUB_CHK);
7636 return new ActualPar(v);
7637 } else {
7638 actual_par->error("A specific value without matching symbols "
a38c6d4c 7639 "was expected for a %s", get_assname());
970ed795
EL
7640 return new ActualPar();
7641 }
7642 }
7643
7644 static void chk_defpar_value(const Value* v)
7645 {
7646 Common::Reference *vref = v->get_reference();
7647 Common::Assignment *ass2 = vref->get_refd_assignment();
7648 ass2->chk();
7649 Scope *scope = ass2->get_my_scope();
7650 ComponentTypeBody *ctb = dynamic_cast<ComponentTypeBody *>(scope);
7651 if (ctb) { // this is a component variable
7652 v->error("default value cannot refer to"
7653 " a template field of the component in the `runs on' clause");
7654 }
7655 }
7656
7657 static void chk_defpar_template(const Template *body,
7658 Type::expected_value_t exp_val)
7659 {
7660 switch (body->get_templatetype()) {
7661 case Template::TEMPLATE_ERROR:
7662 break; // could be erroneous in the source; skip it
7663 case Template::TEMPLATE_NOTUSED:
7664 case Template::OMIT_VALUE:
7665 case Template::ANY_VALUE:
7666 case Template::ANY_OR_OMIT:
7667 break; // acceptable (?)
7668 case Template::TEMPLATE_INVOKE: // calling a function is not acceptable
7669 body->error("default value can not be a function invocation");
7670 break;
7671 case Template::VALUE_RANGE: {
7672 ValueRange *range = body->get_value_range();
7673 Value *low = range->get_min_v();
7674 Type::typetype_t tt_low = low->get_expr_returntype(exp_val);
7675 Value *high = range->get_max_v();
7676 Type::typetype_t tt_high = high->get_expr_returntype(exp_val);
7677 if (tt_low == tt_high) break;
7678 break; }
7679
7680 case Template::BSTR_PATTERN:
7681 case Template::HSTR_PATTERN:
7682 case Template::OSTR_PATTERN:
7683 case Template::CSTR_PATTERN:
7684 case Template::USTR_PATTERN:
7685 break; // should be acceptable in all cases (if only fixed strings possible)
7686
7687 case Template::SPECIFIC_VALUE: {
7688 Common::Value *v = body->get_specific_value();
7689 if (v->get_valuetype() == Value::V_REFD) chk_defpar_value(v);
7690 break; }
7691
7692 case Template::ALL_FROM:
7693 case Template::VALUE_LIST_ALL_FROM:
7694 FATAL_ERROR("should have been flattened");
7695 break;
7696 case Template::SUPERSET_MATCH:
7697 case Template::SUBSET_MATCH:
7698 case Template::PERMUTATION_MATCH:
7699 case Template::TEMPLATE_LIST:
7700 case Template::COMPLEMENTED_LIST:
7701 case Template::VALUE_LIST: {
7702 // in template charstring par := charstring : ("foo", "bar", "baz")
7703 size_t num = body->get_nof_comps();
7704 for (size_t i = 0; i < num; ++i) {
7705 const Template *tpl = body->get_temp_byIndex(i);
7706 chk_defpar_template(tpl, exp_val);
7707 }
7708 break; }
7709
7710 case Template::NAMED_TEMPLATE_LIST: {
7711 size_t num = body->get_nof_comps();
7712 for (size_t i = 0; i < num; ++i) {
7713 const NamedTemplate *nt = body->get_namedtemp_byIndex(i);
7714 const Template *tpl = nt->get_template();
7715 chk_defpar_template(tpl, exp_val);
7716 }
7717 break; }
7718
7719 case Template::INDEXED_TEMPLATE_LIST: {
7720 size_t num = body->get_nof_comps();
7721 for (size_t i = 0; i < num; ++i) {
7722 const IndexedTemplate *it = body->get_indexedtemp_byIndex(i);
7723 const Template *tpl = it->get_template();
7724 chk_defpar_template(tpl, exp_val);
7725 }
7726 break; }
7727
7728 case Template::TEMPLATE_REFD: {
7729 Ref_base *ref = body->get_reference();
7730
7731 Ttcn::ActualParList *aplist = ref->get_parlist();
7732 if (!aplist) break;
7733 size_t num = aplist->get_nof_pars();
7734 for (size_t i = 0; i < num; ++i) {
7735 const Ttcn::ActualPar *ap = aplist->get_par(i);
7736 deeper:
7737 switch (ap->get_selection()) {
7738 case ActualPar::AP_ERROR: {
7739 break; }
7740 case ActualPar::AP_VALUE: {
7741 Value *v = ap->get_Value(); // "v_variable" as the parameter of the template
7742 v->chk();
7743 switch (v->get_valuetype()) {
7744 case Value::V_REFD: {
7745 chk_defpar_value(v);
7746 break; }
7747 default:
7748 break;
7749 }
7750 break; }
7751 case ActualPar::AP_TEMPLATE: {
7752 // A component cannot contain a template definition, parameterized or not.
7753 // Therefore the template this actual par references, cannot be
7754 // a field of a component => no error possible, nothing to do.
7755 break; }
7756 case ActualPar::AP_REF: {
7757 // A template cannot have an out/inout parameter
7758 FATAL_ERROR("Template with out parameter?");
7759 break; }
7760 case ActualPar::AP_DEFAULT: {
7761 ap = ap->get_ActualPar();
7762 goto deeper;
7763 break; }
7764 // no default
7765 } // switch actual par selection
7766 } // next
7767
7768 break; }
7769 } // switch templatetype
7770
7771 }
7772
7773 // This function is called in two situations:
7774 // 1. FormalParList::chk calls FormalPar::chk to compute the default value
7775 // (make an ActualPar from a TemplateInstance).
7776 // In this case, defval.ti==0, and actual_par contains its old value.
7777 // This case is called only if the formal par has a default value.
7778 // 2. FormalParList::chk_actual_parlist calls FormalPar::chk_actual_par
7779 // to check the parameters supplied by the execute statement to the tc.
7780 // In this case, defval.ap has the value computed in case 1.
7781 ActualPar *FormalPar::chk_actual_par_template(TemplateInstance *actual_par,
7782 Type::expected_value_t exp_val)
7783 {
7784 actual_par->chk(type);
7785 // actual_par->template_body may change: SPECIFIC_VALUE to TEMPLATE_REFD
7786 Definition *fplist_def = my_parlist->get_my_def();
7787 // The parameter list belongs to this definition. If it's a function
7788 // or testcase, it may have a "runs on" clause.
7789 Def_Function *parent_fn = dynamic_cast<Def_Function *>(fplist_def);
7790 Type *runs_on_type = 0;
7791 if (parent_fn) runs_on_type = parent_fn->get_RunsOnType();
7792 else { // not a function; maybe a testcase
7793 Def_Testcase *parent_tc = dynamic_cast<Def_Testcase *>(fplist_def);
7794 if (parent_tc) runs_on_type = parent_tc->get_RunsOnType();
7795 }
7796 if (runs_on_type) {
7797 // If it _has_ a runs on clause, the type must be a component.
7798 if (runs_on_type->get_typetype() != Type::T_COMPONENT) FATAL_ERROR("not component?");
7799 // The default value "shall not refer to elements of the component type
7800 // in the runs on clause"
7801 ComponentTypeBody *runs_on_component = runs_on_type->get_CompBody();
7802 size_t compass = runs_on_component->get_nof_asss();
7803 for (size_t c = 0; c < compass; c++) {
7804 Assignment *ass = runs_on_component->get_ass_byIndex(c);
7805 (void)ass;
7806 }
7807 }
7808
7809 Ttcn::Template * body = actual_par->get_Template();
7810 if (exp_val == Type::EXPECTED_STATIC_VALUE
7811 ||exp_val == Type::EXPECTED_CONSTANT) {
7812 chk_defpar_template(body, exp_val);
7813 }
7814 // Rip out the type, derived ref and template from actual_par
7815 // (which may come from a function invocation or the definition
7816 // of the default value) and give it to the new ActualPar.
7817 ActualPar *ret_val = new ActualPar(
7818 new TemplateInstance(actual_par->get_Type(),
7819 actual_par->get_DerivedRef(), actual_par->get_Template()));
7820 // Zero out these members because the caller will soon call delete
7821 // on actual_par, but they now belong to ret_val.
7822 // FIXME: should this really be in here, or outside in the caller before the delete ?
7823 actual_par->release();
7824
7825 if (template_restriction!=TR_NONE) {
7826 bool needs_runtime_check =
7827 ret_val->get_TemplateInstance()->chk_restriction(
3abe9331 7828 "template formal parameter", template_restriction,
7829 ret_val->get_TemplateInstance());
970ed795
EL
7830 if (needs_runtime_check)
7831 ret_val->set_gen_restriction_check(template_restriction);
7832 }
7833 return ret_val;
7834 }
7835
7836 ActualPar *FormalPar::chk_actual_par_by_ref(TemplateInstance *actual_par,
7837 bool is_template, Type::expected_value_t exp_val)
7838 {
7839 Type *ap_type = actual_par->get_Type();
7840 if (ap_type) {
7841 ap_type->warning("Explicit type specification is useless for an %s",
a38c6d4c 7842 get_assname());
970ed795
EL
7843 actual_par->chk_Type(type);
7844 }
7845 Ref_base *derived_ref = actual_par->get_DerivedRef();
7846 if (derived_ref) {
7847 derived_ref->error("An in-line modified template cannot be used as %s",
a38c6d4c 7848 get_assname());
970ed795
EL
7849 actual_par->chk_DerivedRef(type);
7850 }
7851 // needed for the error messages
7852 const char *expected_string = is_template ?
7853 "template variable or template parameter" :
7854 "variable or value parameter";
7855 Template *ap_template = actual_par->get_Template();
7856 if (ap_template->is_Ref()) {
7857 Ref_base *ref = ap_template->get_Ref();
7858 Common::Assignment *ass = ref->get_refd_assignment();
7859 if (!ass) {
a38c6d4c 7860 delete ref;
7861 return new ActualPar();
970ed795
EL
7862 }
7863 bool asstype_correct = false;
7864 switch (ass->get_asstype()) {
7865 case A_PAR_VAL_IN:
a38c6d4c 7866 ass->use_as_lvalue(*ref);
7867 if (get_asstype() == A_PAR_VAL_OUT || get_asstype() == A_PAR_TEMPL_OUT) {
7868 ass->warning("Passing an `in' parameter as another function's `out' parameter");
7869 }
7870 // no break
970ed795
EL
7871 case A_VAR:
7872 case A_PAR_VAL_OUT:
7873 case A_PAR_VAL_INOUT:
7874 if (!is_template) asstype_correct = true;
a38c6d4c 7875 break;
970ed795 7876 case A_PAR_TEMPL_IN:
a38c6d4c 7877 ass->use_as_lvalue(*ref);
7878 if (get_asstype() == A_PAR_VAL_OUT || get_asstype() == A_PAR_TEMPL_OUT) {
7879 ass->warning("Passing an `in' parameter as another function's `out' parameter");
7880 }
7881 // no break
970ed795
EL
7882 case A_VAR_TEMPLATE:
7883 case A_PAR_TEMPL_OUT:
7884 case A_PAR_TEMPL_INOUT:
7885 if (is_template) asstype_correct = true;
a38c6d4c 7886 break;
970ed795 7887 default:
a38c6d4c 7888 break;
970ed795
EL
7889 }
7890 if (asstype_correct) {
a38c6d4c 7891 FieldOrArrayRefs *t_subrefs = ref->get_subrefs();
7892 Type *ref_type = ass->get_Type()->get_field_type(t_subrefs, exp_val);
7893 if (ref_type) {
7894 if (!type->is_identical(ref_type)) {
7895 ref->error("Type mismatch: Reference to a %s of type "
7896 "`%s' was expected instead of `%s'", expected_string,
7897 type->get_typename().c_str(), ref_type->get_typename().c_str());
7898 } else if (type->get_sub_type() && ref_type->get_sub_type() &&
970ed795
EL
7899 (type->get_sub_type()->get_subtypetype()==ref_type->get_sub_type()->get_subtypetype()) &&
7900 (!type->get_sub_type()->is_compatible(ref_type->get_sub_type()))) {
7901 ref->error("Subtype mismatch: subtype %s has no common value with subtype %s",
7902 type->get_sub_type()->to_string().c_str(),
7903 ref_type->get_sub_type()->to_string().c_str());
7904 }
a38c6d4c 7905 if (t_subrefs && t_subrefs->refers_to_string_element()) {
7906 ref->error("Reference to a string element of type `%s' cannot be "
7907 "used in this context", ref_type->get_typename().c_str());
7908 }
7909 }
970ed795
EL
7910 } else {
7911 ref->error("Reference to a %s was expected for an %s instead of %s",
a38c6d4c 7912 expected_string, get_assname(), ass->get_description().c_str());
970ed795
EL
7913 }
7914 ActualPar* ret_val_ap = new ActualPar(ref);
7915 // restriction checking if this is a reference to a template variable
7916 // this is an 'out' or 'inout' template parameter
7917 if (is_template && asstype_correct) {
7918 template_restriction_t refd_tr;
7919 switch (ass->get_asstype()) {
7920 case A_VAR_TEMPLATE: {
7921 Def_Var_Template* dvt = dynamic_cast<Def_Var_Template*>(ass);
7922 if (!dvt) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
7923 refd_tr = dvt->get_template_restriction();
7924 } break;
7925 case A_PAR_TEMPL_IN:
7926 case A_PAR_TEMPL_OUT:
7927 case A_PAR_TEMPL_INOUT: {
7928 FormalPar* fp = dynamic_cast<FormalPar*>(ass);
3abe9331 7929 if (!fp) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
970ed795
EL
7930 refd_tr = fp->get_template_restriction();
7931 } break;
7932 default:
7933 FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
7934 break;
7935 }
7936 refd_tr = Template::get_sub_restriction(refd_tr, ref);
7937 if (template_restriction!=refd_tr) {
7938 bool pre_call_check =
7939 Template::is_less_restrictive(template_restriction, refd_tr);
7940 bool post_call_check =
7941 Template::is_less_restrictive(refd_tr, template_restriction);
7942 if (pre_call_check || post_call_check) {
7943 ref->warning("Inadequate restriction on the referenced %s `%s', "
7944 "this may cause a dynamic test case error at runtime",
7945 ass->get_assname(), ref->get_dispname().c_str());
7946 ass->note("Referenced %s is here", ass->get_assname());
7947 }
7948 if (pre_call_check)
7949 ret_val_ap->set_gen_restriction_check(template_restriction);
7950 if (post_call_check)
7951 ret_val_ap->set_gen_post_restriction_check(refd_tr);
7952 }
7953 // for out and inout template parameters of external functions
7954 // always check because we do not trust user written C++ code
7955 if (refd_tr!=TR_NONE) {
7956 switch (my_parlist->get_my_def()->get_asstype()) {
7957 case A_EXT_FUNCTION:
7958 case A_EXT_FUNCTION_RVAL:
7959 case A_EXT_FUNCTION_RTEMP:
7960 ret_val_ap->set_gen_post_restriction_check(refd_tr);
7961 break;
7962 default:
7963 break;
7964 }
7965 }
7966 }
7967 return ret_val_ap;
7968 } else {
7969 actual_par->error("Reference to a %s was expected for an %s",
7970 expected_string, get_assname());
7971 return new ActualPar();
7972 }
7973 }
7974
7975 ActualPar *FormalPar::chk_actual_par_timer(TemplateInstance *actual_par,
7976 Type::expected_value_t exp_val)
7977 {
7978 Type *ap_type = actual_par->get_Type();
7979 if (ap_type) {
7980 ap_type->error("Explicit type specification cannot be used for a "
7981 "timer parameter");
7982 actual_par->chk_Type(0);
7983 }
7984 Ref_base *derived_ref = actual_par->get_DerivedRef();
7985 if (derived_ref) {
7986 derived_ref->error("An in-line modified template cannot be used as "
7987 "timer parameter");
7988 actual_par->chk_DerivedRef(0);
7989 }
7990 Template *ap_template = actual_par->get_Template();
7991 if (ap_template->is_Ref()) {
7992 Ref_base *ref = ap_template->get_Ref();
7993 Common::Assignment *ass = ref->get_refd_assignment();
7994 if (!ass) {
a38c6d4c 7995 delete ref;
7996 return new ActualPar();
970ed795
EL
7997 }
7998 switch (ass->get_asstype()) {
7999 case A_TIMER: {
8000 ArrayDimensions *dims = ass->get_Dimensions();
a38c6d4c 8001 if (dims) dims->chk_indices(ref, "timer", false, exp_val);
8002 else if (ref->get_subrefs()) ref->error("Reference to single %s "
8003 "cannot have field or array sub-references",
8004 ass->get_description().c_str());
8005 break; }
970ed795
EL
8006 case A_PAR_TIMER:
8007 if (ref->get_subrefs()) ref->error("Reference to %s cannot have "
a38c6d4c 8008 "field or array sub-references", ass->get_description().c_str());
8009 break;
970ed795
EL
8010 default:
8011 ref->error("Reference to a timer or timer parameter was expected for "
a38c6d4c 8012 "a timer parameter instead of %s", ass->get_description().c_str());
970ed795
EL
8013 }
8014 return new ActualPar(ref);
8015 } else {
8016 actual_par->error("Reference to a timer or timer parameter was "
8017 "expected for a timer parameter");
8018 return new ActualPar();
8019 }
8020 }
8021
8022 ActualPar *FormalPar::chk_actual_par_port(TemplateInstance *actual_par,
8023 Type::expected_value_t exp_val)
8024 {
8025 Type *ap_type = actual_par->get_Type();
8026 if (ap_type) {
8027 ap_type->warning("Explicit type specification is useless for a port "
8028 "parameter");
8029 actual_par->chk_Type(type);
8030 }
8031 Ref_base *derived_ref = actual_par->get_DerivedRef();
8032 if (derived_ref) {
8033 derived_ref->error("An in-line modified template cannot be used as "
8034 "port parameter");
8035 actual_par->chk_DerivedRef(type);
8036 }
8037 Template *ap_template = actual_par->get_Template();
8038 if (ap_template->is_Ref()) {
8039 Ref_base *ref = ap_template->get_Ref();
8040 Common::Assignment *ass = ref->get_refd_assignment();
8041 if (!ass) {
a38c6d4c 8042 delete ref;
8043 return new ActualPar();
970ed795
EL
8044 }
8045 bool asstype_correct = false;
8046 switch (ass->get_asstype()) {
8047 case A_PORT: {
8048 ArrayDimensions *dims = ass->get_Dimensions();
a38c6d4c 8049 if (dims) dims->chk_indices(ref, "port", false, exp_val);
8050 else if (ref->get_subrefs()) ref->error("Reference to single %s "
8051 "cannot have field or array sub-references",
8052 ass->get_description().c_str());
970ed795 8053 asstype_correct = true;
a38c6d4c 8054 break; }
970ed795
EL
8055 case A_PAR_PORT:
8056 if (ref->get_subrefs()) ref->error("Reference to %s cannot have "
a38c6d4c 8057 "field or array sub-references", ass->get_description().c_str());
970ed795 8058 asstype_correct = true;
a38c6d4c 8059 break;
970ed795
EL
8060 default:
8061 ref->error("Reference to a port or port parameter was expected for a "
a38c6d4c 8062 "port parameter instead of %s", ass->get_description().c_str());
970ed795
EL
8063 }
8064 if (asstype_correct) {
a38c6d4c 8065 Type *ref_type = ass->get_Type();
8066 if (ref_type && !type->is_identical(ref_type))
8067 ref->error("Type mismatch: Reference to a port or port parameter "
8068 "of type `%s' was expected instead of `%s'",
8069 type->get_typename().c_str(), ref_type->get_typename().c_str());
970ed795
EL
8070 }
8071 return new ActualPar(ref);
8072 } else {
8073 actual_par->error("Reference to a port or port parameter was expected "
8074 "for a port parameter");
8075 return new ActualPar();
8076 }
8077 }
8078
8079 void FormalPar::use_as_lvalue(const Location& p_loc)
8080 {
8081 switch (asstype) {
8082 case A_PAR_VAL_IN:
8083 case A_PAR_TEMPL_IN:
8084 break;
8085 default:
8086 FATAL_ERROR("FormalPar::use_as_lvalue()");
8087 }
8088 if (!used_as_lvalue) {
8089 Definition *my_def = my_parlist->get_my_def();
8090 if (!my_def) FATAL_ERROR("FormalPar::use_as_lvalue()");
8091 if (my_def->get_asstype() == A_TEMPLATE)
a38c6d4c 8092 p_loc.error("Parameter `%s' of the template cannot be passed further "
8093 "as `out' or `inout' parameter", id->get_dispname().c_str());
970ed795 8094 else {
a38c6d4c 8095 // update the genname so that all references in the generated code
8096 // will point to the shadow object
970ed795 8097 if (!lazy_eval) {
a38c6d4c 8098 set_genname(id->get_name() + "_shadow");
970ed795 8099 }
a38c6d4c 8100 used_as_lvalue = true;
970ed795
EL
8101 }
8102 }
8103 }
51fa56b9 8104
8105 char* FormalPar::generate_code_defval(char* str)
970ed795 8106 {
51fa56b9 8107 if (!defval.ap || defval_generated) return str;
8108 defval_generated = true;
970ed795
EL
8109 switch (defval.ap->get_selection()) {
8110 case ActualPar::AP_VALUE: {
8111 Value *val = defval.ap->get_Value();
970ed795 8112 if (use_runtime_2 && TypeConv::needs_conv_refd(val)) {
51fa56b9 8113 str = TypeConv::gen_conv_code_refd(str, val->get_lhs_name().c_str(), val);
970ed795 8114 } else {
51fa56b9 8115 str = val->generate_code_init(str, val->get_lhs_name().c_str());
970ed795
EL
8116 }
8117 break; }
8118 case ActualPar::AP_TEMPLATE: {
8119 TemplateInstance *ti = defval.ap->get_TemplateInstance();
8120 Template *temp = ti->get_Template();
970ed795
EL
8121 Ref_base *dref = ti->get_DerivedRef();
8122 if (dref) {
8123 expression_struct expr;
8124 Code::init_expr(&expr);
8125 expr.expr = mputprintf(expr.expr, "%s = ",
8126 temp->get_lhs_name().c_str());
8127 dref->generate_code(&expr);
51fa56b9 8128 str = Code::merge_free_expr(str, &expr, false);
970ed795
EL
8129 }
8130 if (use_runtime_2 && TypeConv::needs_conv_refd(temp)) {
51fa56b9 8131 str = TypeConv::gen_conv_code_refd(str, temp->get_lhs_name().c_str(), temp);
970ed795 8132 } else {
51fa56b9 8133 str = temp->generate_code_init(str, temp->get_lhs_name().c_str());
970ed795
EL
8134 }
8135 if (defval.ap->get_gen_restriction_check() != TR_NONE) {
51fa56b9 8136 str = Template::generate_restriction_check_code(str,
8137 temp->get_lhs_name().c_str(), defval.ap->get_gen_restriction_check());
970ed795
EL
8138 }
8139 break; }
8140 case ActualPar::AP_REF:
8141 break;
8142 default:
8143 FATAL_ERROR("FormalPar::generate_code()");
8144 }
51fa56b9 8145 return str;
8146 }
8147
8148 void FormalPar::generate_code_defval(output_struct *target, bool)
8149 {
8150 if (!defval.ap) return;
8151 switch (defval.ap->get_selection()) {
8152 case ActualPar::AP_VALUE: {
8153 Value *val = defval.ap->get_Value();
8154 const_def cdef;
8155 Code::init_cdef(&cdef);
8156 type->generate_code_object(&cdef, val);
8157 Code::merge_cdef(target, &cdef);
8158 Code::free_cdef(&cdef);
8159 break; }
8160 case ActualPar::AP_TEMPLATE: {
8161 TemplateInstance *ti = defval.ap->get_TemplateInstance();
8162 Template *temp = ti->get_Template();
8163 const_def cdef;
8164 Code::init_cdef(&cdef);
8165 type->generate_code_object(&cdef, temp);
8166 Code::merge_cdef(target, &cdef);
8167 Code::free_cdef(&cdef);
8168 break; }
8169 case ActualPar::AP_REF:
8170 break;
8171 default:
8172 FATAL_ERROR("FormalPar::generate_code()");
8173 }
8174 target->functions.post_init = generate_code_defval(target->functions.post_init);
970ed795
EL
8175 }
8176
8177 char *FormalPar::generate_code_fpar(char *str)
8178 {
8179 const char *name_str = id->get_name().c_str();
8180 switch (asstype) {
8181 case A_PAR_VAL_IN:
8182 if (lazy_eval) {
8183 str = mputprintf(str, "Lazy_Param<%s>& %s", type->get_genname_value(my_scope).c_str(), name_str);
8184 } else {
8185 str = mputprintf(str, "const %s& %s", type->get_genname_value(my_scope).c_str(), name_str);
8186 }
8187 break;
8188 case A_PAR_VAL_OUT:
8189 case A_PAR_VAL_INOUT:
8190 case A_PAR_PORT:
8191 str = mputprintf(str, "%s& %s", type->get_genname_value(my_scope).c_str(),
a38c6d4c 8192 name_str);
970ed795
EL
8193 break;
8194 case A_PAR_TEMPL_IN:
8195 if (lazy_eval) {
8196 str = mputprintf(str, "Lazy_Param<%s>& %s", type->get_genname_template(my_scope).c_str(), name_str);
8197 } else {
8198 str = mputprintf(str, "const %s& %s", type->get_genname_template(my_scope).c_str(), name_str);
8199 }
8200 break;
8201 case A_PAR_TEMPL_OUT:
8202 case A_PAR_TEMPL_INOUT:
8203 str = mputprintf(str, "%s& %s",
a38c6d4c 8204 type->get_genname_template(my_scope).c_str(), name_str);
970ed795
EL
8205 break;
8206 case A_PAR_TIMER:
8207 str = mputprintf(str, "TIMER& %s", name_str);
8208 break;
8209 default:
8210 FATAL_ERROR("FormalPar::generate_code()");
8211 }
8212 return str;
8213 }
8214
8215 string FormalPar::get_reference_name(Scope* scope) const
8216 {
8217 string ret_val;
8218 if (lazy_eval) {
8219 ret_val += "((";
8220 switch (asstype) {
8221 case A_PAR_TEMPL_IN:
8222 ret_val += type->get_genname_template(scope);
8223 break;
8224 default:
8225 ret_val += type->get_genname_value(scope);
8226 break;
8227 }
8228 ret_val += "&)";
8229 }
8230 ret_val += get_id().get_name();
8231 if (lazy_eval) {
8232 ret_val += ")";
8233 }
8234 return ret_val;
8235 }
8236
8237 char *FormalPar::generate_code_object(char *str, const char *p_prefix, char refch)
8238 {
8239 const char *name_str = id->get_name().c_str();
8240 switch (asstype) {
8241 case A_PAR_VAL_IN:
8242 if (lazy_eval) {
8243 str = mputprintf(str, "Lazy_Param<%s> %s%s;\n", type->get_genname_value(my_scope).c_str(), p_prefix, name_str);
8244 } else {
8245 str = mputprintf(str, "%s %s%s;\n", type->get_genname_value(my_scope).c_str(), p_prefix, name_str);
8246 }
8247 break;
8248 case A_PAR_VAL_OUT:
8249 case A_PAR_VAL_INOUT:
8250 case A_PAR_PORT:
8251 str = mputprintf(str, "%s%c %s%s;\n",
a38c6d4c 8252 type->get_genname_value(my_scope).c_str(), refch, p_prefix, name_str);
970ed795
EL
8253 break;
8254 case A_PAR_TEMPL_IN:
8255 if (lazy_eval) {
8256 str = mputprintf(str, "Lazy_Param<%s> %s%s;\n", type->get_genname_template(my_scope).c_str(), p_prefix, name_str);
8257 } else {
8258 str = mputprintf(str, "%s %s%s;\n", type->get_genname_template(my_scope).c_str(), p_prefix, name_str);
8259 }
8260 break;
8261 case A_PAR_TEMPL_OUT:
8262 case A_PAR_TEMPL_INOUT:
8263 str = mputprintf(str, "%s%c %s%s;\n",
a38c6d4c 8264 type->get_genname_template(my_scope).c_str(), refch, p_prefix, name_str);
970ed795
EL
8265 break;
8266 case A_PAR_TIMER:
8267 str = mputprintf(str, "TIMER& %s%s;\n", p_prefix, name_str);
8268 break;
8269 default:
8270 FATAL_ERROR("FormalPar::generate_code_object()");
8271 }
8272 return str;
8273 }
8274
8275 char *FormalPar::generate_shadow_object(char *str) const
8276 {
8277 if (used_as_lvalue && !lazy_eval) {
8278 const string& t_genname = get_genname();
8279 const char *genname_str = t_genname.c_str();
8280 const char *name_str = id->get_name().c_str();
8281 switch (asstype) {
8282 case A_PAR_VAL_IN:
a38c6d4c 8283 str = mputprintf(str, "%s %s(%s);\n",
8284 type->get_genname_value(my_scope).c_str(), genname_str, name_str);
8285 break;
970ed795 8286 case A_PAR_TEMPL_IN:
a38c6d4c 8287 str = mputprintf(str, "%s %s(%s);\n",
8288 type->get_genname_template(my_scope).c_str(), genname_str, name_str);
8289 break;
970ed795 8290 default:
a38c6d4c 8291 FATAL_ERROR("FormalPar::generate_shadow_object()");
970ed795
EL
8292 }
8293 }
8294 return str;
8295 }
8296
8297 char *FormalPar::generate_code_set_unbound(char *str) const
8298 {
8299 switch (asstype) {
8300 case A_PAR_TEMPL_OUT:
8301 case A_PAR_VAL_OUT:
8302 str = mputprintf(str, "%s.clean_up();\n", id->get_name().c_str());
8303 break;
8304 default:
8305 break;
8306 }
8307 return str;
8308 }
8309
8310 void FormalPar::dump_internal(unsigned level) const
8311 {
8312 DEBUG(level, "%s: %s", get_assname(), id->get_dispname().c_str());
8313 if (type) type->dump(level + 1);
8314 if (checked) {
8315 if (defval.ap) {
8316 DEBUG(level + 1, "default value:");
8317 defval.ap->dump(level + 2);
8318 }
8319 } else {
8320 if (defval.ti) {
8321 DEBUG(level + 1, "default value:");
8322 defval.ti->dump(level + 2);
8323 }
8324 }
8325 }
8326
8327 // =================================
8328 // ===== FormalParList
8329 // =================================
8330
8331 FormalParList::~FormalParList()
8332 {
8333 size_t nof_pars = pars_v.size();
8334 for (size_t i = 0; i < nof_pars; i++) delete pars_v[i];
8335 pars_v.clear();
8336 pars_m.clear();
8337 }
8338
8339 FormalParList *FormalParList::clone() const
8340 {
8341 FATAL_ERROR("FormalParList::clone");
8342 }
8343
8344 void FormalParList::set_fullname(const string& p_fullname)
8345 {
8346 Node::set_fullname(p_fullname);
8347 for (size_t i = 0; i < pars_v.size(); i++) {
8348 FormalPar *par = pars_v[i];
8349 par->set_fullname(p_fullname + "." + par->get_id().get_dispname());
8350 }
8351 }
8352
8353 void FormalParList::set_my_scope(Scope *p_scope)
8354 {
8355 set_parent_scope(p_scope);
8356 Node::set_my_scope(p_scope);
8357 // the scope of parameters is set to the parent scope instead of this
8358 // because they cannot refer to each other
8359 for (size_t i = 0; i < pars_v.size(); i++) pars_v[i]->set_my_scope(p_scope);
8360 }
8361
8362 void FormalParList::add_fp(FormalPar *p_fp)
8363 {
8364 if (!p_fp) FATAL_ERROR("NULL parameter: Ttcn::FormalParList::add_fp()");
8365 pars_v.add(p_fp);
8366 p_fp->set_my_parlist(this);
8367 checked = false;
8368 }
8369
8370 bool FormalParList::has_notused_defval() const
8371 {
8372 for (size_t i = 0; i < pars_v.size(); i++) {
8373 if (pars_v[i]->has_notused_defval())
8374 return true;
8375 }
8376 return false;
8377 }
8378
8379 bool FormalParList::has_only_default_values() const
8380 {
8381 for (size_t i = 0; i < pars_v.size(); i++) {
8382 if (!pars_v[i]->has_defval()) {
8383 return false;
8384 }
8385 }
8386
8387 return true;
8388 }
8389
8390 bool FormalParList::has_fp_withName(const Identifier& p_name)
8391 {
8392 if (!checked) chk(Definition::A_UNDEF);
8393 return pars_m.has_key(p_name.get_name());
8394 }
8395
8396 FormalPar *FormalParList::get_fp_byName(const Identifier& p_name)
8397 {
8398 if (!checked) chk(Definition::A_UNDEF);
8399 return pars_m[p_name.get_name()];
8400 }
8401
8402 bool FormalParList::get_startability()
8403 {
8404 if(!checked) FATAL_ERROR("FormalParList::get_startability()");
8405 return is_startable;
8406 }
8407
8408 Common::Assignment *FormalParList::get_ass_bySRef(Common::Ref_simple *p_ref)
8409 {
8410 if (!p_ref || !checked) FATAL_ERROR("FormalParList::get_ass_bySRef()");
8411 if (p_ref->get_modid()) return parent_scope->get_ass_bySRef(p_ref);
8412 else {
8413 const string& name = p_ref->get_id()->get_name();
8414 if (pars_m.has_key(name)) return pars_m[name];
8415 else return parent_scope->get_ass_bySRef(p_ref);
8416 }
8417 }
8418
8419 bool FormalParList::has_ass_withId(const Identifier& p_id)
8420 {
8421 if (!checked) FATAL_ERROR("Ttcn::FormalParList::has_ass_withId()");
8422 return pars_m.has_key(p_id.get_name())
8423 || parent_scope->has_ass_withId(p_id);
8424 }
8425
8426 void FormalParList::set_genname(const string& p_prefix)
8427 {
8428 for (size_t i = 0; i < pars_v.size(); i++) {
8429 FormalPar *par = pars_v[i];
8430 const string& par_name = par->get_id().get_name();
8431 if (par->get_asstype() != Definition::A_PAR_TIMER)
a38c6d4c 8432 par->get_Type()->set_genname(p_prefix, par_name);
970ed795 8433 if (par->has_defval()) {
a38c6d4c 8434 string embedded_genname(p_prefix);
8435 embedded_genname += '_';
8436 embedded_genname += par_name;
8437 embedded_genname += "_defval";
970ed795
EL
8438 ActualPar *defval = par->get_defval();
8439 switch (defval->get_selection()) {
8440 case ActualPar::AP_ERROR:
8441 case ActualPar::AP_REF:
8442 break;
8443 case ActualPar::AP_VALUE: {
a38c6d4c 8444 Value *v = defval->get_Value();
970ed795 8445 v->set_genname_prefix("const_");
a38c6d4c 8446 v->set_genname_recursive(embedded_genname);
970ed795
EL
8447 break; }
8448 case ActualPar::AP_TEMPLATE: {
a38c6d4c 8449 Template *t = defval->get_TemplateInstance()->get_Template();
8450 t->set_genname_prefix("template_");
8451 t->set_genname_recursive(embedded_genname);
8452 break; }
970ed795
EL
8453 default:
8454 FATAL_ERROR("FormalParList::set_genname()");
8455 }
8456 }
8457 }
8458 }
8459
8460 void FormalParList::chk(Definition::asstype_t deftype)
8461 {
8462 if (checked) return;
8463 checked = true;
8464 min_nof_pars = 0;
8465 is_startable = true;
8466 Error_Context cntxt(this, "In formal parameter list");
8467 for (size_t i = 0; i < pars_v.size(); i++) {
8468 FormalPar *par = pars_v[i];
8469 const Identifier& id = par->get_id();
8470 const string& name = id.get_name();
8471 const char *dispname = id.get_dispname().c_str();
8472 if (pars_m.has_key(name)) {
a38c6d4c 8473 par->error("Duplicate parameter with name `%s'", dispname);
8474 pars_m[name]->note("Previous definition of `%s' is here", dispname);
970ed795 8475 } else {
a38c6d4c 8476 pars_m.add(name, par);
8477 if (parent_scope && parent_scope->has_ass_withId(id)) {
8478 par->error("Parameter name `%s' is not unique in the scope "
8479 "hierarchy", dispname);
8480 Reference ref(0, id.clone());
8481 Common::Assignment *ass = parent_scope->get_ass_bySRef(&ref);
8482 if (!ass) FATAL_ERROR("FormalParList::chk()");
8483 ass->note("Symbol `%s' is already defined here in a higher scope "
8484 "unit", dispname);
8485 }
970ed795
EL
8486 }
8487 Error_Context cntxt2(par, "In parameter `%s'", dispname);
8488 par->chk();
8489 // check whether the parameter type is allowed
8490 switch (deftype) {
8491 case Definition::A_TEMPLATE:
8492 switch (par->get_asstype()) {
a38c6d4c 8493 case Definition::A_PAR_VAL_IN:
8494 case Definition::A_PAR_TEMPL_IN:
8495 // these are allowed
970ed795 8496 break;
a38c6d4c 8497 default:
970ed795 8498 par->error("A template cannot have %s", par->get_assname());
a38c6d4c 8499 }
8500 break;
970ed795
EL
8501 case Definition::A_TESTCASE:
8502 switch (par->get_asstype()) {
a38c6d4c 8503 case Definition::A_PAR_TIMER:
8504 case Definition::A_PAR_PORT:
8505 // these are forbidden
970ed795 8506 par->error("A testcase cannot have %s", par->get_assname());
a38c6d4c 8507 default:
970ed795 8508 break;
a38c6d4c 8509 }
970ed795
EL
8510 default:
8511 // everything is allowed for functions and altsteps
8512 break;
8513 }
8514 //startability chk
8515 switch(par->get_asstype()) {
8516 case Common::Assignment::A_PAR_VAL_IN:
8517 case Common::Assignment::A_PAR_TEMPL_IN:
8518 case Common::Assignment::A_PAR_VAL_INOUT:
8519 case Common::Assignment::A_PAR_TEMPL_INOUT:
8520 if (is_startable && par->get_Type()->is_component_internal())
8521 is_startable = false;
8522 break;
8523 default:
8524 is_startable = false;
8525 break;
8526 }
8527 if (!par->has_defval()) min_nof_pars = i + 1;
8528 // the last parameter without a default value determines the minimum
8529 }
8530 }
8531
8532 // check that @lazy paramterization not used in cases currently unsupported
8533 void FormalParList::chk_noLazyParams() {
8534 Error_Context cntxt(this, "In formal parameter list");
8535 for (size_t i = 0; i < pars_v.size(); i++) {
8536 FormalPar *par = pars_v[i];
8537 if (par->get_lazy_eval()) {
8538 par->error("Formal parameter `%s' cannot be @lazy, not supported in this case.",
8539 par->get_id().get_dispname().c_str());
8540 }
8541 }
8542 }
8543
8544 void FormalParList::chk_startability(const char *p_what, const char *p_name)
8545 {
8546 if(!checked) FATAL_ERROR("FormalParList::chk_startability()");
8547 if (is_startable) return;
8548 for (size_t i = 0; i < pars_v.size(); i++) {
8549 FormalPar *par = pars_v[i];
8550 switch (par->get_asstype()) {
8551 case Common::Assignment::A_PAR_VAL_IN:
8552 case Common::Assignment::A_PAR_TEMPL_IN:
8553 case Common::Assignment::A_PAR_VAL_INOUT:
8554 case Common::Assignment::A_PAR_TEMPL_INOUT:
8555 if (par->get_Type()->is_component_internal()) {
8556 map<Type*,void> type_chain;
8557 char* err_str = mprintf("a parameter or embedded in a parameter of "
8558 "a function used in a start operation. "
8559 "%s `%s' cannot be started on a parallel test component "
8560 "because of `%s'", p_what, p_name, par->get_description().c_str());
8561 par->get_Type()->chk_component_internal(type_chain, err_str);
8562 Free(err_str);
8563 }
8564 break;
8565 default:
8566 par->error("%s `%s' cannot be started on a parallel test component "
a38c6d4c 8567 "because it has %s", p_what, p_name, par->get_description().c_str());
970ed795
EL
8568 }
8569 }
8570 }
8571
8572 void FormalParList::chk_compatibility(FormalParList* p_fp_list,
8573 const char* where)
8574 {
8575 size_t nof_type_pars = pars_v.size();
8576 size_t nof_function_pars = p_fp_list->pars_v.size();
8577 // check for the number of parameters
8578 if (nof_type_pars != nof_function_pars) {
8579 p_fp_list->error("Too %s parameters: %lu was expected instead of %lu",
a38c6d4c 8580 nof_type_pars < nof_function_pars ? "many" : "few",
8581 (unsigned long) nof_type_pars, (unsigned long) nof_function_pars);
970ed795
EL
8582 }
8583 size_t upper_limit =
8584 nof_type_pars < nof_function_pars ? nof_type_pars : nof_function_pars;
8585 for (size_t i = 0; i < upper_limit; i++) {
8586 FormalPar *type_par = pars_v[i];
8587 FormalPar *function_par = p_fp_list->pars_v[i];
8588 Error_Context cntxt(function_par, "In parameter #%lu",
8589 (unsigned long) (i + 1));
8590 FormalPar::asstype_t type_par_asstype = type_par->get_asstype();
8591 FormalPar::asstype_t function_par_asstype = function_par->get_asstype();
8592 // check for parameter kind equivalence
8593 // (in, out or inout / value or template)
8594 if (type_par_asstype != function_par_asstype) {
a38c6d4c 8595 function_par->error("The kind of the parameter is not the same as in "
8596 "type `%s': %s was expected instead of %s", where,
8597 type_par->get_assname(), function_par->get_assname());
970ed795
EL
8598 }
8599 // check for type equivalence
8600 if (type_par_asstype != FormalPar::A_PAR_TIMER &&
a38c6d4c 8601 function_par_asstype != FormalPar::A_PAR_TIMER) {
8602 Type *type_par_type = type_par->get_Type();
8603 Type *function_par_type = function_par->get_Type();
8604 if (!type_par_type->is_identical(function_par_type)) {
8605 function_par_type->error("The type of the parameter is not the same "
8606 "as in type `%s': `%s' was expected instead of `%s'", where,
8607 type_par_type->get_typename().c_str(),
8608 function_par_type->get_typename().c_str());
8609 } else if (type_par_type->get_sub_type() && function_par_type->get_sub_type() &&
970ed795
EL
8610 (type_par_type->get_sub_type()->get_subtypetype()==function_par_type->get_sub_type()->get_subtypetype()) &&
8611 (!type_par_type->get_sub_type()->is_compatible(function_par_type->get_sub_type()))) {
8612 // TODO: maybe equivalence should be checked, or maybe that is too strict
8613 function_par_type->error(
8614 "Subtype mismatch: subtype %s has no common value with subtype %s",
8615 type_par_type->get_sub_type()->to_string().c_str(),
8616 function_par_type->get_sub_type()->to_string().c_str());
8617 }
8618 }
8619 // check for template restriction equivalence
8620 if (type_par->get_template_restriction()!=
8621 function_par->get_template_restriction()) {
8622 function_par->error("The template restriction of the parameter is "
8623 "not the same as in type `%s': %s restriction was expected instead "
8624 "of %s restriction", where,
a38c6d4c 8625 type_par->get_template_restriction()==TR_NONE ? "no" :
970ed795
EL
8626 Template::get_restriction_name(type_par->get_template_restriction()),
8627 function_par->get_template_restriction()==TR_NONE ? "no" :
8628 Template::get_restriction_name(function_par->
8629 get_template_restriction()));
8630 }
8631 // check for @lazy equivalence
8632 if (type_par->get_lazy_eval()!=function_par->get_lazy_eval()) {
8633 function_par->error("Parameter @lazy-ness mismatch");
8634 }
8635 // check for name equivalence
8636 const Identifier& type_par_id = type_par->get_id();
8637 const Identifier& function_par_id = function_par->get_id();
8638 if (type_par_id != function_par_id) {
a38c6d4c 8639 function_par->warning("The name of the parameter is not the same "
8640 "as in type `%s': `%s' was expected instead of `%s'", where,
8641 type_par_id.get_dispname().c_str(),
8642 function_par_id.get_dispname().c_str());
970ed795
EL
8643 }
8644 }
8645 }
8646
8647 bool FormalParList::fold_named_and_chk(ParsedActualParameters *p_paps,
8648 ActualParList *p_aplist)
8649 {
8650 const size_t num_named = p_paps->get_nof_nps();
8651 const size_t num_unnamed = p_paps->get_nof_tis();
8652 size_t num_actual = num_unnamed;
8653
8654 // Construct a map to tell us what index a FormalPar has
8655 typedef map<FormalPar*, size_t> formalpar_map_t;
8656 formalpar_map_t formalpar_map;
8657
8658 size_t num_fp = get_nof_fps();
8659 for (size_t fpx = 0; fpx < num_fp; ++fpx) {
8660 FormalPar *fp = get_fp_byIndex(fpx);
8661 formalpar_map.add(fp, new size_t(fpx));
8662 }
8663
8664 // Go through the named parameters
8665 for (size_t i = 0; i < num_named; ++i) {
8666 NamedParam *np = p_paps->extract_np_byIndex(i);
8667 // We are now responsible for np.
8668
8669 if (has_fp_withName(*np->get_name())) {
a38c6d4c 8670 // there is a formal parameter with that name
8671 FormalPar *fp = get_fp_byName(*np->get_name());
8672 const size_t is_at = *formalpar_map[fp]; // the index of the formal par
8673 if (is_at >= num_actual) {
8674 // There is no actual par in the unnamed part.
8675 // Create one from the named param.
8676
8677 // First, pad the gap with '-'
8678 for (; num_actual < is_at; ++num_actual) {
8679 Template *not_used;
8680 if (pars_v[num_actual]->has_defval()) {
8681 not_used = new Template(Template::TEMPLATE_NOTUSED);
8682 }
8683 else { // cannot use '-' if no default value
8684 not_used = new Template(Template::TEMPLATE_ERROR);
8685 }
8686 TemplateInstance *new_ti = new TemplateInstance(0, 0, not_used);
8687 // Conjure a location info at the beginning of the unnamed part
8688 // (that is, the beginning of the actual parameter list)
8689 new_ti->set_location(p_paps->get_tis()->get_filename(),
8690 p_paps->get_tis()->get_first_line(),
8691 p_paps->get_tis()->get_first_column(), 0, 0);
8692 p_paps->get_tis()->add_ti(new_ti);
8693 }
8694 TemplateInstance * namedti = np->extract_ti();
8695 p_paps->get_tis()->add_ti(namedti);
8696 ++num_actual;
8697 } else {
8698 // There is already an actual par at that position, fetch it
8699 TemplateInstance * ti = p_paps->get_tis()->get_ti_byIndex(is_at);
8700 Template::templatetype_t tt = ti->get_Template()->get_templatetype();
8701
8702 if (is_at >= num_unnamed && !ti->get_Type() && !ti->get_DerivedRef()
8703 && (tt == Template::TEMPLATE_NOTUSED || tt == Template::TEMPLATE_ERROR)) {
8704 // NotUsed in the named part => padding
8705 np->error("Named parameter `%s' out of order",
8706 np->get_name()->get_dispname().c_str());
8707 } else {
8708 // attempt to override an original unnamed param with a named one
8709 np->error("Formal parameter `%s' assigned more than once",
8710 np->get_name()->get_dispname().c_str());
8711 }
8712 }
970ed795
EL
8713 }
8714 else { // no formal parameter with that name
a38c6d4c 8715 char * nam = 0;
8716 switch (my_def->get_asstype()) {
8717 case Common::Assignment::A_TYPE: {
8718 Type *t = my_def->get_Type();
8719
8720 switch (t ? t->get_typetype() : 0) {
8721 case Type::T_FUNCTION:
8722 nam = mcopystr("Function reference");
8723 break;
8724 case Type::T_ALTSTEP:
8725 nam = mcopystr("Altstep reference");
8726 break;
8727 case Type::T_TESTCASE:
8728 nam = mcopystr("Testcase reference");
8729 break;
8730 default:
8731 FATAL_ERROR("FormalParList::chk_actual_parlist() "
8732 "Unexpected type %s", t->get_typename().c_str());
8733 } // switch(typetype)
8734 break; }
8735 default:
8736 nam = mcopystr(my_def->get_assname());
8737 break;
8738 } // switch(asstype)
8739
8740 *nam &= ~('a'-'A'); // Make the first letter uppercase
8741 p_paps->get_tis()->error("%s `%s' has no formal parameter `%s'",
8742 nam,
8743 my_def->get_fullname().c_str(),
8744 np->get_name()->get_dispname().c_str());
8745 Free(nam);
970ed795
EL
8746 }
8747 delete np;
8748 }
8749
8750 // Cleanup
8751 for (size_t fpx = 0; fpx < num_fp; ++fpx) {
8752 delete formalpar_map.get_nth_elem(fpx);
8753 }
8754 formalpar_map.clear();
8755
8756 return chk_actual_parlist(p_paps->get_tis(), p_aplist);
8757 }
8758
8759 bool FormalParList::chk_actual_parlist(TemplateInstances *p_tis,
8760 ActualParList *p_aplist)
8761 {
8762 size_t formal_pars = pars_v.size();
8763 size_t actual_pars = p_tis->get_nof_tis();
8764 // p_aplist->get_nof_pars() is usually 0 on entry
8765 bool error_flag = false;
8766
8767 if (min_nof_pars == formal_pars) {
8768 // none of the parameters have default value
8769 if (actual_pars != formal_pars) {
8770 p_tis->error("Too %s parameters: %lu was expected "
8771 "instead of %lu", actual_pars < formal_pars ? "few" : "many",
8772 (unsigned long) formal_pars, (unsigned long) actual_pars);
8773 error_flag = true;
8774 }
8775 } else {
8776 // some parameters have default value
8777 if (actual_pars < min_nof_pars) {
8778 p_tis->error("Too few parameters: at least %lu "
8779 "was expected instead of %lu",
8780 (unsigned long) min_nof_pars, (unsigned long) actual_pars);
8781 error_flag = true;
8782 } else if (actual_pars > formal_pars) {
8783 p_tis->error("Too many parameters: at most %lu "
8784 "was expected instead of %lu",
8785 (unsigned long) formal_pars, (unsigned long) actual_pars);
8786 error_flag = true;
8787 }
8788 }
8789
8790 // Do not check actual parameters in excess of the formal ones
8791 size_t upper_limit = actual_pars < formal_pars ? actual_pars : formal_pars;
8792 for (size_t i = 0; i < upper_limit; i++) {
8793 TemplateInstance *ti = p_tis->get_ti_byIndex(i);
8794
8795 // the formal parameter for the current actual parameter
8796 FormalPar *fp = pars_v[i];
8797 Error_Context cntxt(ti, "In parameter #%lu for `%s'",
a38c6d4c 8798 (unsigned long) (i + 1), fp->get_id().get_dispname().c_str());
970ed795 8799 if (!ti->get_Type() && !ti->get_DerivedRef() && ti->get_Template()
a38c6d4c 8800 ->get_templatetype() == Template::TEMPLATE_NOTUSED) {
8801 if (fp->has_defval()) {
8802 ActualPar *defval = fp->get_defval();
8803 p_aplist->add(new ActualPar(defval));
8804 if (defval->is_erroneous()) error_flag = true;
8805 } else {
8806 ti->error("Not used symbol (`-') cannot be used for parameter "
8807 "that does not have default value");
8808 p_aplist->add(new ActualPar());
8809 error_flag = true;
8810 }
970ed795 8811 } else if (!ti->get_Type() && !ti->get_DerivedRef() && ti->get_Template()
a38c6d4c 8812 ->get_templatetype() == Template::TEMPLATE_ERROR) {
8813 ti->error("Parameter not specified");
970ed795
EL
8814 } else {
8815 ActualPar *ap = fp->chk_actual_par(ti, Type::EXPECTED_DYNAMIC_VALUE);
8816 p_aplist->add(ap);
8817 if (ap->is_erroneous()) error_flag = true;
8818 }
8819 }
8820
8821 // The rest of formal parameters have no corresponding actual parameters.
8822 // Create actual parameters for them based on their default values
8823 // (which must exist).
8824 for (size_t i = upper_limit; i < formal_pars; i++) {
8825 FormalPar *fp = pars_v[i];
8826 if (fp->has_defval()) {
a38c6d4c 8827 ActualPar *defval = fp->get_defval();
970ed795
EL
8828 p_aplist->add(new ActualPar(defval));
8829 if (defval->is_erroneous()) error_flag = true;
8830 } else {
8831 p_aplist->add(new ActualPar()); // erroneous
8832 error_flag = true;
8833 }
8834 }
8835 return error_flag;
8836 }
8837
8838 bool FormalParList::chk_activate_argument(ActualParList *p_aplist,
8839 const char* p_description)
8840 {
8841 bool ret_val = true;
8842 for(size_t i = 0; i < p_aplist->get_nof_pars(); i++) {
8843 ActualPar *t_ap = p_aplist->get_par(i);
8844 if(t_ap->get_selection() != ActualPar::AP_REF) continue;
8845 FormalPar *t_fp = pars_v[i];
8846 switch(t_fp->get_asstype()) {
8847 case Common::Assignment::A_PAR_VAL_OUT:
8848 case Common::Assignment::A_PAR_VAL_INOUT:
8849 case Common::Assignment::A_PAR_TEMPL_OUT:
8850 case Common::Assignment::A_PAR_TEMPL_INOUT:
8851 case Common::Assignment::A_PAR_TIMER:
8852 //the checking shall be performed for these parameter types
8853 break;
8854 case Common::Assignment::A_PAR_PORT:
8855 // port parameters are always correct because ports can be defined
8856 // only in component types
8857 continue;
8858 default:
8859 FATAL_ERROR("FormalParList::chk_activate_argument()");
8860 }
8861 Ref_base *t_ref = t_ap->get_Ref();
8862 Common::Assignment *t_par_ass = t_ref->get_refd_assignment();
8863 if(!t_par_ass) FATAL_ERROR("FormalParList::chk_activate_argument()");
8864 switch (t_par_ass->get_asstype()) {
8865 case Common::Assignment::A_VAR:
8866 case Common::Assignment::A_VAR_TEMPLATE:
8867 case Common::Assignment::A_TIMER:
a38c6d4c 8868 // it is not allowed to pass references of local variables or timers
8869 if (t_par_ass->is_local()) {
8870 t_ref->error("Parameter #%lu of %s refers to %s, which is a local "
8871 "definition within a statement block and may have shorter "
8872 "lifespan than the activated default. Only references to "
8873 "variables and timers defined in the component type can be passed "
8874 "to activated defaults", (unsigned long) (i + 1), p_description,
8875 t_par_ass->get_description().c_str());
8876 ret_val = false;
8877 }
8878 break;
970ed795
EL
8879 case Common::Assignment::A_PAR_VAL_IN:
8880 case Common::Assignment::A_PAR_VAL_OUT:
8881 case Common::Assignment::A_PAR_VAL_INOUT:
8882 case Common::Assignment::A_PAR_TEMPL_IN:
8883 case Common::Assignment::A_PAR_TEMPL_OUT:
8884 case Common::Assignment::A_PAR_TEMPL_INOUT:
8885 case Common::Assignment::A_PAR_TIMER: {
a38c6d4c 8886 // it is not allowed to pass references pointing to formal parameters
8887 // except for activate() statements within testcases
8888 // note: all defaults are deactivated at the end of the testcase
8889 FormalPar *t_refd_fp = dynamic_cast<FormalPar*>(t_par_ass);
8890 if (!t_refd_fp) FATAL_ERROR("FormalParList::chk_activate_argument()");
8891 FormalParList *t_fpl = t_refd_fp->get_my_parlist();
8892 if (!t_fpl || !t_fpl->my_def)
8893 FATAL_ERROR("FormalParList::chk_activate_argument()");
8894 if (t_fpl->my_def->get_asstype() != Common::Assignment::A_TESTCASE) {
970ed795 8895 t_ref->error("Parameter #%lu of %s refers to %s, which may have "
a38c6d4c 8896 "shorter lifespan than the activated default. Only references to "
8897 "variables and timers defined in the component type can be passed "
8898 "to activated defaults", (unsigned long) (i + 1), p_description,
8899 t_par_ass->get_description().c_str());
970ed795 8900 ret_val = false;
a38c6d4c 8901 } }
970ed795 8902 default:
a38c6d4c 8903 break;
970ed795
EL
8904 }
8905 }
8906 return ret_val;
8907 }
8908
8909 char *FormalParList::generate_code(char *str)
8910 {
8911 for (size_t i = 0; i < pars_v.size(); i++) {
8912 if (i > 0) str = mputstr(str, ", ");
8913 str = pars_v[i]->generate_code_fpar(str);
8914 }
8915 return str;
8916 }
51fa56b9 8917
8918 char* FormalParList::generate_code_defval(char* str)
8919 {
8920 for (size_t i = 0; i < pars_v.size(); i++) {
8921 str = pars_v[i]->generate_code_defval(str);
8922 }
8923 return str;
8924 }
970ed795
EL
8925
8926 void FormalParList::generate_code_defval(output_struct *target)
8927 {
51fa56b9 8928 for (size_t i = 0; i < pars_v.size(); i++) {
970ed795 8929 pars_v[i]->generate_code_defval(target);
51fa56b9 8930 }
970ed795
EL
8931 }
8932
8933 char *FormalParList::generate_code_actual_parlist(char *str,
8934 const char *p_prefix)
8935 {
8936 for (size_t i = 0; i < pars_v.size(); i++) {
8937 if (i > 0) str = mputstr(str, ", ");
8938 str = mputstr(str, p_prefix);
8939 str = mputstr(str, pars_v[i]->get_id().get_name().c_str());
8940 }
8941 return str;
8942 }
8943
8944 char *FormalParList::generate_code_object(char *str, const char *p_prefix, char refch)
8945 {
8946 for (size_t i = 0; i < pars_v.size(); i++)
8947 str = pars_v[i]->generate_code_object(str, p_prefix, refch);
8948 return str;
8949 }
8950
8951 char *FormalParList::generate_shadow_objects(char *str) const
8952 {
8953 for (size_t i = 0; i < pars_v.size(); i++)
8954 str = pars_v[i]->generate_shadow_object(str);
8955 return str;
8956 }
8957
8958 char *FormalParList::generate_code_set_unbound(char *str) const
8959 {
8960 if (enable_set_bound_out_param) return str;
8961 for (size_t i = 0; i < pars_v.size(); i++)
8962 str = pars_v[i]->generate_code_set_unbound(str);
8963 return str;
8964 }
8965
8966
8967 void FormalParList::dump(unsigned level) const
8968 {
8969 size_t nof_pars = pars_v.size();
8970 DEBUG(level, "formal parameters: %lu pcs.", (unsigned long) nof_pars);
8971 for(size_t i = 0; i < nof_pars; i++) pars_v[i]->dump(level + 1);
8972 }
8973
8974 // =================================
8975 // ===== ActualPar
8976 // =================================
8977
8978 ActualPar::ActualPar(Value *v)
8979 : Node(), selection(AP_VALUE), my_scope(0), gen_restriction_check(TR_NONE),
8980 gen_post_restriction_check(TR_NONE)
8981 {
8982 if (!v) FATAL_ERROR("ActualPar::ActualPar()");
8983 val = v;
8984 }
8985
8986 ActualPar::ActualPar(TemplateInstance *t)
8987 : Node(), selection(AP_TEMPLATE), my_scope(0),
8988 gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE)
8989 {
8990 if (!t) FATAL_ERROR("ActualPar::ActualPar()");
8991 temp = t;
8992 }
8993
8994 ActualPar::ActualPar(Ref_base *r)
8995 : Node(), selection(AP_REF), my_scope(0), gen_restriction_check(TR_NONE),
8996 gen_post_restriction_check(TR_NONE)
8997 {
8998 if (!r) FATAL_ERROR("ActualPar::ActualPar()");
8999 ref = r;
9000 }
9001
9002 ActualPar::ActualPar(ActualPar *a)
9003 : Node(), selection(AP_DEFAULT), my_scope(0),
9004 gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE)
9005 {
9006 if (!a) FATAL_ERROR("ActualPar::ActualPar()");
9007 act = a;
9008 }
9009
9010 ActualPar::~ActualPar()
9011 {
9012 switch(selection) {
9013 case AP_ERROR:
9014 break;
9015 case AP_VALUE:
9016 delete val;
9017 break;
9018 case AP_TEMPLATE:
9019 delete temp;
9020 break;
9021 case AP_REF:
9022 delete ref;
9023 break;
9024 case AP_DEFAULT:
9025 break; // nothing to do with act
9026 default:
9027 FATAL_ERROR("ActualPar::~ActualPar()");
9028 }
9029 }
9030
9031 ActualPar *ActualPar::clone() const
9032 {
9033 FATAL_ERROR("ActualPar::clone");
9034 }
9035
9036 void ActualPar::set_fullname(const string& p_fullname)
9037 {
9038 Node::set_fullname(p_fullname);
9039 switch(selection) {
9040 case AP_ERROR:
9041 break;
9042 case AP_VALUE:
9043 val->set_fullname(p_fullname);
9044 break;
9045 case AP_TEMPLATE:
9046 temp->set_fullname(p_fullname);
9047 break;
9048 case AP_REF:
9049 ref->set_fullname(p_fullname);
9050 break;
9051 case AP_DEFAULT:
9052 break;
9053 default:
9054 FATAL_ERROR("ActualPar::set_fullname()");
9055 }
9056 }
9057
9058 void ActualPar::set_my_scope(Scope *p_scope)
9059 {
9060 my_scope = p_scope;
9061 switch(selection) {
9062 case AP_ERROR:
9063 break;
9064 case AP_VALUE:
9065 val->set_my_scope(p_scope);
9066 break;
9067 case AP_TEMPLATE:
9068 temp->set_my_scope(p_scope);
9069 break;
9070 case AP_REF:
9071 ref->set_my_scope(p_scope);
9072 break;
9073 case AP_DEFAULT:
9074 switch (act->selection) {
9075 case AP_REF:
9076 ref->set_my_scope(p_scope);
9077 break;
9078 case AP_VALUE:
9079 break;
9080 case AP_TEMPLATE:
9081 break;
9082 default:
9083 FATAL_ERROR("ActualPar::set_my_scope()");
9084 }
9085 break;
9086 default:
9087 FATAL_ERROR("ActualPar::set_my_scope()");
9088 }
9089 }
9090
9091 Value *ActualPar::get_Value() const
9092 {
9093 if (selection != AP_VALUE) FATAL_ERROR("ActualPar::get_Value()");
9094 return val;
9095 }
9096
9097 TemplateInstance *ActualPar::get_TemplateInstance() const
9098 {
9099 if (selection != AP_TEMPLATE)
9100 FATAL_ERROR("ActualPar::get_TemplateInstance()");
9101 return temp;
9102 }
9103
9104 Ref_base *ActualPar::get_Ref() const
9105 {
9106 if (selection != AP_REF) FATAL_ERROR("ActualPar::get_Ref()");
9107 return ref;
9108 }
9109
9110 ActualPar *ActualPar::get_ActualPar() const
9111 {
9112 if (selection != AP_DEFAULT) FATAL_ERROR("ActualPar::get_ActualPar()");
9113 return act;
9114 }
9115
9116 void ActualPar::chk_recursions(ReferenceChain& refch)
9117 {
9118 switch (selection) {
9119 case AP_VALUE:
9120 refch.mark_state();
9121 val->chk_recursions(refch);
9122 refch.prev_state();
9123 break;
9124 case AP_TEMPLATE: {
9125 Ref_base *derived_ref = temp->get_DerivedRef();
9126 if (derived_ref) {
9127 ActualParList *parlist = derived_ref->get_parlist();
9128 if (parlist) {
9129 refch.mark_state();
9130 parlist->chk_recursions(refch);
9131 refch.prev_state();
9132 }
9133 }
9134
9135 Ttcn::Def_Template* defTemp = temp->get_Referenced_Base_Template();
9136 if (defTemp) {
9137 refch.mark_state();
9138 refch.add(defTemp->get_fullname());
9139 refch.prev_state();
9140 }
9141 refch.mark_state();
9142 temp->get_Template()->chk_recursions(refch);
9143 refch.prev_state();
9144 }
9145 default:
9146 break;
9147 }
9148 }
9149
9150 bool ActualPar::has_single_expr()
9151 {
9152 switch (selection) {
9153 case AP_VALUE:
9154 return val->has_single_expr();
9155 case AP_TEMPLATE:
9156 if (gen_restriction_check!=TR_NONE ||
9157 gen_post_restriction_check!=TR_NONE) return false;
9158 return temp->has_single_expr();
9159 case AP_REF:
9160 if (gen_restriction_check!=TR_NONE ||
9161 gen_post_restriction_check!=TR_NONE) return false;
af710487 9162 if (use_runtime_2 && ref->get_subrefs() != NULL) {
970ed795
EL
9163 FieldOrArrayRefs* subrefs = ref->get_subrefs();
9164 for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
9165 if (FieldOrArrayRef::ARRAY_REF == subrefs->get_ref(i)->get_type()) {
9166 return false;
9167 }
9168 }
9169 }
9170 return ref->has_single_expr();
9171 case AP_DEFAULT:
9172 return true;
9173 default:
9174 FATAL_ERROR("ActualPar::has_single_expr()");
9175 return false;
9176 }
9177 }
9178
9179 void ActualPar::set_code_section(
9180 GovernedSimple::code_section_t p_code_section)
9181 {
9182 switch (selection) {
9183 case AP_VALUE:
9184 val->set_code_section(p_code_section);
9185 break;
9186 case AP_TEMPLATE:
9187 temp->set_code_section(p_code_section);
9188 break;
9189 case AP_REF:
9190 ref->set_code_section(p_code_section);
9191 default:
9192 break;
9193 }
9194 }
9195
9196 void ActualPar::generate_code(expression_struct *expr, bool copy_needed, bool lazy_param, bool used_as_lvalue) const
9197 {
9198 switch (selection) {
9199 case AP_VALUE:
9200 if (lazy_param) { // copy_needed doesn't matter in this case
9201 LazyParamData::init(used_as_lvalue);
9202 LazyParamData::generate_code(expr, val, my_scope);
9203 LazyParamData::clean();
9204 } else {
9205 if (copy_needed) expr->expr = mputprintf(expr->expr, "%s(",
9206 val->get_my_governor()->get_genname_value(my_scope).c_str());
9207 if (use_runtime_2 && TypeConv::needs_conv_refd(val)) {
9208 // Generate everything to preamble to be able to tackle the wrapper
9209 // constructor call. TODO: Reduce the number of temporaries created.
9210 const string& tmp_id = val->get_temporary_id();
9211 const char *tmp_id_str = tmp_id.c_str();
9212 expr->preamble = mputprintf(expr->preamble, "%s %s;\n",
9213 val->get_my_governor()->get_genname_value(my_scope).c_str(),
9214 tmp_id_str);
9215 expr->preamble = TypeConv::gen_conv_code_refd(expr->preamble,
9216 tmp_id_str, val);
9217 expr->expr = mputstr(expr->expr, tmp_id_str);
9218 } else val->generate_code_expr(expr);
9219 if (copy_needed) expr->expr = mputc(expr->expr, ')');
9220 }
9221 break;
9222 case AP_TEMPLATE:
9223 if (lazy_param) { // copy_needed doesn't matter in this case
9224 LazyParamData::init(used_as_lvalue);
9225 LazyParamData::generate_code(expr, temp, gen_restriction_check, my_scope);
9226 LazyParamData::clean();
9227 } else {
9228 if (copy_needed)
9229 expr->expr = mputprintf(expr->expr, "%s(", temp->get_Template()
9230 ->get_my_governor()->get_genname_template(my_scope).c_str());
9231 if (use_runtime_2 && TypeConv::needs_conv_refd(temp->get_Template())) {
9232 const string& tmp_id = temp->get_Template()->get_temporary_id();
9233 const char *tmp_id_str = tmp_id.c_str();
9234 expr->preamble = mputprintf(expr->preamble, "%s %s;\n",
9235 temp->get_Template()->get_my_governor()
9236 ->get_genname_template(my_scope).c_str(), tmp_id_str);
9237 expr->preamble = TypeConv::gen_conv_code_refd(expr->preamble,
9238 tmp_id_str, temp->get_Template());
9239 // Not incorporated into gen_conv_code() yet.
9240 if (gen_restriction_check != TR_NONE)
9241 expr->preamble = Template::generate_restriction_check_code(
9242 expr->preamble, tmp_id_str, gen_restriction_check);
9243 expr->expr = mputstr(expr->expr, tmp_id_str);
9244 } else temp->generate_code(expr, gen_restriction_check);
9245 if (copy_needed) expr->expr = mputc(expr->expr, ')');
9246 }
9247 break;
9248 case AP_REF:
9249 if (lazy_param) FATAL_ERROR("ActualPar::generate_code()"); // syntax error should have already happened
9250 if (copy_needed) FATAL_ERROR("ActualPar::generate_code()");
9251 if (gen_restriction_check != TR_NONE ||
9252 gen_post_restriction_check != TR_NONE) {
9253 // generate runtime check for restricted templates
9254 // code for reference + restriction check
9255 Common::Assignment *ass = ref->get_refd_assignment();
9256 const string& tmp_id= my_scope->get_scope_mod_gen()->get_temporary_id();
9257 const char *tmp_id_str = tmp_id.c_str();
9258 expression_struct ref_expr;
9259 Code::init_expr(&ref_expr);
9260 ref->generate_code_const_ref(&ref_expr);
9261 ref_expr.preamble = mputprintf(ref_expr.preamble, "%s& %s = %s;\n",
9262 ass->get_Type()->get_genname_template(ref->get_my_scope()).c_str(),
9263 tmp_id_str, ref_expr.expr);
9264 if (gen_restriction_check != TR_NONE) {
9265 ref_expr.preamble = Template::generate_restriction_check_code(
9266 ref_expr.preamble, tmp_id_str, gen_restriction_check);
9267 }
9268 if (gen_post_restriction_check != TR_NONE) {
9269 ref_expr.postamble = Template::generate_restriction_check_code(
9270 ref_expr.postamble, tmp_id_str, gen_post_restriction_check);
9271 }
9272 // copy content of ref_expr to expr
9273 expr->preamble = mputstr(expr->preamble, ref_expr.preamble);
9274 expr->expr = mputprintf(expr->expr, "%s", tmp_id_str);
9275 expr->postamble = mputstr(expr->postamble, ref_expr.postamble);
9276 Code::free_expr(&ref_expr);
9277 } else {
9278 ref->generate_code(expr);
9279 }
9280 break;
9281 case AP_DEFAULT:
9282 if (copy_needed) FATAL_ERROR("ActualPar::generate_code()");
9283 switch (act->selection) {
9284 case AP_REF:
9285 if (lazy_param) {
9286 LazyParamData::generate_code_ap_default_ref(expr, act->ref, my_scope);
9287 } else {
9288 act->ref->generate_code(expr);
9289 }
9290 break;
9291 case AP_VALUE:
9292 if (lazy_param) {
9293 LazyParamData::generate_code_ap_default_value(expr, act->val, my_scope);
9294 } else {
9295 expr->expr = mputstr(expr->expr, act->val->get_genname_own(my_scope).c_str());
9296 }
9297 break;
9298 case AP_TEMPLATE:
9299 if (lazy_param) {
9300 LazyParamData::generate_code_ap_default_ti(expr, act->temp, my_scope);
9301 } else {
9302 expr->expr = mputstr(expr->expr, act->temp->get_Template()->get_genname_own(my_scope).c_str());
9303 }
9304 break;
9305 default:
9306 FATAL_ERROR("ActualPar::generate_code()");
9307 }
9308 break;
9309 default:
9310 FATAL_ERROR("ActualPar::generate_code()");
9311 }
9312 }
9313
51fa56b9 9314 char *ActualPar::rearrange_init_code(char *str, Common::Module* usage_mod)
970ed795
EL
9315 {
9316 switch (selection) {
9317 case AP_VALUE:
9318 str = val->rearrange_init_code(str);
9319 break;
9320 case AP_TEMPLATE:
51fa56b9 9321 str = temp->rearrange_init_code(str, usage_mod);
970ed795
EL
9322 case AP_REF:
9323 break;
9324 case AP_DEFAULT:
51fa56b9 9325 str = act->rearrange_init_code_defval(str, usage_mod);
970ed795
EL
9326 break;
9327 default:
9328 FATAL_ERROR("ActualPar::rearrange_init_code()");
9329 }
9330 return str;
9331 }
9332
51fa56b9 9333 char *ActualPar::rearrange_init_code_defval(char *str, Common::Module* usage_mod)
970ed795
EL
9334 {
9335 switch (selection) {
9336 case AP_VALUE:
51fa56b9 9337 if (val->get_my_scope()->get_scope_mod_gen() == usage_mod) {
9338 str = val->generate_code_init(str, val->get_lhs_name().c_str());
9339 }
970ed795
EL
9340 break;
9341 case AP_TEMPLATE: {
51fa56b9 9342 str = temp->rearrange_init_code(str, usage_mod);
970ed795 9343 Template *t = temp->get_Template();
51fa56b9 9344 if (t->get_my_scope()->get_scope_mod_gen() == usage_mod) {
9345 Ref_base *dref = temp->get_DerivedRef();
9346 if (dref) {
9347 expression_struct expr;
9348 Code::init_expr(&expr);
9349 expr.expr = mputprintf(expr.expr, "%s = ", t->get_lhs_name().c_str());
9350 dref->generate_code(&expr);
9351 str = Code::merge_free_expr(str, &expr, false);
9352 }
9353 str = t->generate_code_init(str, t->get_lhs_name().c_str());
970ed795 9354 }
970ed795
EL
9355 break; }
9356 default:
9357 FATAL_ERROR("ActualPar::rearrange_init_code_defval()");
9358 }
9359 return str;
9360 }
9361
9362 void ActualPar::append_stringRepr(string& str) const
9363 {
9364 switch (selection) {
9365 case AP_VALUE:
9366 str += val->get_stringRepr();
9367 break;
9368 case AP_TEMPLATE:
9369 temp->append_stringRepr(str);
9370 break;
9371 case AP_REF:
9372 str += ref->get_dispname();
9373 break;
9374 case AP_DEFAULT:
9375 str += '-';
9376 break;
9377 default:
9378 str += "<erroneous actual parameter>";
9379 }
9380 }
9381
9382 void ActualPar::dump(unsigned level) const
9383 {
9384 switch (selection) {
9385 case AP_VALUE:
9386 DEBUG(level, "actual parameter: value");
9387 val->dump(level + 1);
9388 break;
9389 case AP_TEMPLATE:
9390 DEBUG(level, "actual parameter: template");
9391 temp->dump(level + 1);
9392 break;
9393 case AP_REF:
9394 DEBUG(level, "actual parameter: referecne");
9395 ref->dump(level + 1);
9396 break;
9397 case AP_DEFAULT:
9398 DEBUG(level, "actual parameter: default");
9399 break;
9400 default:
9401 DEBUG(level, "actual parameter: erroneous");
9402 }
9403 }
9404
9405 // =================================
9406 // ===== ActualParList
9407 // =================================
9408
9409 ActualParList::ActualParList(const ActualParList& p)
9410 : Node(p)
9411 {
9412 size_t nof_pars = p.params.size();
9413 for (size_t i = 0; i < nof_pars; i++) params.add(p.params[i]->clone());
9414 }
9415
9416 ActualParList::~ActualParList()
9417 {
9418 size_t nof_pars = params.size();
9419 for (size_t i = 0; i < nof_pars; i++) delete params[i];
9420 params.clear();
9421 }
9422
9423 ActualParList *ActualParList::clone() const
9424 {
9425 return new ActualParList(*this);
9426 }
9427
9428 void ActualParList::set_fullname(const string& p_fullname)
9429 {
9430 Node::set_fullname(p_fullname);
9431 size_t nof_pars = params.size();
9432 for(size_t i = 0; i < nof_pars; i++)
9433 params[i]->set_fullname(p_fullname +
a38c6d4c 9434 ".<parameter" + Int2string(i + 1) + ">");
970ed795
EL
9435 }
9436
9437 void ActualParList::set_my_scope(Scope *p_scope)
9438 {
9439 size_t nof_pars = params.size();
9440 for (size_t i = 0; i < nof_pars; i++) params[i]->set_my_scope(p_scope);
9441 }
9442
9443 void ActualParList::chk_recursions(ReferenceChain& refch)
9444 {
9445 size_t nof_pars = params.size();
9446 for (size_t i = 0; i < nof_pars; i++)
9447 params[i]->chk_recursions(refch);
9448 }
9449
9450 void ActualParList::generate_code_noalias(expression_struct *expr, FormalParList *p_fpl)
9451 {
9452 size_t nof_pars = params.size();
9453 for (size_t i = 0; i < nof_pars; i++) {
9454 if (i > 0) expr->expr = mputstr(expr->expr, ", ");
9455 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());
9456 }
9457 }
9458
9459 void ActualParList::generate_code_alias(expression_struct *expr,
9460 FormalParList *p_fpl, Type *p_comptype, bool p_compself)
9461 {
9462 size_t nof_pars = params.size();
9463 // collect all value and template definitions that are passed by reference
9464 map<Common::Assignment*, void> value_refs, template_refs;
9465 for (size_t i = 0; i < nof_pars; i++) {
9466 ActualPar *par = params[i];
9467 if (par->get_selection() == ActualPar::AP_DEFAULT)
a38c6d4c 9468 par = par->get_ActualPar();
970ed795 9469 if (par->get_selection() == ActualPar::AP_REF) {
a38c6d4c 9470 Common::Assignment *ass = par->get_Ref()->get_refd_assignment();
9471 switch (ass->get_asstype()) {
9472 case Common::Assignment::A_VAR:
9473 case Common::Assignment::A_PAR_VAL_IN:
9474 case Common::Assignment::A_PAR_VAL_OUT:
9475 case Common::Assignment::A_PAR_VAL_INOUT:
9476 if (!value_refs.has_key(ass)) value_refs.add(ass, 0);
9477 break;
9478 case Common::Assignment::A_VAR_TEMPLATE:
9479 case Common::Assignment::A_PAR_TEMPL_IN:
9480 case Common::Assignment::A_PAR_TEMPL_OUT:
9481 case Common::Assignment::A_PAR_TEMPL_INOUT:
9482 if (!template_refs.has_key(ass)) template_refs.add(ass, 0);
9483 default:
9484 break;
9485 }
970ed795
EL
9486 }
9487 }
9488 // walk through the parameter list and generate the code
9489 // add an extra copy constructor call to the referenced value and template
9490 // parameters if the referred definition is also passed by reference to
9491 // another parameter
9492 for (size_t i = 0; i < nof_pars; i++) {
9493 if (i > 0) expr->expr = mputstr(expr->expr, ", ");
9494 ActualPar *par = params[i];
9495 bool copy_needed = false;
9496 // the copy constructor call is not needed if the parameter is copied
9497 // into a shadow object in the body of the called function
9498 if (!p_fpl || !p_fpl->get_fp_byIndex(i)->get_used_as_lvalue()) {
a38c6d4c 9499 switch (par->get_selection()) {
9500 case ActualPar::AP_VALUE: {
9501 Value *v = par->get_Value();
9502 if (v->get_valuetype() == Value::V_REFD) {
9503 Common::Assignment *t_ass =
9504 v->get_reference()->get_refd_assignment();
9505 if (value_refs.has_key(t_ass)) {
9506 // a reference to the same variable is also passed to the called
9507 // definition
9508 copy_needed = true;
9509 } else if (p_comptype || p_compself) {
9510 // the called definition has a 'runs on' clause so it can access
9511 // component variables
9512 switch (t_ass->get_asstype()) {
9513 case Common::Assignment::A_PAR_VAL_OUT:
9514 case Common::Assignment::A_PAR_VAL_INOUT:
9515 // the parameter may be an alias of a component variable
9516 copy_needed = true;
9517 break;
9518 case Common::Assignment::A_VAR:
9519 // copy is needed if t_ass is a component variable that is
9520 // visible by the called definition
9521 if (!t_ass->is_local()) copy_needed = true;
9522 /** \todo component type compatibility: check whether t_ass is
9523 * visible from p_comptype (otherwise copy is not needed) */
9524 default:
9525 break;
9526 }
9527 }
9528 }
9529 break; }
9530 case ActualPar::AP_TEMPLATE: {
9531 TemplateInstance *ti = par->get_TemplateInstance();
9532 if (!ti->get_DerivedRef()) {
9533 Template *t = ti->get_Template();
9534 if (t->get_templatetype() == Template::TEMPLATE_REFD) {
9535 Common::Assignment *t_ass =
9536 t->get_reference()->get_refd_assignment();
9537 if (template_refs.has_key(t_ass)) {
9538 // a reference to the same variable is also passed to the called
9539 // definition
9540 copy_needed = true;
9541 } else if (p_comptype || p_compself) {
9542 // the called definition has a 'runs on' clause so it can access
9543 // component variables
9544 switch (t_ass->get_asstype()) {
9545 case Common::Assignment::A_PAR_TEMPL_OUT:
9546 case Common::Assignment::A_PAR_TEMPL_INOUT:
9547 // the parameter may be an alias of a component variable
9548 copy_needed = true;
9549 break;
9550 case Common::Assignment::A_VAR_TEMPLATE:
9551 // copy is needed if t_ass is a component variable that is
9552 // visible by the called definition
9553 if (!t_ass->is_local()) copy_needed = true;
9554 /** \todo component type compatibility: check whether t_ass is
9555 * visible from p_comptype (otherwise copy is not needed) */
9556 default:
9557 break;
9558 }
9559 }
9560 }
9561 } }
9562 default:
9563 break;
9564 }
970ed795
EL
9565 }
9566
af710487 9567 if (use_runtime_2 && ActualPar::AP_REF == par->get_selection()) {
970ed795
EL
9568 // if the parameter references an element of a record of/set of, then
9569 // the record of object needs to know, so it doesn't delete the referenced
9570 // element
9571 Ref_base* ref = par->get_Ref();
9572 FieldOrArrayRefs* subrefs = ref->get_subrefs();
9573 if (subrefs != NULL) {
9574 Common::Assignment* ass = ref->get_refd_assignment();
9575 size_t ref_i;
9576 for (ref_i = 0; ref_i < subrefs->get_nof_refs(); ++ref_i) {
9577 FieldOrArrayRef* subref = subrefs->get_ref(ref_i);
9578 if (FieldOrArrayRef::ARRAY_REF == subref->get_type()) {
9579 // set the referenced index in each array in the subrefs
9580 expression_struct array_expr;
9581 Code::init_expr(&array_expr);
9582 // the array object's name contains the reference, followed by
9583 // the subrefs before the current array ref
9584 array_expr.expr = mcopystr(LazyParamData::in_lazy() ?
9585 LazyParamData::add_ref_genname(ass, ref->get_my_scope()).c_str() :
9586 ass->get_genname_from_scope(ref->get_my_scope()).c_str());
9587 if (ref_i > 0) {
9588 subrefs->generate_code(&array_expr, ass, ref_i);
9589 }
9590 expression_struct index_expr;
9591 Code::init_expr(&index_expr);
9592 subrefs->get_ref(ref_i)->get_val()->generate_code_expr(&index_expr);
9593 // insert any preambles the array object or the index might have
9594 if (array_expr.preamble != NULL) {
9595 expr->preamble = mputstr(expr->preamble, array_expr.preamble);
9596 expr->postamble = mputstr(expr->postamble, array_expr.preamble);
9597 }
9598 if (index_expr.preamble != NULL) {
9599 expr->preamble = mputstr(expr->preamble, index_expr.preamble);
9600 expr->postamble = mputstr(expr->postamble, index_expr.preamble);
9601 }
9602 // let the array object know that the index is referenced before
9603 // calling the function, and let it know that it's now longer
a38c6d4c 9604 // referenced after the function call (this is done with the help
9605 // of the RefdIndexHandler's constructor and destructor)
9606 string tmp_id = ref->get_my_scope()->get_scope_mod_gen()->get_temporary_id();
af710487 9607 expr->preamble = mputprintf(expr->preamble,
a38c6d4c 9608 "RefdIndexHandler %s(&%s, %s);\n",
9609 tmp_id.c_str(), array_expr.expr, index_expr.expr);
970ed795
EL
9610 // insert any postambles the array object or the index might have
9611 if (array_expr.postamble != NULL) {
9612 expr->preamble = mputstr(expr->preamble, array_expr.postamble);
9613 expr->postamble = mputstr(expr->postamble, array_expr.postamble);
9614 }
9615 if (index_expr.postamble != NULL) {
9616 expr->preamble = mputstr(expr->preamble, index_expr.postamble);
9617 expr->postamble = mputstr(expr->postamble, index_expr.postamble);
9618 }
9619 Code::free_expr(&array_expr);
9620 Code::free_expr(&index_expr);
9621 } // if (FieldOrArrayRef::ARRAY_REF == subref->get_type())
9622 } // for cycle
9623 } // if (subrefs != NULL)
9624 } // if (ActualPar::AP_REF == par->get_selection())
9625
9626 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());
9627 }
9628 value_refs.clear();
9629 template_refs.clear();
9630 }
9631
51fa56b9 9632 char *ActualParList::rearrange_init_code(char *str, Common::Module* usage_mod)
970ed795
EL
9633 {
9634 for (size_t i = 0; i < params.size(); i++)
51fa56b9 9635 str = params[i]->rearrange_init_code(str, usage_mod);
970ed795
EL
9636 return str;
9637 }
9638
9639 void ActualParList::dump(unsigned level) const
9640 {
9641 DEBUG(level, "actual parameter list: %lu parameters",
9642 (unsigned long) params.size());
9643 for (size_t i = 0; i < params.size(); i++)
9644 params[i]->dump(level + 1);
9645 }
9646}
This page took 0.405917 seconds and 5 git commands to generate.