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