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