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