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