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