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