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