function_test/Semantic_Analyser/xer/aa_optional_SE.ttcn removed
[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
af710487 2710 void Module::generate_json_schema(JSON_Tokenizer& json, map<Type*, JSON_Tokenizer>& json_refs)
970ed795
EL
2711 {
2712 // add a new property for this module
af710487 2713 json.put_next_token(JSON_TOKEN_NAME, modid->get_ttcnname().c_str());
970ed795
EL
2714
2715 // add type definitions into an object
2716 json.put_next_token(JSON_TOKEN_OBJECT_START);
2717
af710487 2718 // cycle through each type, generate schema segment and reference when needed
970ed795
EL
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) {
af710487 2722 Type* t = def->get_Type();
2723 if (t->has_encoding(Type::CT_JSON)) {
2724 // insert type's schema segment
2725 t->generate_json_schema(json, false, false);
2726
2727 if (json_refs_for_all_types && !json_refs.has_key(t)) {
2728 // create JSON schema reference for the type
2729 JSON_Tokenizer* json_ref = new JSON_Tokenizer;
2730 json_refs.add(t, json_ref);
2731 t->generate_json_schema_ref(*json_ref);
2732 }
2733 }
970ed795
EL
2734 }
2735 }
2736
2737 // end of type definitions
2738 json.put_next_token(JSON_TOKEN_OBJECT_END);
af710487 2739
2740 // insert function data
970ed795
EL
2741 for (size_t i = 0; i < asss->get_nof_asss(); ++i) {
2742 Def_ExtFunction* def = dynamic_cast<Def_ExtFunction*>(asss->get_ass_byIndex(i));
2743 if (def != NULL) {
2744 def->generate_json_schema_ref(json_refs);
2745 }
2746 }
2747 }
2748
2749 // =================================
2750 // ===== Definition
2751 // =================================
2752
2753 string Definition::get_genname() const
2754 {
2755 if (!genname.empty()) return genname;
2756 else return id->get_name();
2757 }
2758
2759 namedbool Definition::has_implicit_omit_attr() const {
2760 if (w_attrib_path) {
2761 const vector<SingleWithAttrib>& real_attribs =
2762 w_attrib_path->get_real_attrib();
2763 for (size_t in = real_attribs.size(); in > 0; in--) {
2764 if (SingleWithAttrib::AT_OPTIONAL ==
2765 real_attribs[in-1]->get_attribKeyword()) {
2766 if ("implicit omit" ==
2767 real_attribs[in-1]->get_attribSpec().get_spec()) {
2768 return IMPLICIT_OMIT;
2769 } else if ("explicit omit" ==
2770 real_attribs[in-1]->get_attribSpec().get_spec()) {
2771 return NOT_IMPLICIT_OMIT;
2772 } // error reporting for other values is in chk_global_attrib
2773 }
2774 }
2775 }
2776 return NOT_IMPLICIT_OMIT;
2777 }
2778
2779 Definition::~Definition()
2780 {
2781 delete w_attrib_path;
2782 delete erroneous_attrs;
2783 }
2784
2785 void Definition::set_fullname(const string& p_fullname)
2786 {
2787 Common::Assignment::set_fullname(p_fullname);
2788 if (w_attrib_path) w_attrib_path->set_fullname(p_fullname + ".<attribpath>");
2789 if (erroneous_attrs) erroneous_attrs->set_fullname(p_fullname+".<erroneous_attributes>");
2790 }
2791
2792 bool Definition::is_local() const
2793 {
2794 if (!my_scope) FATAL_ERROR("Definition::is_local()");
2795 for (Scope *scope = my_scope; scope; scope = scope->get_parent_scope()) {
2796 if (dynamic_cast<StatementBlock*>(scope)) return true;
2797 }
2798 return false;
2799 }
2800
2801 bool Definition::chk_identical(Definition *)
2802 {
2803 FATAL_ERROR("Definition::chk_identical()");
2804 return false;
2805 }
2806
2807 void Definition::chk_erroneous_attr()
2808 {
2809 if (!w_attrib_path) return;
2810 const Ttcn::MultiWithAttrib* attribs = w_attrib_path->get_local_attrib();
2811 if (!attribs) return;
2812 for (size_t i = 0; i < attribs->get_nof_elements(); i++) {
2813 const Ttcn::SingleWithAttrib* act_attr = attribs->get_element(i);
2814 if (act_attr->get_attribKeyword()==Ttcn::SingleWithAttrib::AT_ERRONEOUS) {
2815 if (!use_runtime_2) {
2816 error("`erroneous' attributes can be used only with the Function Test Runtime");
2817 note("If you need negative testing use the -R flag when generating the makefile");
2818 return;
2819 }
2820 size_t nof_qualifiers = act_attr->get_attribQualifiers() ? act_attr->get_attribQualifiers()->get_nof_qualifiers() : 0;
2821 dynamic_array<Type*> refd_type_array(nof_qualifiers); // only the qualifiers pointing to existing fields will be added to erroneous_attrs objects
2822 if (nof_qualifiers==0) {
2823 act_attr->error("At least one qualifier must be specified for the `erroneous' attribute");
2824 } else {
2825 // check if qualifiers point to existing fields
2826 for (size_t qi=0; qi<nof_qualifiers; qi++) {
2827 Qualifier* act_qual = const_cast<Qualifier*>(act_attr->get_attribQualifiers()->get_qualifier(qi));
2828 act_qual->set_my_scope(get_my_scope());
2829 Type* field_type = get_Type()->get_field_type(act_qual, Type::EXPECTED_CONSTANT);
2830 if (field_type) {
2831 dynamic_array<size_t> subrefs_array;
2832 dynamic_array<Type*> type_array;
2833 bool valid_indexes = get_Type()->get_subrefs_as_array(act_qual, subrefs_array, type_array);
2834 if (!valid_indexes) field_type = NULL;
2835 if (act_qual->refers_to_string_element()) {
2836 act_qual->error("Reference to a string element cannot be used in this context");
2837 field_type = NULL;
2838 }
2839 }
2840 refd_type_array.add(field_type);
2841 }
2842 }
2843 // parse the attr. spec.
2844 ErroneousAttributeSpec* err_attr_spec = ttcn3_parse_erroneous_attr_spec_string(
2845 act_attr->get_attribSpec().get_spec().c_str(), act_attr->get_attribSpec());
2846 if (err_attr_spec) {
2847 if (!erroneous_attrs) erroneous_attrs = new ErroneousAttributes(get_Type());
2848 // attr.spec will be owned by erroneous_attrs object
2849 erroneous_attrs->add_spec(err_attr_spec);
2850 err_attr_spec->set_fullname(get_fullname());
2851 err_attr_spec->set_my_scope(get_my_scope());
2852 err_attr_spec->chk();
2853 // create qualifier - err.attr.spec. pairs
2854 for (size_t qi=0; qi<nof_qualifiers; qi++) {
2855 if (refd_type_array[qi] && (err_attr_spec->get_indicator()!=ErroneousAttributeSpec::I_INVALID)) {
2856 erroneous_attrs->add_pair(act_attr->get_attribQualifiers()->get_qualifier(qi), err_attr_spec);
2857 }
2858 }
2859 }
2860 }
2861 }
2862 if (erroneous_attrs) erroneous_attrs->chk();
2863 }
2864
2865 char* Definition::generate_code_str(char *str)
2866 {
2867 FATAL_ERROR("Definition::generate_code_str()");
2868 return str;
2869 }
2870
2871 void Definition::ilt_generate_code(ILT *)
2872 {
2873 FATAL_ERROR("Definition::ilt_generate_code()");
2874 }
2875
2876 char *Definition::generate_code_init_comp(char *str, Definition *)
2877 {
2878 FATAL_ERROR("Definition::generate_code_init_comp()");
2879 return str;
2880 }
2881
2882 void Definition::set_with_attr(MultiWithAttrib* p_attrib)
2883 {
2884 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2885 w_attrib_path->set_with_attr(p_attrib);
2886 }
2887
2888 WithAttribPath* Definition::get_attrib_path()
2889 {
2890 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2891 return w_attrib_path;
2892 }
2893
2894 void Definition::set_parent_path(WithAttribPath* p_path)
2895 {
2896 if (!w_attrib_path) w_attrib_path = new WithAttribPath();
2897 w_attrib_path->set_parent(p_path);
2898 }
2899
2900 void Definition::set_parent_group(Group* p_group)
2901 {
2902 if(parentgroup) // there would be a leak!
2903 FATAL_ERROR("Definition::set_parent_group()");
2904 parentgroup = p_group;
2905 }
2906
2907 Group* Definition::get_parent_group()
2908 {
2909 return parentgroup;
2910 }
2911
2912 void Definition::dump_internal(unsigned level) const
2913 {
2914 DEBUG(level, "Move along, nothing to see here");
2915 }
2916
2917 void Definition::dump(unsigned level) const
2918 {
2919 dump_internal(level);
2920 if (w_attrib_path) {
2921 MultiWithAttrib *attrib = w_attrib_path->get_with_attr();
2922 if (attrib) {
2923 DEBUG(level + 1, "Definition Attributes:");
2924 attrib->dump(level + 2);
2925 }
2926 }
2927 if (erroneous_attrs) erroneous_attrs->dump(level+1);
2928 }
2929
2930 // =================================
2931 // ===== Def_Type
2932 // =================================
2933
2934 Def_Type::Def_Type(Identifier *p_id, Type *p_type)
2935 : Definition(A_TYPE, p_id), type(p_type)
2936 {
2937 if(!p_type) FATAL_ERROR("Ttcn::Def_Type::Def_Type()");
2938 type->set_ownertype(Type::OT_TYPE_DEF, this);
2939 }
2940
2941 Def_Type::~Def_Type()
2942 {
2943 delete type;
2944 }
2945
2946 Def_Type *Def_Type::clone() const
2947 {
2948 FATAL_ERROR("Def_Type::clone");
2949 }
2950
2951 void Def_Type::set_fullname(const string& p_fullname)
2952 {
2953 Definition::set_fullname(p_fullname);
2954 type->set_fullname(p_fullname);
2955 }
2956
2957 void Def_Type::set_my_scope(Scope *p_scope)
2958 {
2959 bridgeScope.set_parent_scope(p_scope);
2960 bridgeScope.set_scopeMacro_name(id->get_dispname());
2961
2962 Definition::set_my_scope(&bridgeScope);
2963 type->set_my_scope(&bridgeScope);
2964
2965 }
2966
2967 Setting *Def_Type::get_Setting()
2968 {
2969 return get_Type();
2970 }
2971
2972 Type *Def_Type::get_Type()
2973 {
2974 chk();
2975 return type;
2976 }
2977
2978 void Def_Type::chk()
2979 {
2980 if (checked) return;
2981 checked = true;
2982 Error_Context cntxt(this, "In %s definition `%s'",
2983 type->get_typetype() == Type::T_SIGNATURE ? "signature" : "type",
2984 id->get_dispname().c_str());
2985 type->set_genname(get_genname());
2986 if (!semantic_check_only && type->get_typetype() == Type::T_COMPONENT) {
2987 // the prefix of embedded definitions must be set before the checking
2988 type->get_CompBody()->set_genname(get_genname() + "_component_");
2989 }
2990
2991 while (w_attrib_path) { // not a loop, but we can _break_ out of it
2992 w_attrib_path->chk_global_attrib();
2993 w_attrib_path->chk_no_qualif();
2994 if (type->get_typetype() != Type::T_ANYTYPE) break;
2995 // This is the anytype; it must be empty (we're about to add the fields)
2996 if (type->get_nof_comps() > 0) FATAL_ERROR("Def_Type::chk");
2997
2998 Ttcn::ExtensionAttributes *extattrs = parse_extattributes(w_attrib_path);
2999 if (extattrs == 0) break; // NULL means parsing error
3000
3001 size_t num_atrs = extattrs->size();
3002 for (size_t k = 0; k < num_atrs; ++k) {
3003 ExtensionAttribute &ea = extattrs->get(k);
3004 switch (ea.get_type()) {
3005 case ExtensionAttribute::ANYTYPELIST: {
3006 Types *anytypes = ea.get_types();
3007 // List of types to be converted into fields for the anytype.
3008 // Make sure scope is set on all types in the list.
3009 anytypes->set_my_scope(get_my_scope());
3010
3011 // Convert the list of types into field names for the anytype
3012 for (size_t i=0; i < anytypes->get_nof_types(); ++i) {
3013 Type *t = anytypes->extract_type_byIndex(i);
3014 // we are now the owner of the Type.
3015 if (t->get_typetype()==Type::T_ERROR) { // should we give up?
3016 delete t;
3017 continue;
3018 }
3019
3020 string field_name;
3021 const char* btn = Type::get_typename_builtin(t->get_typetype());
3022 if (btn) {
3023 field_name = btn;
3024 }
3025 else if (t->get_typetype() == Type::T_REFD) {
3026 // Extract the identifier
3027 Common::Reference *ref = t->get_Reference();
3028 Ttcn::Reference *tref = dynamic_cast<Ttcn::Reference*>(ref);
3029 if (!tref) FATAL_ERROR("Def_Type::chk, wrong kind of reference");
3030 const Common::Identifier *modid = tref->get_modid();
3031 if (modid) {
3032 ea.error("Qualified name '%s' cannot be added to the anytype",
3033 tref->get_dispname().c_str());
3034 delete t;
3035 continue;
3036 }
3037 field_name = tref->get_id()->get_ttcnname();
3038 }
3039 else {
3040 // Can't happen here
3041 FATAL_ERROR("Unexpected type %d", t->get_typetype());
3042 }
3043
3044 const string& at_field = anytype_field(field_name);
3045 Identifier *field_id = new Identifier(Identifier::ID_TTCN, at_field);
3046 CompField *cf = new CompField(field_id, t, false, 0);
3047 cf->set_location(ea);
3048 cf->set_fullname(get_fullname());
3049 type->add_comp(cf);
3050 } // next i
3051 delete anytypes;
3052 break; }
3053 default:
3054 w_attrib_path->get_with_attr()->error("Type def can only have anytype");
3055 break;
3056 } // switch
3057 } // next attribute
3058
3059 delete extattrs;
3060 break; // do not loop
3061 }
3062
3063 // Now we can check the type
3064 type->chk();
3065 type->chk_constructor_name(*id);
3066 if (id->get_ttcnname() == "address") type->chk_address();
3067 ReferenceChain refch(type, "While checking embedded recursions");
3068 type->chk_recursions(refch);
3069
3070 if (type->get_typetype()==Type::T_FUNCTION
3071 ||type->get_typetype()==Type::T_ALTSTEP
3072 ||type->get_typetype()==Type::T_TESTCASE) {
3073 // TR 922. This is a function/altstep/testcase reference.
3074 // Set this definition as the definition for the formal parameters.
3075 type->get_fat_parameters()->set_my_def(this);
3076 }
3077 }
3078
3079 void Def_Type::generate_code(output_struct *target, bool)
3080 {
3081 type->generate_code(target);
3082 if (type->get_typetype() == Type::T_COMPONENT) {
3083 // the C++ equivalents of embedded component element definitions must be
3084 // generated from outside Type::generate_code() because the function can
3085 // call itself recursively and create invalid (overlapped) initializer
3086 // sequences
3087 type->get_CompBody()->generate_code(target);
3088 }
3089 }
3090
3091 void Def_Type::generate_code(CodeGenHelper& cgh) {
3092 type->generate_code(cgh.get_outputstruct(get_Type()));
3093 if (type->get_typetype() == Type::T_COMPONENT) {
3094 // the C++ equivalents of embedded component element definitions must be
3095 // generated from outside Type::generate_code() because the function can
3096 // call itself recursively and create invalid (overlapped) initializer
3097 // sequences
3098 type->get_CompBody()->generate_code(cgh.get_current_outputstruct());
3099 }
3100 cgh.finalize_generation(get_Type());
3101 }
3102
3103
3104 void Def_Type::dump_internal(unsigned level) const
3105 {
3106 DEBUG(level, "Type def: %s @ %p", id->get_dispname().c_str(), (const void*)this);
3107 type->dump(level + 1);
3108 }
3109
3110 void Def_Type::set_with_attr(MultiWithAttrib* p_attrib)
3111 {
3112 if (!w_attrib_path) {
3113 w_attrib_path = new WithAttribPath();
3114 type->set_parent_path(w_attrib_path);
3115 }
3116 type->set_with_attr(p_attrib);
3117 }
3118
3119 WithAttribPath* Def_Type::get_attrib_path()
3120 {
3121 if (!w_attrib_path) {
3122 w_attrib_path = new WithAttribPath();
3123 type->set_parent_path(w_attrib_path);
3124 }
3125 return w_attrib_path;
3126 }
3127
3128 void Def_Type::set_parent_path(WithAttribPath* p_path)
3129 {
3130 if (!w_attrib_path) {
3131 w_attrib_path = new WithAttribPath();
3132 type->set_parent_path(w_attrib_path);
3133 }
3134 w_attrib_path->set_parent(p_path);
3135 }
970ed795
EL
3136
3137 // =================================
3138 // ===== Def_Const
3139 // =================================
3140
3141 Def_Const::Def_Const(Identifier *p_id, Type *p_type, Value *p_value)
3142 : Definition(A_CONST, p_id)
3143 {
3144 if (!p_type || !p_value) FATAL_ERROR("Ttcn::Def_Const::Def_Const()");
3145 type=p_type;
3146 type->set_ownertype(Type::OT_CONST_DEF, this);
3147 value=p_value;
3148 value_under_check=false;
3149 }
3150
3151 Def_Const::~Def_Const()
3152 {
3153 delete type;
3154 delete value;
3155 }
3156
3157 Def_Const *Def_Const::clone() const
3158 {
3159 FATAL_ERROR("Def_Const::clone");
3160 }
3161
3162 void Def_Const::set_fullname(const string& p_fullname)
3163 {
3164 Definition::set_fullname(p_fullname);
3165 type->set_fullname(p_fullname + ".<type>");
3166 value->set_fullname(p_fullname);
3167 }
3168
3169 void Def_Const::set_my_scope(Scope *p_scope)
3170 {
3171 Definition::set_my_scope(p_scope);
3172 type->set_my_scope(p_scope);
3173 value->set_my_scope(p_scope);
3174 }
3175
3176 Setting *Def_Const::get_Setting()
3177 {
3178 return get_Value();
3179 }
3180
3181 Type *Def_Const::get_Type()
3182 {
3183 chk();
3184 return type;
3185 }
3186
3187
3188 Value *Def_Const::get_Value()
3189 {
3190 chk();
3191 return value;
3192 }
3193
3194 void Def_Const::chk()
3195 {
3196 if(checked) {
3197 if (value_under_check) {
3198 error("Circular reference in constant definition `%s'",
3199 id->get_dispname().c_str());
3200 value_under_check = false; // only report the error once for this definition
3201 }
3202 return;
3203 }
3204 Error_Context cntxt(this, "In constant definition `%s'",
3205 id->get_dispname().c_str());
3206 type->set_genname(_T_, get_genname());
3207 type->chk();
3208 value->set_my_governor(type);
3209 type->chk_this_value_ref(value);
3210 checked=true;
3211 if (w_attrib_path) {
3212 w_attrib_path->chk_global_attrib(true);
3213 switch (type->get_type_refd_last()->get_typetype_ttcn3()) {
3214 case Type::T_SEQ_T:
3215 case Type::T_SET_T:
3216 case Type::T_CHOICE_T:
3217 // These types may have qualified attributes
3218 break;
3219 case Type::T_SEQOF: case Type::T_SETOF:
3220 break;
3221 default:
3222 w_attrib_path->chk_no_qualif();
3223 break;
3224 }
3225 }
3226 Type *t = type->get_type_refd_last();
3227 switch (t->get_typetype()) {
3228 case Type::T_PORT:
3229 error("Constant cannot be defined for port type `%s'",
3230 t->get_fullname().c_str());
3231 break;
3232 case Type::T_SIGNATURE:
3233 error("Constant cannot be defined for signature `%s'",
3234 t->get_fullname().c_str());
3235 break;
3236 default:
3237 value_under_check = true;
3238 type->chk_this_value(value, 0, Type::EXPECTED_CONSTANT, INCOMPLETE_ALLOWED,
3239 OMIT_NOT_ALLOWED, SUB_CHK, has_implicit_omit_attr());
3240 value_under_check = false;
3241 chk_erroneous_attr();
3242 if (erroneous_attrs) value->set_err_descr(erroneous_attrs->get_err_descr());
3243 {
3244 ReferenceChain refch(type, "While checking embedded recursions");
3245 value->chk_recursions(refch);
3246 }
3247 break;
3248 }
3249 if (!semantic_check_only) {
3250 value->set_genname_prefix("const_");
3251 value->set_genname_recursive(get_genname());
3252 value->set_code_section(GovernedSimple::CS_PRE_INIT);
3253 }
3254 }
3255
3256 bool Def_Const::chk_identical(Definition *p_def)
3257 {
3258 chk();
3259 p_def->chk();
3260 if (p_def->get_asstype() != A_CONST) {
3261 const char *dispname_str = id->get_dispname().c_str();
3262 error("Local definition `%s' is a constant, but the definition "
3263 "inherited from component type `%s' is a %s", dispname_str,
3264 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
3265 p_def->note("The inherited definition of `%s' is here", dispname_str);
3266 return false;
3267 }
3268 Def_Const *p_def_const = dynamic_cast<Def_Const*>(p_def);
3269 if (!p_def_const) FATAL_ERROR("Def_Const::chk_identical()");
3270 if (!type->is_identical(p_def_const->type)) {
3271 const char *dispname_str = id->get_dispname().c_str();
3272 type->error("Local constant `%s' has type `%s', but the constant "
3273 "inherited from component type `%s' has type `%s'", dispname_str,
3274 type->get_typename().c_str(),
3275 p_def_const->get_my_scope()->get_fullname().c_str(),
3276 p_def_const->type->get_typename().c_str());
3277 p_def_const->note("The inherited constant `%s' is here", dispname_str);
3278 return false;
3279 } else if (!(*value == *p_def_const->value)) {
3280 const char *dispname_str = id->get_dispname().c_str();
3281 value->error("Local constant `%s' and the constant inherited from "
3282 "component type `%s' have different values", dispname_str,
3283 p_def_const->get_my_scope()->get_fullname().c_str());
3284 p_def_const->note("The inherited constant `%s' is here", dispname_str);
3285 return false;
3286 } else return true;
3287 }
3288
3289 void Def_Const::generate_code(output_struct *target, bool)
3290 {
3291 type->generate_code(target);
3292 const_def cdef;
3293 Code::init_cdef(&cdef);
3294 type->generate_code_object(&cdef, value);
3295 cdef.init = update_location_object(cdef.init);
3296 cdef.init = value->generate_code_init(cdef.init,
3297 value->get_lhs_name().c_str());
3298 Code::merge_cdef(target, &cdef);
3299 Code::free_cdef(&cdef);
3300 }
3301
3302 void Def_Const::generate_code(Common::CodeGenHelper& cgh) {
3303 // constant definitions always go to its containing module
3304 generate_code(cgh.get_current_outputstruct());
3305 }
3306
3307 char *Def_Const::generate_code_str(char *str)
3308 {
3309 const string& t_genname = get_genname();
3310 const char *genname_str = t_genname.c_str();
3311 if (value->has_single_expr()) {
3312 // the value can be represented by a single C++ expression
3313 // the object is initialized by the constructor
3314 str = mputprintf(str, "%s %s(%s);\n",
3315 type->get_genname_value(my_scope).c_str(), genname_str,
3316 value->get_single_expr().c_str());
3317 } else {
3318 // use the default constructor
3319 str = mputprintf(str, "%s %s;\n",
3320 type->get_genname_value(my_scope).c_str(), genname_str);
3321 // the value is assigned using subsequent statements
3322 str = value->generate_code_init(str, genname_str);
3323 }
3324 return str;
3325 }
3326
3327 void Def_Const::ilt_generate_code(ILT *ilt)
3328 {
3329 const string& t_genname = get_genname();
3330 const char *genname_str = t_genname.c_str();
3331 char*& def=ilt->get_out_def();
3332 char*& init=ilt->get_out_branches();
3333 def = mputprintf(def, "%s %s;\n", type->get_genname_value(my_scope).c_str(),
3334 genname_str);
3335 init = value->generate_code_init(init, genname_str);
3336 }
3337
3338 char *Def_Const::generate_code_init_comp(char *str, Definition *)
3339 {
3340 /* This function actually does nothing as \a this and \a base_defn are
3341 * exactly the same. */
3342 return str;
3343 }
3344
3345 void Def_Const::dump_internal(unsigned level) const
3346 {
3347 DEBUG(level, "Constant: %s @%p", id->get_dispname().c_str(), (const void*)this);
3348 type->dump(level + 1);
3349 value->dump(level + 1);
3350 }
3351
3352 // =================================
3353 // ===== Def_ExtConst
3354 // =================================
3355
3356 Def_ExtConst::Def_ExtConst(Identifier *p_id, Type *p_type)
3357 : Definition(A_EXT_CONST, p_id)
3358 {
3359 if (!p_type) FATAL_ERROR("Ttcn::Def_ExtConst::Def_ExtConst()");
3360 type = p_type;
3361 type->set_ownertype(Type::OT_CONST_DEF, this);
3362 }
3363
3364 Def_ExtConst::~Def_ExtConst()
3365 {
3366 delete type;
3367 }
3368
3369 Def_ExtConst *Def_ExtConst::clone() const
3370 {
3371 FATAL_ERROR("Def_ExtConst::clone");
3372 }
3373
3374 void Def_ExtConst::set_fullname(const string& p_fullname)
3375 {
3376 Definition::set_fullname(p_fullname);
3377 type->set_fullname(p_fullname + ".<type>");
3378 }
3379
3380 void Def_ExtConst::set_my_scope(Scope *p_scope)
3381 {
3382 Definition::set_my_scope(p_scope);
3383 type->set_my_scope(p_scope);
3384 }
3385
3386 Type *Def_ExtConst::get_Type()
3387 {
3388 chk();
3389 return type;
3390 }
3391
3392 void Def_ExtConst::chk()
3393 {
3394 if(checked) return;
3395 Error_Context cntxt(this, "In external constant definition `%s'",
3396 id->get_dispname().c_str());
3397 type->set_genname(_T_, get_genname());
3398 type->chk();
3399 checked=true;
3400 Type *t = type->get_type_refd_last();
3401 switch (t->get_typetype()) {
3402 case Type::T_PORT:
3403 error("External constant cannot be defined for port type `%s'",
3404 t->get_fullname().c_str());
3405 break;
3406 case Type::T_SIGNATURE:
3407 error("External constant cannot be defined for signature `%s'",
3408 t->get_fullname().c_str());
3409 break;
3410 default:
3411 break;
3412 }
3413 if (w_attrib_path) {
3414 w_attrib_path->chk_global_attrib();
3415 switch (type->get_type_refd_last()->get_typetype()) {
3416 case Type::T_SEQ_T:
3417 case Type::T_SET_T:
3418 case Type::T_CHOICE_T:
3419 // These types may have qualified attributes
3420 break;
3421 case Type::T_SEQOF: case Type::T_SETOF:
3422 break;
3423 default:
3424 w_attrib_path->chk_no_qualif();
3425 break;
3426 }
3427 }
3428 }
3429
3430 void Def_ExtConst::generate_code(output_struct *target, bool)
3431 {
3432 type->generate_code(target);
3433 target->header.global_vars = mputprintf(target->header.global_vars,
3434 "extern const %s& %s;\n", type->get_genname_value(my_scope).c_str(),
3435 get_genname().c_str());
3436 }
3437
3438 void Def_ExtConst::generate_code(Common::CodeGenHelper& cgh) {
3439 // constant definitions always go to its containing module
3440 generate_code(cgh.get_current_outputstruct());
3441 }
3442
3443 void Def_ExtConst::dump_internal(unsigned level) const
3444 {
3445 DEBUG(level, "External constant: %s @ %p", id->get_dispname().c_str(), (const void*)this);
3446 type->dump(level + 1);
3447 }
3448
3449 // =================================
3450 // ===== Def_Modulepar
3451 // =================================
3452
3453 Def_Modulepar::Def_Modulepar(Identifier *p_id, Type *p_type, Value *p_defval)
3454 : Definition(A_MODULEPAR, p_id)
3455 {
3456 if (!p_type) FATAL_ERROR("Ttcn::Def_Modulepar::Def_Modulepar()");
3457 type = p_type;
3458 type->set_ownertype(Type::OT_MODPAR_DEF, this);
3459 def_value = p_defval;
3460 }
3461
3462 Def_Modulepar::~Def_Modulepar()
3463 {
3464 delete type;
3465 delete def_value;
3466 }
3467
3468 Def_Modulepar* Def_Modulepar::clone() const
3469 {
3470 FATAL_ERROR("Def_Modulepar::clone");
3471 }
3472
3473 void Def_Modulepar::set_fullname(const string& p_fullname)
3474 {
3475 Definition::set_fullname(p_fullname);
3476 type->set_fullname(p_fullname + ".<type>");
3477 if (def_value) def_value->set_fullname(p_fullname + ".<default_value>");
3478 }
3479
3480 void Def_Modulepar::set_my_scope(Scope *p_scope)
3481 {
3482 Definition::set_my_scope(p_scope);
3483 type->set_my_scope(p_scope);
3484 if (def_value) def_value->set_my_scope(p_scope);
3485 }
3486
3487 Type *Def_Modulepar::get_Type()
3488 {
3489 chk();
3490 return type;
3491 }
3492
3493 void Def_Modulepar::chk()
3494 {
3495 if(checked) return;
3496 Error_Context cntxt(this, "In module parameter definition `%s'",
3497 id->get_dispname().c_str());
3498 type->set_genname(_T_, get_genname());
3499 type->chk();
3500 if (w_attrib_path) {
3501 w_attrib_path->chk_global_attrib();
3502 switch (type->get_type_refd_last()->get_typetype()) {
3503 case Type::T_SEQ_T:
3504 case Type::T_SET_T:
3505 case Type::T_CHOICE_T:
3506 // These types may have qualified attributes
3507 break;
3508 case Type::T_SEQOF: case Type::T_SETOF:
3509 break;
3510 default:
3511 w_attrib_path->chk_no_qualif();
3512 break;
3513 }
3514 }
3515 map<Type*,void> type_chain;
3516 map<Type::typetype_t, void> not_allowed;
3517 not_allowed.add(Type::T_PORT, 0);
3518 not_allowed.add(Type::T_COMPONENT, 0);
3519 not_allowed.add(Type::T_DEFAULT, 0);
3520 Type *t = type->get_type_refd_last();
3521 // if the type is valid the original will be returned
3522 Type::typetype_t tt = t->search_for_not_allowed_type(type_chain, not_allowed);
3523 type_chain.clear();
3524 not_allowed.clear();
3525 switch (tt) {
3526 case Type::T_PORT:
3527 error("Type of module parameter cannot be or embed port type `%s'",
3528 t->get_fullname().c_str());
3529 break;
3530 case Type::T_SIGNATURE:
3531 error("Type of module parameter cannot be signature `%s'",
3532 t->get_fullname().c_str());
3533 break;
3534 case Type::T_COMPONENT:
3535 error("Type of module parameter cannot be or embed component `%s'",
3536 t->get_fullname().c_str());
3537 break;
3538 case Type::T_DEFAULT:
3539 error("Type of module parameter cannot be or embed default `%s'",
3540 t->get_fullname().c_str());
3541 break;
3542 case Type::T_FUNCTION:
3543 case Type::T_ALTSTEP:
3544 case Type::T_TESTCASE:
3545 if (t->get_fat_runs_on_self()) {
3546 error("Type of module parameter cannot be of function reference type"
3547 " `%s' which has runs on self clause", t->get_fullname().c_str());
3548 }
3549 break;
3550 default:
3551#if defined(MINGW)
3552 checked = true;
3553#else
3554 if (def_value) {
3555 Error_Context cntxt2(def_value, "In default value");
3556 def_value->set_my_governor(type);
3557 type->chk_this_value_ref(def_value);
3558 checked = true;
3559 type->chk_this_value(def_value, 0, Type::EXPECTED_CONSTANT, INCOMPLETE_ALLOWED,
3560 OMIT_NOT_ALLOWED, SUB_CHK, has_implicit_omit_attr());
3561 if (!semantic_check_only) {
3562 def_value->set_genname_prefix("modulepar_");
3563 def_value->set_genname_recursive(get_genname());
3564 def_value->set_code_section(GovernedSimple::CS_PRE_INIT);
3565 }
3566 } else checked = true;
3567#endif
3568 break;
3569 }
3570 }
3571
3572 void Def_Modulepar::generate_code(output_struct *target, bool)
3573 {
3574 type->generate_code(target);
3575 const_def cdef;
3576 Code::init_cdef(&cdef);
3577 const string& t_genname = get_genname();
3578 const char *name = t_genname.c_str();
3579 type->generate_code_object(&cdef, my_scope, t_genname, "modulepar_", false);
3580 if (def_value) {
3581 cdef.init = update_location_object(cdef.init);
3582 cdef.init = def_value->generate_code_init(cdef.init, def_value->get_lhs_name().c_str());
3583 }
3584 Code::merge_cdef(target, &cdef);
3585 Code::free_cdef(&cdef);
3586
3587 if (has_implicit_omit_attr()) {
3588 target->functions.post_init = mputprintf(target->functions.post_init,
3589 "modulepar_%s.set_implicit_omit();\n", name);
3590 }
3591
3592 const char *dispname = id->get_dispname().c_str();
3593 target->functions.set_param = mputprintf(target->functions.set_param,
3594 "if (!strcmp(par_name, \"%s\")) {\n"
3595 "modulepar_%s.set_param(param);\n"
3596 "return TRUE;\n"
3597 "} else ", dispname, name);
3598
3599 if (target->functions.log_param) {
3600 // this is not the first modulepar
3601 target->functions.log_param = mputprintf(target->functions.log_param,
3602 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname);
3603 } else {
3604 // this is the first modulepar
3605 target->functions.log_param = mputprintf(target->functions.log_param,
3606 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname);
3607 }
3608 target->functions.log_param = mputprintf(target->functions.log_param,
3609 "%s.log();\n", name);
3610 }
3611
3612 void Def_Modulepar::generate_code(Common::CodeGenHelper& cgh) {
3613 // module parameter definitions always go to its containing module
3614 generate_code(cgh.get_current_outputstruct());
3615 }
3616
3617 void Def_Modulepar::dump_internal(unsigned level) const
3618 {
3619 DEBUG(level, "Module parameter: %s @ %p", id->get_dispname().c_str(), (const void*)this);
3620 type->dump(level + 1);
3621 if (def_value) def_value->dump(level + 1);
3622 else DEBUG(level + 1, "No default value");
3623 }
3624
3625 // =================================
3626 // ===== Def_Modulepar_Template
3627 // =================================
3628
3629 Def_Modulepar_Template::Def_Modulepar_Template(Identifier *p_id, Type *p_type, Template *p_deftmpl)
3630 : Definition(A_MODULEPAR_TEMP, p_id)
3631 {
3632 if (!p_type) FATAL_ERROR("Ttcn::Def_Modulepar_Template::Def_Modulepar_Template()");
3633 type = p_type;
3634 type->set_ownertype(Type::OT_MODPAR_DEF, this);
3635 def_template = p_deftmpl;
3636 }
3637
3638 Def_Modulepar_Template::~Def_Modulepar_Template()
3639 {
3640 delete type;
3641 delete def_template;
3642 }
3643
3644 Def_Modulepar_Template* Def_Modulepar_Template::clone() const
3645 {
3646 FATAL_ERROR("Def_Modulepar_Template::clone");
3647 }
3648
3649 void Def_Modulepar_Template::set_fullname(const string& p_fullname)
3650 {
3651 Definition::set_fullname(p_fullname);
3652 type->set_fullname(p_fullname + ".<type>");
3653 if (def_template) def_template->set_fullname(p_fullname + ".<default_template>");
3654 }
3655
3656 void Def_Modulepar_Template::set_my_scope(Scope *p_scope)
3657 {
3658 Definition::set_my_scope(p_scope);
3659 type->set_my_scope(p_scope);
3660 if (def_template) def_template->set_my_scope(p_scope);
3661 }
3662
3663 Type *Def_Modulepar_Template::get_Type()
3664 {
3665 chk();
3666 return type;
3667 }
3668
3669 void Def_Modulepar_Template::chk()
3670 {
3671 if(checked) return;
3672 Error_Context cntxt(this, "In template module parameter definition `%s'",
3673 id->get_dispname().c_str());
3674 if (w_attrib_path) {
3675 w_attrib_path->chk_global_attrib();
3676 switch (type->get_type_refd_last()->get_typetype()) {
3677 case Type::T_SEQ_T:
3678 case Type::T_SET_T:
3679 case Type::T_CHOICE_T:
3680 // These types may have qualified attributes
3681 break;
3682 case Type::T_SEQOF: case Type::T_SETOF:
3683 break;
3684 default:
3685 w_attrib_path->chk_no_qualif();
3686 break;
3687 }
3688 }
3689 type->set_genname(_T_, get_genname());
3690 type->chk();
3691 Type *t = type->get_type_refd_last();
3692 switch (t->get_typetype()) {
3693 case Type::T_PORT:
3694 error("Type of template module parameter cannot be port type `%s'",
3695 t->get_fullname().c_str());
3696 break;
3697 case Type::T_SIGNATURE:
3698 error("Type of template module parameter cannot be signature `%s'",
3699 t->get_fullname().c_str());
3700 break;
3701 case Type::T_FUNCTION:
3702 case Type::T_ALTSTEP:
3703 case Type::T_TESTCASE:
3704 if (t->get_fat_runs_on_self()) {
3705 error("Type of template module parameter cannot be of function reference type"
3706 " `%s' which has runs on self clause", t->get_fullname().c_str());
3707 }
3708 break;
3709 default:
3710 if (has_implicit_omit_attr()) {
3711 error("Implicit omit not supported for template module parameters");
3712 }
3713#if defined(MINGW)
3714 checked = true;
3715#else
3716 if (def_template) {
3717 Error_Context cntxt2(def_template, "In default template");
3718 def_template->set_my_governor(type);
3719 def_template->flatten(false);
3720 if (def_template->get_templatetype() == Template::CSTR_PATTERN &&
3721 type->get_type_refd_last()->get_typetype() == Type::T_USTR) {
3722 def_template->set_templatetype(Template::USTR_PATTERN);
3723 def_template->get_ustr_pattern()->set_pattern_type(
3724 PatternString::USTR_PATTERN);
3725 }
3726 type->chk_this_template_ref(def_template);
3727 checked = true;
3728 type->chk_this_template_generic(def_template, INCOMPLETE_ALLOWED,
3729 OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, has_implicit_omit_attr() ? IMPLICIT_OMIT : NOT_IMPLICIT_OMIT, 0);
3730 if (!semantic_check_only) {
3731 def_template->set_genname_prefix("modulepar_");
3732 def_template->set_genname_recursive(get_genname());
3733 def_template->set_code_section(GovernedSimple::CS_PRE_INIT);
3734 }
3735 } else checked = true;
3736#endif
3737 break;
3738 }
3739 }
3740
3741 void Def_Modulepar_Template::generate_code(output_struct *target, bool)
3742 {
3743 type->generate_code(target);
3744 const_def cdef;
3745 Code::init_cdef(&cdef);
3746 const string& t_genname = get_genname();
3747 const char *name = t_genname.c_str();
3748 type->generate_code_object(&cdef, my_scope, t_genname, "modulepar_", true);
3749 if (def_template) {
3750 cdef.init = update_location_object(cdef.init);
3751 cdef.init = def_template->generate_code_init(cdef.init, def_template->get_lhs_name().c_str());
3752 }
3753 Code::merge_cdef(target, &cdef);
3754 Code::free_cdef(&cdef);
3755
3756 if (has_implicit_omit_attr()) {
3757 FATAL_ERROR("Def_Modulepar_Template::generate_code()");
3758 }
3759
3760 const char *dispname = id->get_dispname().c_str();
3761 target->functions.set_param = mputprintf(target->functions.set_param,
3762 "if (!strcmp(par_name, \"%s\")) {\n"
3763 "modulepar_%s.set_param(param);\n"
3764 "return TRUE;\n"
3765 "} else ", dispname, name);
3766
3767 if (target->functions.log_param) {
3768 // this is not the first modulepar
3769 target->functions.log_param = mputprintf(target->functions.log_param,
3770 "TTCN_Logger::log_event_str(\", %s := \");\n", dispname);
3771 } else {
3772 // this is the first modulepar
3773 target->functions.log_param = mputprintf(target->functions.log_param,
3774 "TTCN_Logger::log_event_str(\"%s := \");\n", dispname);
3775 }
3776 target->functions.log_param = mputprintf(target->functions.log_param,
3777 "%s.log();\n", name);
3778 }
3779
3780 void Def_Modulepar_Template::generate_code(Common::CodeGenHelper& cgh) {
3781 // module parameter definitions always go to its containing module
3782 generate_code(cgh.get_current_outputstruct());
3783 }
3784
3785 void Def_Modulepar_Template::dump_internal(unsigned level) const
3786 {
3787 DEBUG(level, "Module parameter: %s @ %p", id->get_dispname().c_str(), (const void*)this);
3788 type->dump(level + 1);
3789 if (def_template) def_template->dump(level + 1);
3790 else DEBUG(level + 1, "No default template");
3791 }
3792
3793 // =================================
3794 // ===== Def_Template
3795 // =================================
3796
3797 Def_Template::Def_Template(template_restriction_t p_template_restriction,
3798 Identifier *p_id, Type *p_type, FormalParList *p_fpl,
3799 Reference *p_derived_ref, Template *p_body)
3800 : Definition(A_TEMPLATE, p_id), type(p_type), fp_list(p_fpl),
3801 derived_ref(p_derived_ref), base_template(0), recurs_deriv_checked(false),
3802 body(p_body), template_restriction(p_template_restriction),
3803 gen_restriction_check(false)
3804 {
3805 if (!p_type || !p_body) FATAL_ERROR("Ttcn::Def_Template::Def_Template()");
3806 type->set_ownertype(Type::OT_TEMPLATE_DEF, this);
3807 if (fp_list) fp_list->set_my_def(this);
3808 }
3809
3810 Def_Template::~Def_Template()
3811 {
3812 delete type;
3813 delete fp_list;
3814 delete derived_ref;
3815 delete body;
3816 }
3817
3818 Def_Template *Def_Template::clone() const
3819 {
3820 FATAL_ERROR("Def_Template::clone");
3821 }
3822
3823 void Def_Template::set_fullname(const string& p_fullname)
3824 {
3825 Definition::set_fullname(p_fullname);
3826 type->set_fullname(p_fullname + ".<type>");
3827 if (fp_list) fp_list->set_fullname(p_fullname + ".<formal_par_list>");
3828 if (derived_ref)
3829 derived_ref->set_fullname(p_fullname + ".<derived_reference>");
3830 body->set_fullname(p_fullname);
3831 }
3832
3833 void Def_Template::set_my_scope(Scope *p_scope)
3834 {
3835 bridgeScope.set_parent_scope(p_scope);
3836 bridgeScope.set_scopeMacro_name(id->get_dispname());
3837
3838 Definition::set_my_scope(&bridgeScope);
3839 type->set_my_scope(&bridgeScope);
3840 if (derived_ref) derived_ref->set_my_scope(&bridgeScope);
3841 if (fp_list) {
3842 fp_list->set_my_scope(&bridgeScope);
3843 body->set_my_scope(fp_list);
3844 } else body->set_my_scope(&bridgeScope);
3845 }
3846
3847 Setting *Def_Template::get_Setting()
3848 {
3849 return get_Template();
3850 }
3851
3852 Type *Def_Template::get_Type()
3853 {
3854 if (!checked) chk();
3855 return type;
3856 }
3857
3858 Template *Def_Template::get_Template()
3859 {
3860 if (!checked) chk();
3861 return body;
3862 }
3863
3864 FormalParList *Def_Template::get_FormalParList()
3865 {
3866 if (!checked) chk();
3867 return fp_list;
3868 }
3869
3870 void Def_Template::chk()
3871 {
3872 if (checked) return;
3873 Error_Context cntxt(this, "In template definition `%s'",
3874 id->get_dispname().c_str());
3875 const string& t_genname = get_genname();
3876 type->set_genname(_T_, t_genname);
3877 type->chk();
3878 if (w_attrib_path) {
3879 w_attrib_path->chk_global_attrib(true);
3880 switch (type->get_type_refd_last()->get_typetype_ttcn3()) {
3881 case Type::T_SEQ_T:
3882 case Type::T_SET_T:
3883 case Type::T_CHOICE_T:
3884 // These types may have qualified attributes
3885 break;
3886 case Type::T_SEQOF: case Type::T_SETOF:
3887 break;
3888 default:
3889 w_attrib_path->chk_no_qualif();
3890 break;
3891 }
3892 }
3893 if (fp_list) {
3894 chk_default();
3895 fp_list->chk(asstype);
3896 if (local_scope) error("Parameterized local template `%s' not supported",
3897 id->get_dispname().c_str());
3898 }
3899
3900 // Merge the elements of "all from" into the list
3901 body->flatten(false);
3902
3903 body->set_my_governor(type);
3904
3905 if (body->get_templatetype() == Template::CSTR_PATTERN &&
3906 type->get_type_refd_last()->get_typetype() == Type::T_USTR) {
3907 body->set_templatetype(Template::USTR_PATTERN);
3908 body->get_ustr_pattern()->set_pattern_type(PatternString::USTR_PATTERN);
3909 }
3910
3911 type->chk_this_template_ref(body);
3912 checked = true;
3913 Type *t = type->get_type_refd_last();
3914 if (t->get_typetype() == Type::T_PORT) {
3915 error("Template cannot be defined for port type `%s'",
3916 t->get_fullname().c_str());
3917 }
3918 chk_modified();
3919 chk_recursive_derivation();
3920 type->chk_this_template_generic(body, INCOMPLETE_ALLOWED, OMIT_ALLOWED,
3921 ANY_OR_OMIT_ALLOWED, SUB_CHK,
3922 has_implicit_omit_attr() ? IMPLICIT_OMIT : NOT_IMPLICIT_OMIT, 0);
3923
3924 chk_erroneous_attr();
3925 if (erroneous_attrs) body->set_err_descr(erroneous_attrs->get_err_descr());
3926
3927 {
3928 ReferenceChain refch(type, "While checking embedded recursions");
3929 body->chk_recursions(refch);
3930 }
3931 if (template_restriction!=TR_NONE) {
3932 Error_Context ec(this, "While checking template restriction `%s'",
3933 Template::get_restriction_name(template_restriction));
3934 gen_restriction_check =
3935 body->chk_restriction("template definition", template_restriction);
3936 if (fp_list && template_restriction!=TR_PRESENT) {
3937 size_t nof_fps = fp_list->get_nof_fps();
3938 for (size_t i=0; i<nof_fps; i++) {
3939 FormalPar* fp = fp_list->get_fp_byIndex(i);
3940 // if formal par is not template then skip restriction checking,
3941 // templates can have only `in' parameters
3942 if (fp->get_asstype()!=A_PAR_TEMPL_IN) continue;
3943 template_restriction_t fp_tr = fp->get_template_restriction();
3944 switch (template_restriction) {
3945 case TR_VALUE:
3946 case TR_OMIT:
3947 switch (fp_tr) {
3948 case TR_VALUE:
3949 case TR_OMIT:
3950 // allowed
3951 break;
3952 case TR_PRESENT:
3953 fp->error("Formal parameter with template restriction `%s' "
3954 "not allowed here", Template::get_restriction_name(fp_tr));
3955 break;
3956 case TR_NONE:
3957 fp->error("Formal parameter without template restriction "
3958 "not allowed here");
3959 break;
3960 default:
3961 FATAL_ERROR("Ttcn::Def_Template::chk()");
3962 }
3963 break;
3964 default:
3965 FATAL_ERROR("Ttcn::Def_Template::chk()");
3966 }
3967 }
3968 }
3969 }
3970 if (!semantic_check_only) {
3971 if (fp_list) fp_list->set_genname(t_genname);
3972 body->set_genname_prefix("template_");
3973 body->set_genname_recursive(t_genname);
3974 body->set_code_section(fp_list ? GovernedSimple::CS_INLINE :
3975 GovernedSimple::CS_POST_INIT);
3976 }
3977
3978 }
3979
3980 void Def_Template::chk_default() const
3981 {
3982 if (!fp_list) FATAL_ERROR("Def_Template::chk_default()");
3983 if (!derived_ref) {
3984 if (fp_list->has_notused_defval())
3985 fp_list->error("Only modified templates are allowed to use the not "
3986 "used symbol (`-') as the default parameter");
3987 return;
3988 }
3989 Common::Assignment *ass = derived_ref->get_refd_assignment(false);
3990 if (!ass || ass->get_asstype() != A_TEMPLATE) return; // Work locally.
3991 Def_Template *base = dynamic_cast<Def_Template *>(ass);
3992 if (!base) FATAL_ERROR("Def_Template::chk_default()");
3993 FormalParList *base_fpl = base->get_FormalParList();
3994 size_t nof_base_fps = base_fpl ? base_fpl->get_nof_fps() : 0;
3995 size_t nof_local_fps = fp_list ? fp_list->get_nof_fps() : 0;
3996 size_t min_fps = nof_base_fps;
3997 if (nof_local_fps < nof_base_fps) min_fps = nof_local_fps;
3998 for (size_t i = 0; i < min_fps; i++) {
3999 FormalPar *base_fp = base_fpl->get_fp_byIndex(i);
4000 FormalPar *local_fp = fp_list->get_fp_byIndex(i);
4001 if (local_fp->has_notused_defval()) {
4002 if (base_fp->has_defval()) {
4003 local_fp->set_defval(base_fp->get_defval());
4004 } else {
4005 local_fp->error("Not used symbol (`-') doesn't have the "
4006 "corresponding default parameter in the "
4007 "base template");
4008 }
4009 }
4010 }
4011 // Additional parameters in the derived template with using the not used
4012 // symbol. TODO: Merge the loops.
4013 for (size_t i = nof_base_fps; i < nof_local_fps; i++) {
4014 FormalPar *local_fp = fp_list->get_fp_byIndex(i);
4015 if (local_fp->has_notused_defval())
4016 local_fp->error("Not used symbol (`-') doesn't have the "
4017 "corresponding default parameter in the "
4018 "base template");
4019 }
4020 }
4021
4022 void Def_Template::chk_modified()
4023 {
4024 if (!derived_ref) return;
4025 // Do not check the (non-existent) actual parameter list of the derived
4026 // reference against the formal parameter list of the base template.
4027 // According to TTCN-3 syntax the derived reference cannot have parameters
4028 // even if the base template is parameterized.
4029 Common::Assignment *ass = derived_ref->get_refd_assignment(false);
4030 // Checking the existence and type compatibility of the base template.
4031 if (!ass) return;
4032 if (ass->get_asstype() != A_TEMPLATE) {
4033 derived_ref->error("Reference to a template was expected in the "
4034 "`modifies' definition instead of %s",
4035 ass->get_description().c_str());
4036 return;
4037 }
4038 base_template = dynamic_cast<Def_Template*>(ass);
4039 if (!base_template) FATAL_ERROR("Def_Template::chk_modified()");
4040 Type *base_type = base_template->get_Type();
4041 TypeCompatInfo info_base(my_scope->get_scope_mod(), type, base_type, true,
4042 false, true);
4043 TypeChain l_chain_base;
4044 TypeChain r_chain_base;
4045 if (!type->is_compatible(base_type, &info_base, &l_chain_base,
4046 &r_chain_base)) {
4047 if (info_base.is_subtype_error()) {
4048 type->error("%s", info_base.get_subtype_error().c_str());
4049 } else
4050 if (!info_base.is_erroneous()) {
4051 type->error("The modified template has different type than base "
4052 "template `%s': `%s' was expected instead of `%s'",
4053 ass->get_fullname().c_str(),
4054 base_type->get_typename().c_str(),
4055 type->get_typename().c_str());
4056 } else {
4057 // Always use the format string.
4058 type->error("%s", info_base.get_error_str_str().c_str());
4059 }
4060 } else {
4061 if (info_base.needs_conversion())
4062 body->set_needs_conversion();
4063 }
4064 // Check for restriction.
4065 if (Template::is_less_restrictive(base_template->get_template_restriction(),
4066 template_restriction)) {
4067 error("The template restriction is not the same or more "
4068 "restrictive as of base template `%s'", ass->get_fullname().c_str());
4069 }
4070 // Checking formal parameter lists.
4071 FormalParList *base_fpl = base_template->get_FormalParList();
4072 size_t nof_base_fps = base_fpl ? base_fpl->get_nof_fps() : 0;
4073 size_t nof_local_fps = fp_list ? fp_list->get_nof_fps() : 0;
4074 size_t min_fps;
4075 if (nof_local_fps < nof_base_fps) {
4076 error("The modified template has fewer formal parameters than base "
4077 "template `%s': at least %lu parameter%s expected instead of %lu",
4078 ass->get_fullname().c_str(), (unsigned long)nof_base_fps,
4079 nof_base_fps > 1 ? "s were" : " was", (unsigned long)nof_local_fps);
4080 min_fps = nof_local_fps;
4081 } else min_fps = nof_base_fps;
4082
4083 for (size_t i = 0; i < min_fps; i++) {
4084 FormalPar *base_fp = base_fpl->get_fp_byIndex(i);
4085 FormalPar *local_fp = fp_list->get_fp_byIndex(i);
4086 Error_Context cntxt(local_fp, "In formal parameter #%lu",
4087 (unsigned long)(i + 1));
4088 // Check for parameter kind equivalence (value or template).
4089 if (base_fp->get_asstype() != local_fp->get_asstype())
4090 local_fp->error("The kind of parameter is not the same as in base "
4091 "template `%s': %s was expected instead of %s",
4092 ass->get_fullname().c_str(), base_fp->get_assname(),
4093 local_fp->get_assname());
4094 // Check for type compatibility.
4095 Type *base_fp_type = base_fp->get_Type();
4096 Type *local_fp_type = local_fp->get_Type();
4097 TypeCompatInfo info_par(my_scope->get_scope_mod(), base_fp_type,
4098 local_fp_type, true, false);
4099 TypeChain l_chain_par;
4100 TypeChain r_chain_par;
4101 if (!base_fp_type->is_compatible(local_fp_type, &info_par, &l_chain_par,
4102 &r_chain_par)) {
4103 if (info_par.is_subtype_error()) {
4104 local_fp_type->error("%s", info_par.get_subtype_error().c_str());
4105 } else
4106 if (!info_par.is_erroneous()) {
4107 local_fp_type->error("The type of parameter is not the same as in "
4108 "base template `%s': `%s' was expected instead "
4109 "of `%s'",
4110 ass->get_fullname().c_str(),
4111 base_fp_type->get_typename().c_str(),
4112 local_fp_type->get_typename().c_str());
4113 } else {
4114 local_fp_type->error("%s", info_par.get_error_str_str().c_str());
4115 }
4116 } else {
4117 if (info_par.needs_conversion())
4118 body->set_needs_conversion();
4119 }
4120 // Check for name equivalence.
4121 const Identifier& base_fp_id = base_fp->get_id();
4122 const Identifier& local_fp_id = local_fp->get_id();
4123 if (!(base_fp_id == local_fp_id))
4124 local_fp->error("The name of parameter is not the same as in base "
4125 "template `%s': `%s' was expected instead of `%s'",
4126 ass->get_fullname().c_str(),
4127 base_fp_id.get_dispname().c_str(),
4128 local_fp_id.get_dispname().c_str());
4129 // Check for restrictions: the derived must be same or more restrictive.
4130 if (base_fp->get_asstype()==local_fp->get_asstype() &&
4131 Template::is_less_restrictive(base_fp->get_template_restriction(),
4132 local_fp->get_template_restriction())) {
4133 local_fp->error("The restriction of parameter is not the same or more "
4134 "restrictive as in base template `%s'", ass->get_fullname().c_str());
4135 }
4136 }
4137 // Set the pointer to the body of base template.
4138 body->set_base_template(base_template->get_Template());
4139 }
4140
4141 void Def_Template::chk_recursive_derivation()
4142 {
4143 if (recurs_deriv_checked) return;
4144 if (base_template) {
4145 ReferenceChain refch(this, "While checking the chain of base templates");
4146 refch.add(get_fullname());
4147 for (Def_Template *iter = base_template; iter; iter = iter->base_template)
4148 {
4149 if (iter->recurs_deriv_checked) break;
4150 else if (refch.add(iter->get_fullname()))
4151 iter->recurs_deriv_checked = true;
4152 else break;
4153 }
4154 }
4155 recurs_deriv_checked = true;
4156 }
4157
4158 void Def_Template::generate_code(output_struct *target, bool)
4159 {
4160 type->generate_code(target);
4161 if (fp_list) {
4162 // Parameterized template. Generate code for a function which returns
4163 // a $(genname)_template and has the appropriate parameters.
4164 const string& t_genname = get_genname();
4165 const char *template_name = t_genname.c_str();
4166 const char *template_dispname = id->get_dispname().c_str();
4167 const string& type_genname = type->get_genname_template(my_scope);
4168 const char *type_genname_str = type_genname.c_str();
4169 char *formal_par_list = fp_list->generate_code(memptystr());
4170 fp_list->generate_code_defval(target);
4171 target->header.function_prototypes =
4172 mputprintf(target->header.function_prototypes,
4173 "extern %s %s(%s);\n",
4174 type_genname_str, template_name, formal_par_list);
4175 char *function_body = mprintf("%s %s(%s)\n"
4176 "{\n", type_genname_str, template_name, formal_par_list);
4177 function_body = create_location_object(function_body, "TEMPLATE",
4178 template_dispname);
4179 if (base_template) {
4180 // modified template
4181 function_body = mputprintf(function_body, "%s ret_val(%s",
4182 type_genname_str,
4183 base_template->get_genname_from_scope(my_scope).c_str());
4184 if (base_template->fp_list) {
4185 // the base template is also parameterized
4186 function_body = mputc(function_body, '(');
4187 size_t nof_base_pars = base_template->fp_list->get_nof_fps();
4188 for (size_t i = 0; i < nof_base_pars; i++) {
4189 if (i > 0) function_body = mputstr(function_body, ", ");
4190 function_body = mputstr(function_body,
4191 fp_list->get_fp_byIndex(i)->get_id().get_name().c_str());
4192 }
4193 function_body = mputc(function_body, ')');
4194 }
4195 function_body = mputstr(function_body, ");\n");
4196 } else {
4197 // simple template
4198 function_body = mputprintf(function_body, "%s ret_val;\n",
4199 type_genname_str);
4200 }
4201 if (erroneous_attrs && erroneous_attrs->get_err_descr()) {
4202 function_body = erroneous_attrs->get_err_descr()->
4203 generate_code_str(function_body, string("ret_val"));
4204 }
4205 function_body = body->generate_code_init(function_body, "ret_val");
4206 if (template_restriction!=TR_NONE && gen_restriction_check)
4207 function_body = Template::generate_restriction_check_code(function_body,
4208 "ret_val", template_restriction);
4209 function_body = mputstr(function_body, "return ret_val;\n"
4210 "}\n\n");
4211 target->source.function_bodies =
4212 mputstr(target->source.function_bodies, function_body);
4213 Free(formal_par_list);
4214 Free(function_body);
4215 } else {
4216 // non-parameterized template
4217 const_def cdef;
4218 Code::init_cdef(&cdef);
4219 type->generate_code_object(&cdef, body);
4220 cdef.init = update_location_object(cdef.init);
4221 if (base_template) {
4222 // modified template
4223 if (base_template->my_scope->get_scope_mod_gen() ==
4224 my_scope->get_scope_mod_gen()) {
4225 // if the base template is in the same module its body has to be
4226 // initialized first
4227 cdef.init = base_template->body->generate_code_init(cdef.init,
4228 base_template->body->get_lhs_name().c_str());
4229 }
4230 if (use_runtime_2 && body->get_needs_conversion()) {
4231 Type *body_type = body->get_my_governor()->get_type_refd_last();
4232 Type *base_type = base_template->body->get_my_governor()
4233 ->get_type_refd_last();
4234 if (!body_type || !base_type)
4235 FATAL_ERROR("Def_Template::generate_code()");
4236 const string& tmp_id = body->get_temporary_id();
4237 const char *tmp_id_str = tmp_id.c_str();
4238 // base template initialization
4239 cdef.init = mputprintf(cdef.init,
4240 "%s %s;\n"
4241 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4242 "and `%s' are not compatible at run-time\");\n"
4243 "%s = %s;\n",
4244 body_type->get_genname_template(my_scope).c_str(), tmp_id_str,
4245 TypeConv::get_conv_func(base_type, body_type, my_scope
4246 ->get_scope_mod()).c_str(), tmp_id_str, base_template
4247 ->get_genname_from_scope(my_scope).c_str(), base_type
4248 ->get_typename().c_str(), body_type->get_typename().c_str(),
4249 body->get_lhs_name().c_str(), tmp_id_str);
4250 } else {
4251 cdef.init = mputprintf(cdef.init, "%s = %s;\n",
4252 body->get_lhs_name().c_str(),
4253 base_template->get_genname_from_scope(my_scope).c_str());
4254 }
4255 }
4256 if (use_runtime_2 && TypeConv::needs_conv_refd(body))
4257 cdef.init = TypeConv::gen_conv_code_refd(cdef.init,
4258 body->get_lhs_name().c_str(), body);
4259 else
4260 cdef.init = body->generate_code_init(cdef.init,
4261 body->get_lhs_name().c_str());
4262 if (template_restriction != TR_NONE && gen_restriction_check)
4263 cdef.init = Template::generate_restriction_check_code(cdef.init,
4264 body->get_lhs_name().c_str(), template_restriction);
4265 target->header.global_vars = mputstr(target->header.global_vars,
4266 cdef.decl);
4267 target->source.global_vars = mputstr(target->source.global_vars,
4268 cdef.def);
4269 target->functions.post_init = mputstr(target->functions.post_init,
4270 cdef.init);
4271 Code::free_cdef(&cdef);
4272 }
4273 }
4274
4275 void Def_Template::generate_code(Common::CodeGenHelper& cgh) {
4276 generate_code(cgh.get_outputstruct(this));
4277 }
4278
4279 char *Def_Template::generate_code_str(char *str)
4280 {
4281 const string& t_genname = get_genname();
4282 const char *genname_str = t_genname.c_str();
4283 const string& type_genname = type->get_genname_template(my_scope);
4284 const char *type_genname_str = type_genname.c_str();
4285 if (fp_list) {
4286 const char *dispname_str = id->get_dispname().c_str();
4287 NOTSUPP("Code generation for parameterized local template `%s'",
4288 dispname_str);
4289 str = mputprintf(str, "/* NOT SUPPORTED: template %s */\n",
4290 dispname_str);
4291 } else {
4292 if (base_template) {
4293 // non-parameterized modified template
4294 if (use_runtime_2 && body->get_needs_conversion()) {
4295 Type *body_type = body->get_my_governor()->get_type_refd_last();
4296 Type *base_type = base_template->body->get_my_governor()
4297 ->get_type_refd_last();
4298 if (!body_type || !base_type)
4299 FATAL_ERROR("Def_Template::generate_code_str()");
4300 const string& tmp_id = body->get_temporary_id();
4301 const char *tmp_id_str = tmp_id.c_str();
4302 str = mputprintf(str,
4303 "%s %s;\n"
4304 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
4305 "and `%s' are not compatible at run-time\");\n"
4306 "%s %s(%s);\n",
4307 body_type->get_genname_template(my_scope).c_str(), tmp_id_str,
4308 TypeConv::get_conv_func(base_type, body_type, my_scope
4309 ->get_scope_mod()).c_str(), tmp_id_str, base_template
4310 ->get_genname_from_scope(my_scope).c_str(), base_type
4311 ->get_typename().c_str(), body_type->get_typename().c_str(),
4312 type_genname_str, genname_str, tmp_id_str);
4313 } else {
4314 // the object is initialized from the base template by the
4315 // constructor
4316 str = mputprintf(str, "%s %s(%s);\n", type_genname_str, genname_str,
4317 base_template->get_genname_from_scope(my_scope).c_str());
4318 }
4319 // the modified body is assigned in the subsequent statements
4320 str = body->generate_code_init(str, genname_str);
4321 } else {
4322 // non-parameterized non-modified template
4323 if (body->has_single_expr()) {
4324 // the object is initialized by the constructor
4325 str = mputprintf(str, "%s %s(%s);\n", type_genname_str,
4326 genname_str, body->get_single_expr(false).c_str());
4327 } else {
4328 // the default constructor is used
4329 str = mputprintf(str, "%s %s;\n", type_genname_str, genname_str);
4330 // the body is assigned in the subsequent statements
4331 str = body->generate_code_init(str, genname_str);
4332 }
4333 }
4334 if (template_restriction != TR_NONE && gen_restriction_check)
4335 str = Template::generate_restriction_check_code(str, genname_str,
4336 template_restriction);
4337 }
4338 return str;
4339 }
4340
4341 void Def_Template::ilt_generate_code(ILT *ilt)
4342 {
4343 const string& t_genname = get_genname();
4344 const char *genname_str = t_genname.c_str();
4345 char*& def=ilt->get_out_def();
4346 char*& init=ilt->get_out_branches();
4347 if (fp_list) {
4348 const char *dispname_str = id->get_dispname().c_str();
4349 NOTSUPP("Code generation for parameterized local template `%s'",
4350 dispname_str);
4351 def = mputprintf(def, "/* NOT SUPPORTED: template %s */\n", dispname_str);
4352 init = mputprintf(init, "/* NOT SUPPORTED: template %s */\n",
4353 dispname_str);
4354 } else {
4355 // non-parameterized template
4356 // use the default constructor for initialization
4357 def = mputprintf(def, "%s %s;\n",
4358 type->get_genname_template(my_scope).c_str(), genname_str);
4359 if (base_template) {
4360 // copy the base template with an assignment
4361 init = mputprintf(init, "%s = %s;\n", genname_str,
4362 base_template->get_genname_from_scope(my_scope).c_str());
4363 }
4364 // finally assign the body
4365 init = body->generate_code_init(init, genname_str);
4366 if (template_restriction!=TR_NONE && gen_restriction_check)
4367 init = Template::generate_restriction_check_code(init, genname_str,
4368 template_restriction);
4369 }
4370 }
4371
4372 void Def_Template::dump_internal(unsigned level) const
4373 {
4374 DEBUG(level, "Template: %s", id->get_dispname().c_str());
4375 if (fp_list) fp_list->dump(level + 1);
4376 if (derived_ref)
4377 DEBUG(level + 1, "modifies: %s", derived_ref->get_dispname().c_str());
4378 if (template_restriction!=TR_NONE)
4379 DEBUG(level + 1, "restriction: %s",
4380 Template::get_restriction_name(template_restriction));
4381 type->dump(level + 1);
4382 body->dump(level + 1);
4383 }
4384
4385 // =================================
4386 // ===== Def_Var
4387 // =================================
4388
4389 Def_Var::Def_Var(Identifier *p_id, Type *p_type, Value *p_initial_value)
4390 : Definition(A_VAR, p_id), type(p_type), initial_value(p_initial_value)
4391 {
4392 if (!p_type) FATAL_ERROR("Ttcn::Def_Var::Def_Var()");
4393 type->set_ownertype(Type::OT_VAR_DEF, this);
4394 }
4395
4396 Def_Var::~Def_Var()
4397 {
4398 delete type;
4399 delete initial_value;
4400 }
4401
4402 Def_Var *Def_Var::clone() const
4403 {
4404 FATAL_ERROR("Def_Var::clone");
4405 }
4406
4407 void Def_Var::set_fullname(const string& p_fullname)
4408 {
4409 Definition::set_fullname(p_fullname);
4410 type->set_fullname(p_fullname + ".<type>");
4411 if (initial_value)
4412 initial_value->set_fullname(p_fullname + ".<initial_value>");
4413 }
4414
4415 void Def_Var::set_my_scope(Scope *p_scope)
4416 {
4417 Definition::set_my_scope(p_scope);
4418 type->set_my_scope(p_scope);
4419 if (initial_value) initial_value->set_my_scope(p_scope);
4420 }
4421
4422 Type *Def_Var::get_Type()
4423 {
4424 chk();
4425 return type;
4426 }
4427
4428 void Def_Var::chk()
4429 {
4430 if(checked) return;
4431 Error_Context cntxt(this, "In variable definition `%s'",
4432 id->get_dispname().c_str());
4433 type->set_genname(_T_, get_genname());
4434 type->chk();
4435 checked = true;
4436 Type *t = type->get_type_refd_last();
4437 switch (t->get_typetype()) {
4438 case Type::T_PORT:
4439 error("Variable cannot be defined for port type `%s'",
4440 t->get_fullname().c_str());
4441 break;
4442 case Type::T_SIGNATURE:
4443 error("Variable cannot be defined for signature `%s'",
4444 t->get_fullname().c_str());
4445 break;
4446 default:
4447 if (initial_value) {
4448 initial_value->set_my_governor(type);
4449 type->chk_this_value_ref(initial_value);
4450 type->chk_this_value(initial_value, this, is_local() ?
4451 Type::EXPECTED_DYNAMIC_VALUE : Type::EXPECTED_STATIC_VALUE,
4452 INCOMPLETE_ALLOWED, OMIT_NOT_ALLOWED, SUB_CHK);
4453 if (!semantic_check_only) {
4454 initial_value->set_genname_recursive(get_genname());
4455 initial_value->set_code_section(GovernedSimple::CS_INLINE);
4456 }
4457 }
4458 break;
4459 }
4460
4461 if (w_attrib_path) {
4462 w_attrib_path->chk_global_attrib();
4463 w_attrib_path->chk_no_qualif();
4464 }
4465 }
4466
4467 bool Def_Var::chk_identical(Definition *p_def)
4468 {
4469 chk();
4470 p_def->chk();
4471 if (p_def->get_asstype() != A_VAR) {
4472 const char *dispname_str = id->get_dispname().c_str();
4473 error("Local definition `%s' is a variable, but the definition "
4474 "inherited from component type `%s' is a %s", dispname_str,
4475 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
4476 p_def->note("The inherited definition of `%s' is here", dispname_str);
4477 return false;
4478 }
4479 Def_Var *p_def_var = dynamic_cast<Def_Var*>(p_def);
4480 if (!p_def_var) FATAL_ERROR("Def_Var::chk_identical()");
4481 if (!type->is_identical(p_def_var->type)) {
4482 const char *dispname_str = id->get_dispname().c_str();
4483 type->error("Local variable `%s' has type `%s', but the variable "
4484 "inherited from component type `%s' has type `%s'", dispname_str,
4485 type->get_typename().c_str(),
4486 p_def_var->get_my_scope()->get_fullname().c_str(),
4487 p_def_var->type->get_typename().c_str());
4488 p_def_var->note("The inherited variable `%s' is here", dispname_str);
4489 return false;
4490 }
4491 if (initial_value) {
4492 if (p_def_var->initial_value) {
4493 if (!initial_value->is_unfoldable() &&
4494 !p_def_var->initial_value->is_unfoldable() &&
4495 !(*initial_value == *p_def_var->initial_value)) {
4496 const char *dispname_str = id->get_dispname().c_str();
4497 initial_value->warning("Local variable `%s' and the variable "
4498 "inherited from component type `%s' have different initial values",
4499 dispname_str, p_def_var->get_my_scope()->get_fullname().c_str());
4500 p_def_var->note("The inherited variable `%s' is here", dispname_str);
4501 }
4502 } else {
4503 const char *dispname_str = id->get_dispname().c_str();
4504 initial_value->warning("Local variable `%s' has initial value, but "
4505 "the variable inherited from component type `%s' does not",
4506 dispname_str, p_def_var->get_my_scope()->get_fullname().c_str());
4507 p_def_var->note("The inherited variable `%s' is here", dispname_str);
4508 }
4509 } else if (p_def_var->initial_value) {
4510 const char *dispname_str = id->get_dispname().c_str();
4511 warning("Local variable `%s' does not have initial value, but the "
4512 "variable inherited from component type `%s' has", dispname_str,
4513 p_def_var->get_my_scope()->get_fullname().c_str());
4514 p_def_var->note("The inherited variable `%s' is here", dispname_str);
4515 }
4516 return true;
4517 }
4518
4519 void Def_Var::generate_code(output_struct *target, bool clean_up)
4520 {
4521 type->generate_code(target);
4522 const_def cdef;
4523 Code::init_cdef(&cdef);
4524 type->generate_code_object(&cdef, my_scope, get_genname(), 0, false);
4525 Code::merge_cdef(target, &cdef);
4526 Code::free_cdef(&cdef);
4527 if (initial_value) {
4528 target->functions.init_comp =
4529 initial_value->generate_code_init(target->functions.init_comp,
4530 initial_value->get_lhs_name().c_str());
4531 } else if (clean_up) { // No initial value.
4532 target->functions.init_comp = mputprintf(target->functions.init_comp,
4533 "%s.clean_up();\n", get_genname().c_str());
4534 }
4535 }
4536
4537 void Def_Var::generate_code(CodeGenHelper& cgh)
4538 {
4539 generate_code(cgh.get_outputstruct(this));
4540 }
4541
4542 char *Def_Var::generate_code_str(char *str)
4543 {
4544 const string& t_genname = get_genname();
4545 const char *genname_str = t_genname.c_str();
4546 if (initial_value && initial_value->has_single_expr()) {
4547 // the initial value can be represented by a single C++ expression
4548 // the object is initialized by the constructor
4549 str = mputprintf(str, "%s %s(%s);\n",
4550 type->get_genname_value(my_scope).c_str(), genname_str,
4551 initial_value->get_single_expr().c_str());
4552 } else {
4553 // use the default constructor
4554 str = mputprintf(str, "%s %s;\n",
4555 type->get_genname_value(my_scope).c_str(), genname_str);
4556 if (initial_value) {
4557 // the initial value is assigned using subsequent statements
4558 str = initial_value->generate_code_init(str, genname_str);
4559 }
4560 }
4561 return str;
4562 }
4563
4564 void Def_Var::ilt_generate_code(ILT *ilt)
4565 {
4566 const string& t_genname = get_genname();
4567 const char *genname_str = t_genname.c_str();
4568 char*& def=ilt->get_out_def();
4569 char*& init=ilt->get_out_branches();
4570 def = mputprintf(def, "%s %s;\n", type->get_genname_value(my_scope).c_str(),
4571 genname_str);
4572 if (initial_value)
4573 init = initial_value->generate_code_init(init, genname_str);
4574 }
4575
4576 char *Def_Var::generate_code_init_comp(char *str, Definition *base_defn)
4577 {
4578 if (initial_value) {
4579 str = initial_value->generate_code_init(str,
4580 base_defn->get_genname_from_scope(my_scope).c_str());
4581 }
4582 return str;
4583 }
4584
4585 void Def_Var::dump_internal(unsigned level) const
4586 {
4587 DEBUG(level, "Variable %s", id->get_dispname().c_str());
4588 type->dump(level + 1);
4589 if (initial_value) initial_value->dump(level + 1);
4590 }
4591
4592 // =================================
4593 // ===== Def_Var_Template
4594 // =================================
4595
4596 Def_Var_Template::Def_Var_Template(Identifier *p_id, Type *p_type,
4597 Template *p_initial_value, template_restriction_t p_template_restriction)
4598 : Definition(A_VAR_TEMPLATE, p_id), type(p_type),
4599 initial_value(p_initial_value), template_restriction(p_template_restriction)
4600 {
4601 if (!p_type) FATAL_ERROR("Ttcn::Def_Var_Template::Def_Var_Template()");
4602 type->set_ownertype(Type::OT_VARTMPL_DEF, this);
4603 }
4604
4605 Def_Var_Template::~Def_Var_Template()
4606 {
4607 delete type;
4608 delete initial_value;
4609 }
4610
4611 Def_Var_Template *Def_Var_Template::clone() const
4612 {
4613 FATAL_ERROR("Def_Var_Template::clone");
4614 }
4615
4616 void Def_Var_Template::set_fullname(const string& p_fullname)
4617 {
4618 Definition::set_fullname(p_fullname);
4619 type->set_fullname(p_fullname + ".<type>");
4620 if (initial_value)
4621 initial_value->set_fullname(p_fullname + ".<initial_value>");
4622 }
4623
4624 void Def_Var_Template::set_my_scope(Scope *p_scope)
4625 {
4626 Definition::set_my_scope(p_scope);
4627 type->set_my_scope(p_scope);
4628 if (initial_value) initial_value->set_my_scope(p_scope);
4629 }
4630
4631 Type *Def_Var_Template::get_Type()
4632 {
4633 chk();
4634 return type;
4635 }
4636
4637 void Def_Var_Template::chk()
4638 {
4639 if(checked) return;
4640 Error_Context cntxt(this, "In template variable definition `%s'",
4641 id->get_dispname().c_str());
4642 type->set_genname(_T_, get_genname());
4643 type->chk();
4644 checked = true;
4645 Type *t = type->get_type_refd_last();
4646 if (t->get_typetype() == Type::T_PORT) {
4647 error("Template variable cannot be defined for port type `%s'",
4648 t->get_fullname().c_str());
4649 }
4650
4651 if (initial_value) {
4652 initial_value->set_my_governor(type);
4653 initial_value->flatten(false);
4654
4655 if (initial_value->get_templatetype() == Template::CSTR_PATTERN &&
4656 type->get_type_refd_last()->get_typetype() == Type::T_USTR) {
4657 initial_value->set_templatetype(Template::USTR_PATTERN);
4658 initial_value->get_ustr_pattern()->set_pattern_type(
4659 PatternString::USTR_PATTERN);
4660 }
4661
4662 type->chk_this_template_ref(initial_value);
4663 // temporary hack: to allow incomplete body as initial value
4664 // checking as a modified template, but without a base template
4665 type->chk_this_template_generic(initial_value, INCOMPLETE_ALLOWED,
4666 OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, IMPLICIT_OMIT, 0);
4667 gen_restriction_check =
4668 initial_value->chk_restriction("template variable definition",
4669 template_restriction);
4670 if (!semantic_check_only) {
4671 initial_value->set_genname_recursive(get_genname());
4672 initial_value->set_code_section(GovernedSimple::CS_INLINE);
4673 }
4674 }
4675 if (w_attrib_path) {
4676 w_attrib_path->chk_global_attrib();
4677 w_attrib_path->chk_no_qualif();
4678 }
4679 }
4680
4681 bool Def_Var_Template::chk_identical(Definition *p_def)
4682 {
4683 chk();
4684 p_def->chk();
4685 if (p_def->get_asstype() != A_VAR_TEMPLATE) {
4686 const char *dispname_str = id->get_dispname().c_str();
4687 error("Local definition `%s' is a template variable, but the definition "
4688 "inherited from component type `%s' is a %s", dispname_str,
4689 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
4690 p_def->note("The inherited definition of `%s' is here", dispname_str);
4691 return false;
4692 }
4693 Def_Var_Template *p_def_var_template =
4694 dynamic_cast<Def_Var_Template*>(p_def);
4695 if (!p_def_var_template) FATAL_ERROR("Def_Var_Template::chk_identical()");
4696 if (!type->is_identical(p_def_var_template->type)) {
4697 const char *dispname_str = id->get_dispname().c_str();
4698 type->error("Local template variable `%s' has type `%s', but the "
4699 "template variable inherited from component type `%s' has type `%s'",
4700 dispname_str, type->get_typename().c_str(),
4701 p_def_var_template->get_my_scope()->get_fullname().c_str(),
4702 p_def_var_template->type->get_typename().c_str());
4703 p_def_var_template->note("The inherited template variable `%s' is here",
4704 dispname_str);
4705 return false;
4706 }
4707 if (initial_value) {
4708 if (!p_def_var_template->initial_value) {
4709 const char *dispname_str = id->get_dispname().c_str();
4710 initial_value->warning("Local template variable `%s' has initial "
4711 "value, but the template variable inherited from component type "
4712 "`%s' does not", dispname_str,
4713 p_def_var_template->get_my_scope()->get_fullname().c_str());
4714 p_def_var_template->note("The inherited template variable `%s' is here",
4715 dispname_str);
4716 }
4717 } else if (p_def_var_template->initial_value) {
4718 const char *dispname_str = id->get_dispname().c_str();
4719 warning("Local template variable `%s' does not have initial value, but "
4720 "the template variable inherited from component type `%s' has",
4721 dispname_str,
4722 p_def_var_template->get_my_scope()->get_fullname().c_str());
4723 p_def_var_template->note("The inherited template variable `%s' is here",
4724 dispname_str);
4725 }
4726 return true;
4727 }
4728
4729 void Def_Var_Template::generate_code(output_struct *target, bool clean_up)
4730 {
4731 type->generate_code(target);
4732 const_def cdef;
4733 Code::init_cdef(&cdef);
4734 type->generate_code_object(&cdef, my_scope, get_genname(), 0, true);
4735 Code::merge_cdef(target, &cdef);
4736 Code::free_cdef(&cdef);
4737 if (initial_value) {
4738 if (Common::Type::T_SEQOF == initial_value->get_my_governor()->get_typetype() ||
4739 Common::Type::T_ARRAY == initial_value->get_my_governor()->get_typetype()) {
4740 target->functions.init_comp = mputprintf(target->functions.init_comp,
4741 "%s.remove_all_permutations();\n", initial_value->get_lhs_name().c_str());
4742 }
4743 target->functions.init_comp =
4744 initial_value->generate_code_init(target->functions.init_comp,
4745 initial_value->get_lhs_name().c_str());
4746 if (template_restriction!=TR_NONE && gen_restriction_check)
4747 target->functions.init_comp = Template::generate_restriction_check_code(
4748 target->functions.init_comp, initial_value->get_lhs_name().c_str(),
4749 template_restriction);
4750 } else if (clean_up) { // No initial value.
4751 // Always reset component variables/variable templates on component
4752 // reinitialization. Fix for HM79493.
4753 target->functions.init_comp = mputprintf(target->functions.init_comp,
4754 "%s.clean_up();\n", get_genname().c_str());
4755 }
4756 }
4757
4758 void Def_Var_Template::generate_code(CodeGenHelper& cgh)
4759 {
4760 generate_code(cgh.get_outputstruct(this));
4761 }
4762
4763 char *Def_Var_Template::generate_code_str(char *str)
4764 {
4765 const string& t_genname = get_genname();
4766 const char *genname_str = t_genname.c_str();
4767 if (initial_value && initial_value->has_single_expr()) {
4768 // The initial value can be represented by a single C++ expression
4769 // the object is initialized by the constructor.
4770 str = mputprintf(str, "%s %s(%s);\n",
4771 type->get_genname_template(my_scope).c_str(), genname_str,
4772 initial_value->get_single_expr(false).c_str());
4773 } else {
4774 // Use the default constructor.
4775 str = mputprintf(str, "%s %s;\n",
4776 type->get_genname_template(my_scope).c_str(), genname_str);
4777 if (initial_value) {
4778 // The initial value is assigned using subsequent statements.
4779 if (use_runtime_2 && TypeConv::needs_conv_refd(initial_value))
4780 str = TypeConv::gen_conv_code_refd(str, genname_str, initial_value);
4781 else str = initial_value->generate_code_init(str, genname_str);
4782 }
4783 }
4784 if (initial_value && template_restriction != TR_NONE
4785 && gen_restriction_check)
4786 str = Template::generate_restriction_check_code(str, genname_str,
4787 template_restriction);
4788 return str;
4789 }
4790
4791 void Def_Var_Template::ilt_generate_code(ILT *ilt)
4792 {
4793 const string& t_genname = get_genname();
4794 const char *genname_str = t_genname.c_str();
4795 char*& def=ilt->get_out_def();
4796 char*& init=ilt->get_out_branches();
4797 def = mputprintf(def, "%s %s;\n",
4798 type->get_genname_template(my_scope).c_str(), genname_str);
4799 if (initial_value) {
4800 init = initial_value->generate_code_init(init, genname_str);
4801 if (template_restriction!=TR_NONE && gen_restriction_check)
4802 init = Template::generate_restriction_check_code(init, genname_str,
4803 template_restriction);
4804 }
4805 }
4806
4807 char *Def_Var_Template::generate_code_init_comp(char *str,
4808 Definition *base_defn)
4809 {
4810 if (initial_value) {
4811 str = initial_value->generate_code_init(str,
4812 base_defn->get_genname_from_scope(my_scope).c_str());
4813 if (template_restriction != TR_NONE && gen_restriction_check)
4814 str = Template::generate_restriction_check_code(str,
4815 base_defn->get_genname_from_scope(my_scope).c_str(),
4816 template_restriction);
4817 }
4818 return str;
4819 }
4820
4821 void Def_Var_Template::dump_internal(unsigned level) const
4822 {
4823 DEBUG(level, "Template variable %s", id->get_dispname().c_str());
4824 if (template_restriction!=TR_NONE)
4825 DEBUG(level + 1, "restriction: %s",
4826 Template::get_restriction_name(template_restriction));
4827 type->dump(level + 1);
4828 if (initial_value) initial_value->dump(level + 1);
4829 }
4830
4831 // =================================
4832 // ===== Def_Timer
4833 // =================================
4834
4835 Def_Timer::~Def_Timer()
4836 {
4837 delete dimensions;
4838 delete default_duration;
4839 }
4840
4841 Def_Timer *Def_Timer::clone() const
4842 {
4843 FATAL_ERROR("Def_Timer::clone");
4844 }
4845
4846 void Def_Timer::set_fullname(const string& p_fullname)
4847 {
4848 Definition::set_fullname(p_fullname);
4849 if (dimensions) dimensions->set_fullname(p_fullname + ".<dimensions>");
4850 if (default_duration)
4851 default_duration->set_fullname(p_fullname + ".<default_duration>");
4852 }
4853
4854 void Def_Timer::set_my_scope(Scope *p_scope)
4855 {
4856 Definition::set_my_scope(p_scope);
4857 if (dimensions) dimensions->set_my_scope(p_scope);
4858 if (default_duration) default_duration->set_my_scope(p_scope);
4859 }
4860
4861 ArrayDimensions *Def_Timer::get_Dimensions()
4862 {
4863 if (!checked) chk();
4864 return dimensions;
4865 }
4866
4867 void Def_Timer::chk()
4868 {
4869 if(checked) return;
4870 Error_Context cntxt(this, "In timer definition `%s'",
4871 id->get_dispname().c_str());
4872 if (dimensions) dimensions->chk();
4873 if (default_duration) {
4874 Error_Context cntxt2(default_duration, "In default duration");
4875 if (dimensions) chk_array_duration(default_duration);
4876 else chk_single_duration(default_duration);
4877 if (!semantic_check_only) {
4878 default_duration->set_code_section(GovernedSimple::CS_POST_INIT);
4879 }
4880 }
4881 checked = true;
4882 if (w_attrib_path) {
4883 w_attrib_path->chk_global_attrib();
4884 w_attrib_path->chk_no_qualif();
4885 }
4886 }
4887
4888 bool Def_Timer::chk_identical(Definition *p_def)
4889 {
4890 chk();
4891 p_def->chk();
4892 if (p_def->get_asstype() != A_TIMER) {
4893 const char *dispname_str = id->get_dispname().c_str();
4894 error("Local definition `%s' is a timer, but the definition inherited "
4895 "from component type `%s' is a %s", dispname_str,
4896 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
4897 p_def->note("The inherited definition of `%s' is here", dispname_str);
4898 return false;
4899 }
4900 Def_Timer *p_def_timer = dynamic_cast<Def_Timer*>(p_def);
4901 if (!p_def_timer) FATAL_ERROR("Def_Timer::chk_identical()");
4902 if (dimensions) {
4903 if (p_def_timer->dimensions) {
4904 if (!dimensions->is_identical(p_def_timer->dimensions)) {
4905 const char *dispname_str = id->get_dispname().c_str();
4906 error("Local timer `%s' and the timer inherited from component type "
4907 "`%s' have different array dimensions", dispname_str,
4908 p_def_timer->get_my_scope()->get_fullname().c_str());
4909 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4910 return false;
4911 }
4912 } else {
4913 const char *dispname_str = id->get_dispname().c_str();
4914 error("Local definition `%s' is a timer array, but the definition "
4915 "inherited from component type `%s' is a single timer", dispname_str,
4916 p_def_timer->get_my_scope()->get_fullname().c_str());
4917 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4918 return false;
4919 }
4920 } else if (p_def_timer->dimensions) {
4921 const char *dispname_str = id->get_dispname().c_str();
4922 error("Local definition `%s' is a single timer, but the definition "
4923 "inherited from component type `%s' is a timer array", dispname_str,
4924 p_def_timer->get_my_scope()->get_fullname().c_str());
4925 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4926 return false;
4927 }
4928 if (default_duration) {
4929 if (p_def_timer->default_duration) {
4930 if (!default_duration->is_unfoldable() &&
4931 !p_def_timer->default_duration->is_unfoldable() &&
4932 !(*default_duration == *p_def_timer->default_duration)) {
4933 const char *dispname_str = id->get_dispname().c_str();
4934 default_duration->warning("Local timer `%s' and the timer inherited "
4935 "from component type `%s' have different default durations",
4936 dispname_str, p_def_timer->get_my_scope()->get_fullname().c_str());
4937 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4938 }
4939 } else {
4940 const char *dispname_str = id->get_dispname().c_str();
4941 default_duration->error("Local timer `%s' has default duration, but "
4942 "the timer inherited from component type `%s' does not", dispname_str,
4943 p_def_timer->get_my_scope()->get_fullname().c_str());
4944 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4945 return false;
4946 }
4947 } else if (p_def_timer->default_duration) {
4948 const char *dispname_str = id->get_dispname().c_str();
4949 error("Local timer `%s' does not have default duration, but the timer "
4950 "inherited from component type `%s' has", dispname_str,
4951 p_def_timer->get_my_scope()->get_fullname().c_str());
4952 p_def_timer->note("The inherited timer `%s' is here", dispname_str);
4953 return false;
4954 }
4955 return true;
4956 }
4957
4958 bool Def_Timer::has_default_duration(FieldOrArrayRefs *p_subrefs)
4959 {
4960 // return true in case of any uncertainity
4961 if (!default_duration) return false;
4962 else if (!dimensions || !p_subrefs) return true;
4963 Value *v = default_duration;
4964 size_t nof_dims = dimensions->get_nof_dims();
4965 size_t nof_refs = p_subrefs->get_nof_refs();
4966 size_t upper_limit = nof_dims < nof_refs ? nof_dims : nof_refs;
4967 for (size_t i = 0; i < upper_limit; i++) {
4968 v = v->get_value_refd_last();
4969 if (v->get_valuetype() != Value::V_SEQOF) break;
4970 FieldOrArrayRef *ref = p_subrefs->get_ref(i);
4971 if (ref->get_type() != FieldOrArrayRef::ARRAY_REF) return true;
4972 Value *v_index = ref->get_val()->get_value_refd_last();
4973 if (v_index->get_valuetype() != Value::V_INT) return true;
4974 Int index = v_index->get_val_Int()->get_val()
4975 - dimensions->get_dim_byIndex(i)->get_offset();
4976 if (index >= 0 && index < static_cast<Int>(v->get_nof_comps()))
4977 v = v->get_comp_byIndex(index);
4978 else return true;
4979 }
4980 return v->get_valuetype() != Value::V_NOTUSED;
4981 }
4982
4983 void Def_Timer::chk_single_duration(Value *dur)
4984 {
4985 dur->chk_expr_float(is_local() ?
4986 Type::EXPECTED_DYNAMIC_VALUE : Type::EXPECTED_STATIC_VALUE);
4987 Value *v = dur->get_value_refd_last();
4988 if (v->get_valuetype() == Value::V_REAL) {
4989 ttcn3float v_real = v->get_val_Real();
4990 if ( (v_real<0.0) || isSpecialFloatValue(v_real) ) {
4991 dur->error("A non-negative float value was expected "
4992 "as timer duration instead of `%s'", Real2string(v_real).c_str());
4993 }
4994 }
4995 }
4996
4997 void Def_Timer::chk_array_duration(Value *dur, size_t start_dim)
4998 {
4999 ArrayDimension *dim = dimensions->get_dim_byIndex(start_dim);
5000 bool array_size_known = !dim->get_has_error();
5001 size_t array_size = 0;
5002 if (array_size_known) array_size = dim->get_size();
5003 Value *v = dur->get_value_refd_last();
5004 switch (v->get_valuetype()) {
5005 case Value::V_ERROR:
5006 return;
5007 case Value::V_SEQOF: {
5008 size_t nof_vs = v->get_nof_comps();
5009 // Value-list notation.
5010 if (!v->is_indexed()) {
5011 if (array_size_known) {
5012 if (array_size > nof_vs) {
5013 dur->error("Too few elements in the default duration of timer "
5014 "array: %lu was expected instead of %lu",
5015 (unsigned long)array_size, (unsigned long)nof_vs);
5016 } else if (array_size < nof_vs) {
5017 dur->error("Too many elements in the default duration of timer "
5018 "array: %lu was expected instead of %lu",
5019 (unsigned long)array_size, (unsigned long)nof_vs);
5020 }
5021 }
5022 bool last_dimension = start_dim + 1 >= dimensions->get_nof_dims();
5023 for (size_t i = 0; i < nof_vs; i++) {
5024 Value *array_v = v->get_comp_byIndex(i);
5025 if (array_v->get_valuetype() == Value::V_NOTUSED) continue;
5026 if (last_dimension) chk_single_duration(array_v);
5027 else chk_array_duration(array_v, start_dim + 1);
5028 }
5029 } else {
5030 // Indexed-notation.
5031 bool last_dimension = start_dim + 1 >= dimensions->get_nof_dims();
5032 map<Int, Int> index_map;
5033 for (size_t i = 0; i < nof_vs; i++) {
5034 Value *array_v = v->get_comp_byIndex(i);
5035 if (array_v->get_valuetype() == Value::V_NOTUSED) continue;
5036 if (last_dimension) chk_single_duration(array_v);
5037 else chk_array_duration(array_v, start_dim + 1);
5038 Error_Context cntxt(this, "In timer array element %lu",
5039 (unsigned long)(i + 1));
5040 Value *index = v->get_index_byIndex(i);
5041 dim->chk_index(index, Type::EXPECTED_DYNAMIC_VALUE);
5042 if (index->get_value_refd_last()->get_valuetype() == Value::V_INT) {
5043 const int_val_t *index_int = index->get_value_refd_last()
5044 ->get_val_Int();
5045 if (*index_int > INT_MAX) {
5046 index->error("An integer value less than `%d' was expected for "
5047 "indexing timer array instead of `%s'", INT_MAX,
5048 (index_int->t_str()).c_str());
5049 index->set_valuetype(Value::V_ERROR);
5050 } else {
5051 Int index_val = index_int->get_val();
5052 if (index_map.has_key(index_val)) {
5053 index->error("Duplicate index value `%s' for timer array "
5054 "elements `%s' and `%s'",
5055 Int2string(index_val).c_str(),
5056 Int2string((Int)i + 1).c_str(),
5057 Int2string(*index_map[index_val]).c_str());
5058 index->set_valuetype(Value::V_ERROR);
5059 } else {
5060 index_map.add(index_val, new Int((Int)i + 1));
5061 }
5062 }
5063 }
5064 }
5065 // It's not possible to have "index_map.size() > array_size", since we
5066 // add only correct constant-index values into the map. It's possible
5067 // to create partially initialized timer arrays.
5068 for (size_t i = 0; i < index_map.size(); i++)
5069 delete index_map.get_nth_elem(i);
5070 index_map.clear();
5071 }
5072 break; }
5073 default:
5074 if (array_size_known) {
5075 dur->error("An array value (with %lu elements) was expected as "
5076 "default duration of timer array",
5077 (unsigned long)array_size);
5078 } else {
5079 dur->error("An array value was expected as default duration of timer "
5080 "array");
5081 }
5082 dur->set_valuetype(Value::V_ERROR);
5083 return;
5084 }
5085 }
5086
5087 void Def_Timer::generate_code(output_struct *target, bool)
5088 {
5089 const string& t_genname = get_genname();
5090 const char *genname_str = t_genname.c_str();
5091 const string& dispname = id->get_dispname();
5092 if (dimensions) {
5093 // timer array
5094 const string& array_type = dimensions->get_timer_type();
5095 const char *array_type_str = array_type.c_str();
5096 target->header.global_vars = mputprintf(target->header.global_vars,
5097 "extern %s %s;\n", array_type_str, genname_str);
5098 target->source.global_vars = mputprintf(target->source.global_vars,
5099 "%s %s;\n", array_type_str, genname_str);
5100 target->functions.pre_init = mputstr(target->functions.pre_init, "{\n"
5101 "static const char * const timer_name = \"");
5102 target->functions.pre_init = mputstr(target->functions.pre_init,
5103 dispname.c_str());
5104 target->functions.pre_init = mputprintf(target->functions.pre_init,
5105 "\";\n"
5106 "%s.set_name(timer_name);\n"
5107 "}\n", genname_str);
5108 if (default_duration) target->functions.post_init =
5109 generate_code_array_duration(target->functions.post_init, genname_str,
5110 default_duration);
5111 } else {
5112 // single timer
5113 target->header.global_vars = mputprintf(target->header.global_vars,
5114 "extern TIMER %s;\n", genname_str);
5115 if (default_duration) {
5116 // has default duration
5117 Value *v = default_duration->get_value_refd_last();
5118 if (v->get_valuetype() == Value::V_REAL) {
5119 // duration is known at compilation time -> set in the constructor
5120 target->source.global_vars = mputprintf(target->source.global_vars,
5121 "TIMER %s(\"%s\", %s);\n", genname_str, dispname.c_str(),
5122 v->get_single_expr().c_str());
5123 } else {
5124 // duration is known only at runtime -> set in post_init
5125 target->source.global_vars = mputprintf(target->source.global_vars,
5126 "TIMER %s(\"%s\");\n", genname_str, dispname.c_str());
5127 expression_struct expr;
5128 Code::init_expr(&expr);
5129 expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
5130 genname_str);
5131 default_duration->generate_code_expr(&expr);
5132 expr.expr = mputc(expr.expr, ')');
5133 target->functions.post_init =
5134 Code::merge_free_expr(target->functions.post_init, &expr);
5135 }
5136 } else {
5137 // does not have default duration
5138 target->source.global_vars = mputprintf(target->source.global_vars,
5139 "TIMER %s(\"%s\");\n", genname_str, dispname.c_str());
5140 }
5141 }
5142 }
5143
5144 void Def_Timer::generate_code(CodeGenHelper& cgh) {
5145 generate_code(cgh.get_current_outputstruct());
5146 }
5147
5148 char *Def_Timer::generate_code_array_duration(char *str,
5149 const char *object_name, Value *dur, size_t start_dim)
5150 {
5151 ArrayDimension *dim = dimensions->get_dim_byIndex(start_dim);
5152 size_t dim_size = dim->get_size();
5153 Value *v = dur->get_value_refd_last();
5154 if (v->get_valuetype() != Value::V_SEQOF
5155 || (v->get_nof_comps() != dim_size && !v->is_indexed()))
5156 FATAL_ERROR("Def_Timer::generate_code_array_duration()");
5157 // Value-list notation.
5158 if (!v->is_indexed()) {
5159 if (start_dim + 1 < dimensions->get_nof_dims()) {
5160 // There are more dimensions, the elements of "v" are arrays a
5161 // temporary reference shall be introduced if the next dimension has
5162 // more than 1 elements.
5163 bool temp_ref_needed =
5164 dimensions->get_dim_byIndex(start_dim + 1)->get_size() > 1;
5165 for (size_t i = 0; i < dim_size; i++) {
5166 Value *v_elem = v->get_comp_byIndex(i);
5167 if (v_elem->get_valuetype() == Value::V_NOTUSED) continue;
5168 if (temp_ref_needed) {
5169 const string& tmp_id = my_scope->get_scope_mod_gen()
5170 ->get_temporary_id();
5171 const char *tmp_str = tmp_id.c_str();
5172 str = mputprintf(str, "{\n"
5173 "%s& %s = %s.array_element(%lu);\n",
5174 dimensions->get_timer_type(start_dim + 1).c_str(),
5175 tmp_str, object_name, (unsigned long)i);
5176 str = generate_code_array_duration(str, tmp_str, v_elem,
5177 start_dim + 1);
5178 str = mputstr(str, "}\n");
5179 } else {
5180 char *tmp_str = mprintf("%s.array_element(%lu)", object_name,
5181 (unsigned long)i);
5182 str = generate_code_array_duration(str, tmp_str, v_elem,
5183 start_dim + 1);
5184 Free(tmp_str);
5185 }
5186 }
5187 } else {
5188 // We are in the last dimension, the elements of "v" are floats.
5189 for (size_t i = 0; i < dim_size; i++) {
5190 Value *v_elem = v->get_comp_byIndex(i);
5191 if (v_elem->get_valuetype() == Value::V_NOTUSED) continue;
5192 expression_struct expr;
5193 Code::init_expr(&expr);
5194 expr.expr = mputprintf(expr.expr,
5195 "%s.array_element(%lu).set_default_duration(",
5196 object_name, (unsigned long)i);
5197 v_elem->generate_code_expr(&expr);
5198 expr.expr = mputc(expr.expr, ')');
5199 str = Code::merge_free_expr(str, &expr);
5200 }
5201 }
5202 // Indexed-list notation.
5203 } else {
5204 if (start_dim + 1 < dimensions->get_nof_dims()) {
5205 bool temp_ref_needed =
5206 dimensions->get_dim_byIndex(start_dim + 1)->get_size() > 1;
5207 for (size_t i = 0; i < v->get_nof_comps(); i++) {
5208 Value *v_elem = v->get_comp_byIndex(i);
5209 if (v_elem->get_valuetype() == Value::V_NOTUSED) continue;
5210 if (temp_ref_needed) {
5211 const string& tmp_id = my_scope->get_scope_mod_gen()
5212 ->get_temporary_id();
5213 const string& idx_id = my_scope->get_scope_mod_gen()
5214 ->get_temporary_id();
5215 const char *tmp_str = tmp_id.c_str();
5216 str = mputstr(str, "{\n");
5217 str = mputprintf(str, "int %s;\n", idx_id.c_str());
5218 str = v->get_index_byIndex(i)->generate_code_init(str,
5219 idx_id.c_str());
5220 str = mputprintf(str, "%s& %s = %s.array_element(%s);\n",
5221 dimensions->get_timer_type(start_dim + 1).c_str(),
5222 tmp_str, object_name, idx_id.c_str());
5223 str = generate_code_array_duration(str, tmp_str, v_elem,
5224 start_dim + 1);
5225 str = mputstr(str, "}\n");
5226 } else {
5227 const string& idx_id = my_scope->get_scope_mod_gen()
5228 ->get_temporary_id();
5229 str = mputstr(str, "{\n");
5230 str = mputprintf(str, "int %s;\n", idx_id.c_str());
5231 str = v->get_index_byIndex(i)->generate_code_init(str,
5232 idx_id.c_str());
5233 char *tmp_str = mprintf("%s.array_element(%s)", object_name,
5234 idx_id.c_str());
5235 str = generate_code_array_duration(str, tmp_str, v_elem,
5236 start_dim + 1);
5237 str = mputstr(str, "}\n");
5238 Free(tmp_str);
5239 }
5240 }
5241 } else {
5242 for (size_t i = 0; i < v->get_nof_comps(); i++) {
5243 Value *v_elem = v->get_comp_byIndex(i);
5244 if (v_elem->get_valuetype() == Value::V_NOTUSED) continue;
5245 expression_struct expr;
5246 Code::init_expr(&expr);
5247 str = mputstr(str, "{\n");
5248 const string& idx_id = my_scope->get_scope_mod_gen()
5249 ->get_temporary_id();
5250 str = mputprintf(str, "int %s;\n", idx_id.c_str());
5251 str = v->get_index_byIndex(i)->generate_code_init(str,
5252 idx_id.c_str());
5253 str = mputprintf(str,
5254 "%s.array_element(%s).set_default_duration(",
5255 object_name, idx_id.c_str());
5256 v_elem->generate_code_expr(&expr);
5257 expr.expr = mputc(expr.expr, ')');
5258 str = Code::merge_free_expr(str, &expr);
5259 str = mputstr(str, "}\n");
5260 }
5261 }
5262 }
5263 return str;
5264 }
5265
5266 char *Def_Timer::generate_code_str(char *str)
5267 {
5268 const string& t_genname = get_genname();
5269 const char *genname_str = t_genname.c_str();
5270 const string& dispname = id->get_dispname();
5271 if (dimensions) {
5272 // timer array
5273 const string& array_type = dimensions->get_timer_type();
5274 const char *array_type_str = array_type.c_str();
5275 str = mputprintf(str, "%s %s;\n", array_type_str, genname_str);
5276 str = mputstr(str, "{\n"
5277 "static const char * const timer_name = \"");
5278 str = mputstr(str, dispname.c_str());
5279 str = mputprintf(str, "\";\n"
5280 "%s.set_name(timer_name);\n"
5281 "}\n", genname_str);
5282 if (default_duration) str = generate_code_array_duration(str,
5283 genname_str, default_duration);
5284 } else {
5285 // single timer
5286 if (default_duration && default_duration->has_single_expr()) {
5287 // the default duration can be passed to the constructor
5288 str = mputprintf(str, "TIMER %s(\"%s\", %s);\n", genname_str,
5289 dispname.c_str(), default_duration->get_single_expr().c_str());
5290 } else {
5291 // only the name is passed to the constructor
5292 str = mputprintf(str, "TIMER %s(\"%s\");\n", genname_str,
5293 dispname.c_str());
5294 if (default_duration) {
5295 // the default duration is set explicitly
5296 expression_struct expr;
5297 Code::init_expr(&expr);
5298 expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
5299 genname_str);
5300 default_duration->generate_code_expr(&expr);
5301 expr.expr = mputc(expr.expr, ')');
5302 str = Code::merge_free_expr(str, &expr);
5303 }
5304 }
5305 }
5306 return str;
5307 }
5308
5309 void Def_Timer::ilt_generate_code(ILT *ilt)
5310 {
5311 const string& t_genname = get_genname();
5312 const char *genname_str = t_genname.c_str();
5313 const string& dispname = id->get_dispname();
5314
5315 char*& def = ilt->get_out_def();
5316 char*& init = ilt->get_out_branches();
5317
5318 if (dimensions) {
5319 // timer array
5320 const string& array_type = dimensions->get_timer_type();
5321 const char *array_type_str = array_type.c_str();
5322 def = mputprintf(def, "%s %s;\n", array_type_str, genname_str);
5323 def = mputstr(def, "{\n"
5324 "static const char * const timer_names[] = { ");
5325 def = dimensions->generate_element_names(def, dispname);
5326 def = mputprintf(def, " };\n"
5327 "%s.set_name(%lu, timer_names);\n"
5328 "}\n", genname_str, (unsigned long) dimensions->get_array_size());
5329 if (default_duration) init = generate_code_array_duration(init,
5330 genname_str, default_duration);
5331 } else {
5332 // single timer
5333 if (default_duration) {
5334 // has default duration
5335 Value *v = default_duration->get_value_refd_last();
5336 if (v->get_valuetype() == Value::V_REAL) {
5337 // duration is known at compilation time -> set in the constructor
5338 def = mputprintf(def, "TIMER %s(\"%s\", %s);\n", genname_str,
5339 dispname.c_str(), v->get_single_expr().c_str());
5340 } else {
5341 // duration is known only at runtime -> set when control reaches the
5342 // timer definition
5343 def = mputprintf(def, "TIMER %s(\"%s\");\n", genname_str,
5344 dispname.c_str());
5345 expression_struct expr;
5346 Code::init_expr(&expr);
5347 expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
5348 genname_str);
5349 default_duration->generate_code_expr(&expr);
5350 expr.expr = mputc(expr.expr, ')');
5351 init = Code::merge_free_expr(init, &expr);
5352 }
5353 } else {
5354 // does not have default duration
5355 def = mputprintf(def, "TIMER %s(\"%s\");\n", genname_str,
5356 dispname.c_str());
5357 }
5358 }
5359 }
5360
5361 char *Def_Timer::generate_code_init_comp(char *str, Definition *base_defn)
5362 {
5363 if (default_duration) {
5364 Def_Timer *base_timer_defn = dynamic_cast<Def_Timer*>(base_defn);
5365 if (!base_timer_defn || !base_timer_defn->default_duration)
5366 FATAL_ERROR("Def_Timer::generate_code_init_comp()");
5367 // initializer is not needed if the default durations are the same
5368 // constants in both timers
5369 if (default_duration->is_unfoldable() ||
5370 base_timer_defn->default_duration->is_unfoldable() ||
5371 !(*default_duration == *base_timer_defn->default_duration)) {
5372 if (dimensions) {
5373 str = generate_code_array_duration(str,
5374 base_timer_defn->get_genname_from_scope(my_scope).c_str(),
5375 default_duration);
5376 } else {
5377 expression_struct expr;
5378 Code::init_expr(&expr);
5379 expr.expr = mputprintf(expr.expr, "%s.set_default_duration(",
5380 base_timer_defn->get_genname_from_scope(my_scope).c_str());
5381 default_duration->generate_code_expr(&expr);
5382 expr.expr = mputc(expr.expr, ')');
5383 str = Code::merge_free_expr(str, &expr);
5384 }
5385 }
5386 }
5387 return str;
5388 }
5389
5390 void Def_Timer::dump_internal(unsigned level) const
5391 {
5392 DEBUG(level, "Timer: %s", id->get_dispname().c_str());
5393 if (dimensions) dimensions->dump(level + 1);
5394 if (default_duration) {
5395 DEBUG(level + 1, "Default duration:");
5396 default_duration->dump(level + 1);
5397 }
5398 }
5399
5400 // =================================
5401 // ===== Def_Port
5402 // =================================
5403
5404 Def_Port::Def_Port(Identifier *p_id, Reference *p_tref,
5405 ArrayDimensions *p_dims)
5406 : Definition(A_PORT, p_id), type_ref(p_tref), port_type(0),
5407 dimensions(p_dims)
5408 {
5409 if (!p_tref) FATAL_ERROR("Def_Port::Def_Port()");
5410 }
5411
5412 Def_Port::~Def_Port()
5413 {
5414 delete type_ref;
5415 delete dimensions;
5416 }
5417
5418 Def_Port *Def_Port::clone() const
5419 {
5420 FATAL_ERROR("Def_Port::clone");
5421 }
5422
5423 void Def_Port::set_fullname(const string& p_fullname)
5424 {
5425 Definition::set_fullname(p_fullname);
5426 type_ref->set_fullname(p_fullname + ".<type_ref>");
5427 if (dimensions) dimensions->set_fullname(p_fullname);
5428 }
5429
5430 void Def_Port::set_my_scope(Scope *p_scope)
5431 {
5432 Definition::set_my_scope(p_scope);
5433 type_ref->set_my_scope(p_scope);
5434 if (dimensions) dimensions->set_my_scope(p_scope);
5435 }
5436
5437 Type *Def_Port::get_Type()
5438 {
5439 chk();
5440 return port_type;
5441 }
5442
5443 ArrayDimensions *Def_Port::get_Dimensions()
5444 {
5445 if (!checked) chk();
5446 return dimensions;
5447 }
5448
5449 void Def_Port::chk()
5450 {
5451 if (checked) return;
5452 checked = true;
5453 Error_Context cntxt(this, "In port definition `%s'",
5454 id->get_dispname().c_str());
5455 Common::Assignment *ass = type_ref->get_refd_assignment();
5456 if (ass) {
5457 if (ass->get_asstype() == A_TYPE) {
5458 Type *t = ass->get_Type()->get_type_refd_last();
5459 if (t->get_typetype() == Type::T_PORT) port_type = t;
5460 else type_ref->error("Type reference `%s' does not refer to a "
5461 "port type", type_ref->get_dispname().c_str());
5462 } else type_ref->error("Reference `%s' does not refer to a "
5463 "type", type_ref->get_dispname().c_str());
5464 }
5465 if (dimensions) dimensions->chk();
5466 if (w_attrib_path) {
5467 w_attrib_path->chk_global_attrib();
5468 w_attrib_path->chk_no_qualif();
5469 }
5470 }
5471
5472 bool Def_Port::chk_identical(Definition *p_def)
5473 {
5474 chk();
5475 p_def->chk();
5476 if (p_def->get_asstype() != A_PORT) {
5477 const char *dispname_str = id->get_dispname().c_str();
5478 error("Local definition `%s' is a port, but the definition inherited "
5479 "from component type `%s' is a %s", dispname_str,
5480 p_def->get_my_scope()->get_fullname().c_str(), p_def->get_assname());
5481 p_def->note("The inherited definition of `%s' is here", dispname_str);
5482 return false;
5483 }
5484 Def_Port *p_def_port = dynamic_cast<Def_Port*>(p_def);
5485 if (!p_def_port) FATAL_ERROR("Def_Port::chk_identical()");
5486 if (port_type && p_def_port->port_type &&
5487 port_type != p_def_port->port_type) {
5488 const char *dispname_str = id->get_dispname().c_str();
5489 type_ref->error("Local port `%s' has type `%s', but the port inherited "
5490 "from component type `%s' has type `%s'", dispname_str,
5491 port_type->get_typename().c_str(),
5492 p_def_port->get_my_scope()->get_fullname().c_str(),
5493 p_def_port->port_type->get_typename().c_str());
5494 p_def_port->note("The inherited port `%s' is here", dispname_str);
5495 return false;
5496 }
5497 if (dimensions) {
5498 if (p_def_port->dimensions) {
5499 if (!dimensions->is_identical(p_def_port->dimensions)) {
5500 const char *dispname_str = id->get_dispname().c_str();
5501 error("Local port `%s' and the port inherited from component type "
5502 "`%s' have different array dimensions", dispname_str,
5503 p_def_port->get_my_scope()->get_fullname().c_str());
5504 p_def_port->note("The inherited port `%s' is here", dispname_str);
5505 return false;
5506 }
5507 } else {
5508 const char *dispname_str = id->get_dispname().c_str();
5509 error("Local definition `%s' is a port array, but the definition "
5510 "inherited from component type `%s' is a single port", dispname_str,
5511 p_def_port->get_my_scope()->get_fullname().c_str());
5512 p_def_port->note("The inherited port `%s' is here", dispname_str);
5513 return false;
5514 }
5515 } else if (p_def_port->dimensions) {
5516 const char *dispname_str = id->get_dispname().c_str();
5517 error("Local definition `%s' is a single port, but the definition "
5518 "inherited from component type `%s' is a port array", dispname_str,
5519 p_def_port->get_my_scope()->get_fullname().c_str());
5520 p_def_port->note("The inherited port `%s' is here", dispname_str);
5521 return false;
5522 }
5523 return true;
5524 }
5525
5526 void Def_Port::generate_code(output_struct *target, bool)
5527 {
5528 const string& t_genname = get_genname();
5529 const char *genname_str = t_genname.c_str();
5530 const string& type_genname = port_type->get_genname_value(my_scope);
5531 const string& dispname = id->get_dispname();
5532 if (dimensions) {
5533 // port array
5534 const string& array_type = dimensions->get_port_type(type_genname);
5535 const char *array_type_str = array_type.c_str();
5536 target->header.global_vars = mputprintf(target->header.global_vars,
5537 "extern %s %s;\n", array_type_str, genname_str);
5538 target->source.global_vars = mputprintf(target->source.global_vars,
5539 "%s %s;\n", array_type_str, genname_str);
5540 target->functions.pre_init = mputstr(target->functions.pre_init, "{\n"
5541 "static const char * const port_name = \"");
5542 target->functions.pre_init = mputstr(target->functions.pre_init,
5543 dispname.c_str());
5544 target->functions.pre_init = mputprintf(target->functions.pre_init,
5545 "\";\n"
5546 "%s.set_name(port_name);\n"
5547 "}\n", genname_str);
5548 } else {
5549 // single port
5550 const char *type_genname_str = type_genname.c_str();
5551 target->header.global_vars = mputprintf(target->header.global_vars,
5552 "extern %s %s;\n", type_genname_str, genname_str);
5553 target->source.global_vars = mputprintf(target->source.global_vars,
5554 "%s %s(\"%s\");\n", type_genname_str, genname_str, dispname.c_str());
5555 }
5556 target->functions.init_comp = mputprintf(target->functions.init_comp,
5557 "%s.activate_port();\n", genname_str);
5558 }
5559
5560 void Def_Port::generate_code(CodeGenHelper& cgh) {
5561 generate_code(cgh.get_current_outputstruct());
5562 }
5563
5564 char *Def_Port::generate_code_init_comp(char *str, Definition *base_defn)
5565 {
5566 return mputprintf(str, "%s.activate_port();\n",
5567 base_defn->get_genname_from_scope(my_scope).c_str());
5568 }
5569
5570 void Def_Port::dump_internal(unsigned level) const
5571 {
5572 DEBUG(level, "Port: %s", id->get_dispname().c_str());
5573 DEBUG(level + 1, "Port type:");
5574 type_ref->dump(level + 2);
5575 if (dimensions) dimensions->dump(level + 1);
5576 }
5577
5578 // =================================
5579 // ===== Def_Function_Base
5580 // =================================
5581
5582 Def_Function_Base::asstype_t Def_Function_Base::determine_asstype(
5583 bool is_external, bool has_return_type, bool returns_template)
5584 {
5585 if (is_external) {
5586 if (has_return_type) {
5587 if (returns_template) return A_EXT_FUNCTION_RTEMP;
5588 else return A_EXT_FUNCTION_RVAL;
5589 } else {
5590 if (returns_template)
5591 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5592 return A_EXT_FUNCTION;
5593 }
5594 } else { // not an external function
5595 if (has_return_type) {
5596 if (returns_template) return A_FUNCTION_RTEMP;
5597 else return A_FUNCTION_RVAL;
5598 } else {
5599 if (returns_template)
5600 FATAL_ERROR("Def_Function_Base::determine_asstype()");
5601 return A_FUNCTION;
5602 }
5603 }
5604 }
5605
5606 Def_Function_Base::Def_Function_Base(const Def_Function_Base& p)
5607 : Definition(p), prototype(PROTOTYPE_NONE), input_type(0), output_type(0)
5608 {
5609 fp_list = p.fp_list->clone();
5610 fp_list->set_my_def(this);
5611 return_type = p.return_type ? p.return_type->clone() : 0;
5612 template_restriction = p.template_restriction;
5613 }
5614
5615 Def_Function_Base::Def_Function_Base(bool is_external, Identifier *p_id,
5616 FormalParList *p_fpl, Type *p_return_type, bool returns_template,
5617 template_restriction_t p_template_restriction)
5618 : Definition(determine_asstype(is_external, p_return_type != 0,
5619 returns_template), p_id), fp_list(p_fpl), return_type(p_return_type),
5620 prototype(PROTOTYPE_NONE), input_type(0), output_type(0),
5621 template_restriction(p_template_restriction)
5622 {
5623 if (!p_fpl) FATAL_ERROR("Def_Function_Base::Def_Function_Base()");
5624 fp_list->set_my_def(this);
5625 if (return_type) return_type->set_ownertype(Type::OT_FUNCTION_DEF, this);
5626 }
5627
5628 Def_Function_Base::~Def_Function_Base()
5629 {
5630 delete fp_list;
5631 delete return_type;
5632 }
5633
5634 void Def_Function_Base::set_fullname(const string& p_fullname)
5635 {
5636 Definition::set_fullname(p_fullname);
5637 fp_list->set_fullname(p_fullname + ".<formal_par_list>");
5638 if (return_type) return_type->set_fullname(p_fullname + ".<return_type>");
5639 }
5640
5641 void Def_Function_Base::set_my_scope(Scope *p_scope)
5642 {
5643 Definition::set_my_scope(p_scope);
5644 fp_list->set_my_scope(p_scope);
5645 if (return_type) return_type->set_my_scope(p_scope);
5646 }
5647
5648 Type *Def_Function_Base::get_Type()
5649 {
5650 if (!checked) chk();
5651 return return_type;
5652 }
5653
5654 FormalParList *Def_Function_Base::get_FormalParList()
5655 {
5656 if (!checked) chk();
5657 return fp_list;
5658 }
5659
5660 const char *Def_Function_Base::get_prototype_name() const
5661 {
5662 switch (prototype) {
5663 case PROTOTYPE_NONE:
5664 return "<no prototype>";
5665 case PROTOTYPE_CONVERT:
5666 return "convert";
5667 case PROTOTYPE_FAST:
5668 return "fast";
5669 case PROTOTYPE_BACKTRACK:
5670 return "backtrack";
5671 case PROTOTYPE_SLIDING:
5672 return "sliding";
5673 default:
5674 return "<unknown prototype>";
5675 }
5676 }
5677
5678 void Def_Function_Base::chk_prototype()
5679 {
5680 switch (prototype) {
5681 case PROTOTYPE_NONE:
5682 // return immediately
5683 return;
5684 case PROTOTYPE_CONVERT:
5685 case PROTOTYPE_FAST:
5686 case PROTOTYPE_BACKTRACK:
5687 case PROTOTYPE_SLIDING:
5688 // perform the checks below
5689 break;
5690 default:
5691 FATAL_ERROR("Def_Function_Base::chk_prototype()");
5692 }
5693 // checking the formal parameter list
5694 if (prototype == PROTOTYPE_CONVERT) {
5695 if (fp_list->get_nof_fps() == 1) {
5696 FormalPar *par = fp_list->get_fp_byIndex(0);
5697 if (par->get_asstype() == A_PAR_VAL_IN) {
5698 input_type = par->get_Type();
5699 } else {
5700 par->error("The parameter must be an `in' value parameter for "
5701 "attribute `prototype(%s)' instead of %s", get_prototype_name(),
5702 par->get_assname());
5703 }
5704 } else {
5705 fp_list->error("The function must have one parameter instead of %lu "
5706 "for attribute `prototype(%s)'", (unsigned long) fp_list->get_nof_fps(),
5707 get_prototype_name());
5708 }
5709 } else { // not PROTOTYPE_CONVERT
5710 if (fp_list->get_nof_fps() == 2) {
5711 FormalPar *first_par = fp_list->get_fp_byIndex(0);
5712 if (prototype == PROTOTYPE_SLIDING) {
5713 if (first_par->get_asstype() == A_PAR_VAL_INOUT) {
5714 Type *first_par_type = first_par->get_Type();
5715 switch (first_par_type->get_type_refd_last()
5716 ->get_typetype_ttcn3()) {
5717 case Type::T_ERROR:
5718 case Type::T_OSTR:
5719 case Type::T_CSTR:
5720 case Type::T_BSTR:
5721 input_type = first_par_type;
5722 break;
5723 default:
5724 first_par_type->error("The type of the first parameter must be "
5725 "`octetstring' or `charstring' or `bitstring' for attribute "
5726 "`prototype(%s)' instead of `%s'", get_prototype_name(),
5727 first_par_type->get_typename().c_str());
5728 }
5729 } else {
5730 first_par->error("The first parameter must be an `inout' value "
5731 "parameter for attribute `prototype(%s)' instead of %s",
5732 get_prototype_name(), first_par->get_assname());
5733 }
5734 } else {
5735 if (first_par->get_asstype() == A_PAR_VAL_IN) {
5736 input_type = first_par->get_Type();
5737 } else {
5738 first_par->error("The first parameter must be an `in' value "
5739 "parameter for attribute `prototype(%s)' instead of %s",
5740 get_prototype_name(), first_par->get_assname());
5741 }
5742 }
5743 FormalPar *second_par = fp_list->get_fp_byIndex(1);
5744 if (second_par->get_asstype() == A_PAR_VAL_OUT) {
5745 output_type = second_par->get_Type();
5746 } else {
5747 second_par->error("The second parameter must be an `out' value "
5748 "parameter for attribute `prototype(%s)' instead of %s",
5749 get_prototype_name(), second_par->get_assname());
5750 }
5751 } else {
5752 fp_list->error("The function must have two parameters for attribute "
5753 "`prototype(%s)' instead of %lu", get_prototype_name(),
5754 (unsigned long) fp_list->get_nof_fps());
5755 }
5756 }
5757 // checking the return type
5758 if (prototype == PROTOTYPE_FAST) {
5759 if (return_type) {
5760 return_type->error("The function cannot have return type for "
5761 "attribute `prototype(%s)'", get_prototype_name());
5762 }
5763 } else {
5764 if (return_type) {
5765 if (asstype == A_FUNCTION_RTEMP || asstype == A_EXT_FUNCTION_RTEMP)
5766 return_type->error("The function must return a value instead of a "
5767 "template for attribute `prototype(%s)'", get_prototype_name());
5768 if (prototype == PROTOTYPE_CONVERT) {
5769 output_type = return_type;
5770 } else {
5771 switch (return_type->get_type_refd_last()->get_typetype_ttcn3()) {
5772 case Type::T_ERROR:
5773 case Type::T_INT:
5774 break;
5775 default:
5776 return_type->error("The return type of the function must be "
5777 "`integer' instead of `%s' for attribute `prototype(%s)'",
5778 return_type->get_typename().c_str(), get_prototype_name());
5779 }
5780 }
5781 } else {
5782 error("The function must have return type for attribute "
5783 "`prototype(%s)'", get_prototype_name());
5784 }
5785 }
5786 // checking the 'runs on' clause
5787 if (get_RunsOnType()) {
5788 error("The function cannot have `runs on' clause for attribute "
5789 "`prototype(%s)'", get_prototype_name());
5790 }
5791 }
5792
5793 Type *Def_Function_Base::get_input_type()
5794 {
5795 if (!checked) chk();
5796 return input_type;
5797 }
5798
5799 Type *Def_Function_Base::get_output_type()
5800 {
5801 if (!checked) chk();
5802 return output_type;
5803 }
5804
5805
5806 // =================================
5807 // ===== Def_Function
5808 // =================================
5809
5810 Def_Function::Def_Function(Identifier *p_id, FormalParList *p_fpl,
5811 Reference *p_runs_on_ref, Type *p_return_type,
5812 bool returns_template,
5813 template_restriction_t p_template_restriction,
5814 StatementBlock *p_block)
5815 : Def_Function_Base(false, p_id, p_fpl, p_return_type, returns_template,
5816 p_template_restriction),
5817 runs_on_ref(p_runs_on_ref), runs_on_type(0), block(p_block),
5818 is_startable(false), transparent(false)
5819 {
5820 if (!p_block) FATAL_ERROR("Def_Function::Def_Function()");
5821 block->set_my_def(this);
5822 }
5823
5824 Def_Function::~Def_Function()
5825 {
5826 delete runs_on_ref;
5827 delete block;
5828 }
5829
5830 Def_Function *Def_Function::clone() const
5831 {
5832 FATAL_ERROR("Def_Function::clone");
5833 }
5834
5835 void Def_Function::set_fullname(const string& p_fullname)
5836 {
5837 Def_Function_Base::set_fullname(p_fullname);
5838 if (runs_on_ref) runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>");
5839 block->set_fullname(p_fullname + ".<statement_block>");
5840 }
5841
5842 void Def_Function::set_my_scope(Scope *p_scope)
5843 {
5844 bridgeScope.set_parent_scope(p_scope);
5845 bridgeScope.set_scopeMacro_name(id->get_dispname());
5846
5847 Def_Function_Base::set_my_scope(&bridgeScope);
5848 if (runs_on_ref) runs_on_ref->set_my_scope(&bridgeScope);
5849 block->set_my_scope(fp_list);
5850 }
5851
5852 Type *Def_Function::get_RunsOnType()
5853 {
5854 if (!checked) chk();
5855 return runs_on_type;
5856 }
5857
5858 RunsOnScope *Def_Function::get_runs_on_scope(Type *comptype)
5859 {
5860 Module *my_module = dynamic_cast<Module*>(my_scope->get_scope_mod());
5861 if (!my_module) FATAL_ERROR("Def_Function::get_runs_on_scope()");
5862 return my_module->get_runs_on_scope(comptype);
5863 }
5864
5865 void Def_Function::chk()
5866 {
5867 if (checked) return;
5868 checked = true;
5869 Error_Context cntxt(this, "In function definition `%s'",
5870 id->get_dispname().c_str());
5871 // checking the `runs on' clause
5872 if (runs_on_ref) {
5873 Error_Context cntxt2(runs_on_ref, "In `runs on' clause");
5874 runs_on_type = runs_on_ref->chk_comptype_ref();
5875 // override the scope of the formal parameter list
5876 if (runs_on_type) {
5877 Scope *runs_on_scope = get_runs_on_scope(runs_on_type);
5878 runs_on_scope->set_parent_scope(my_scope);
5879 fp_list->set_my_scope(runs_on_scope);
5880 }
5881 }
5882 // checking the formal parameter list
5883 fp_list->chk(asstype);
5884 // checking of return type
5885 if (return_type) {
5886 Error_Context cntxt2(return_type, "In return type");
5887 return_type->chk();
5888 return_type->chk_as_return_type(asstype == A_FUNCTION_RVAL,"function");
5889 }
5890 // decision of startability
5891 is_startable = runs_on_ref != 0;
5892 if (is_startable && !fp_list->get_startability()) is_startable = false;
5893 if (is_startable && return_type && return_type->is_component_internal())
5894 is_startable = false;
5895 // checking of statement block
5896 block->chk();
5897 if (return_type) {
5898 // checking the presence of return statements
5899 switch (block->has_return()) {
5900 case StatementBlock::RS_NO:
5901 error("The function has return type, but it does not have any return "
5902 "statement");
5903 break;
5904 case StatementBlock::RS_MAYBE:
5905 error("The function has return type, but control might leave it "
5906 "without reaching a return statement");
5907 default:
5908 break;
5909 }
5910 }
5911 if (!semantic_check_only) {
5912 fp_list->set_genname(get_genname());
5913 block->set_code_section(GovernedSimple::CS_INLINE);
5914 }
5915 if (w_attrib_path) {
5916 w_attrib_path->chk_global_attrib();
5917 w_attrib_path->chk_no_qualif();
5918 Ttcn::ExtensionAttributes * extattrs = parse_extattributes(w_attrib_path);
5919 if (extattrs != 0) { // NULL means parsing error
5920 size_t num_atrs = extattrs->size();
5921 for (size_t i=0; i < num_atrs; ++i) {
5922 ExtensionAttribute &ea = extattrs->get(i);
5923 switch (ea.get_type()) {
5924 case ExtensionAttribute::PROTOTYPE: {
5925 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE) {
5926 ea.error("Duplicate attribute `prototype'");
5927 }
5928 Def_Function_Base::prototype_t proto = ea.get_proto();
5929 set_prototype(proto);
5930 break; }
5931
5932 case ExtensionAttribute::ANYTYPELIST: // ignore it
5933 case ExtensionAttribute::NONE: // erroneous, do not issue an error
5934 break;
5935
5936 case ExtensionAttribute::TRANSPARENT:
5937 transparent = true;
5938 break;
5939
5940 case ExtensionAttribute::ENCODE:
5941 case ExtensionAttribute::DECODE:
5942 case ExtensionAttribute::ERRORBEHAVIOR:
5943 case ExtensionAttribute::PRINTING:
5944 ea.error("Extension attribute 'encode', 'decode', 'errorbehavior'"
5945 " or 'printing' can only be applied to external functions");
5946 // fall through
5947
5948 default: // complain
5949 ea.error("Function definition can only have the 'prototype'"
5950 " extension attribute");
5951 break;
5952 }
5953 }
5954 delete extattrs;
5955 }
5956 }
5957 chk_prototype();
5958 }
5959
5960 bool Def_Function::chk_startable()
5961 {
5962 if (!checked) chk();
5963 if (is_startable) return true;
5964 if (!runs_on_ref) error("Function `%s' cannot be started on a parallel "
5965 "test component because it does not have `runs on' clause",
5966 get_fullname().c_str());
5967 fp_list->chk_startability("Function", get_fullname().c_str());
5968 if (return_type && return_type->is_component_internal()) {
5969 map<Type*,void> type_chain;
5970 char* err_str = mprintf("the return type or embedded in the return type "
5971 "of function `%s' if it is started on a parallel test component",
5972 get_fullname().c_str());
5973 return_type->chk_component_internal(type_chain, err_str);
5974 Free(err_str);
5975 }
5976 return false;
5977 }
5978
5979 void Def_Function::generate_code(output_struct *target, bool)
5980 {
5981 transparency_holder glass(*this);
5982 const string& t_genname = get_genname();
5983 const char *genname_str = t_genname.c_str();
5984 const char *dispname_str = id->get_dispname().c_str();
5985 string return_type_name;
5986 switch (asstype) {
5987 case A_FUNCTION:
5988 return_type_name = "void";
5989 break;
5990 case A_FUNCTION_RVAL:
5991 return_type_name = return_type->get_genname_value(my_scope);
5992 break;
5993 case A_FUNCTION_RTEMP:
5994 return_type_name = return_type->get_genname_template(my_scope);
5995 break;
5996 default:
5997 FATAL_ERROR("Def_Function::generate_code()");
5998 }
5999 const char *return_type_str = return_type_name.c_str();
6000 char *formal_par_list = fp_list->generate_code(memptystr());
6001 fp_list->generate_code_defval(target);
6002 // function prototype
6003 target->header.function_prototypes =
6004 mputprintf(target->header.function_prototypes, "extern %s %s(%s);\n",
6005 return_type_str, genname_str, formal_par_list);
6006
6007 // function body
6008 char *body = mprintf("%s %s(%s)\n"
6009 "{\n", return_type_str, genname_str, formal_par_list);
6010 body = create_location_object(body, "FUNCTION", dispname_str);
6011 if (!enable_set_bound_out_param)
6012 body = fp_list->generate_code_set_unbound(body); // conform the standard out parameter is unbound
6013 body = fp_list->generate_shadow_objects(body);
6014 body = block->generate_code(body);
6015 body = mputstr(body, "}\n\n");
6016 target->source.function_bodies = mputstr(target->source.function_bodies,
6017 body);
6018 Free(body);
6019
6020 if (is_startable) {
6021 size_t nof_fps = fp_list->get_nof_fps();
6022 // starter function (stub)
6023 // function prototype
6024 target->header.function_prototypes =
6025 mputprintf(target->header.function_prototypes,
6026 "extern void start_%s(const COMPONENT& component_reference%s%s);\n",
6027 genname_str, nof_fps>0?", ":"", formal_par_list);
6028 // function body
6029 body = mprintf("void start_%s(const COMPONENT& component_reference%s"
6030 "%s)\n"
6031 "{\n"
6032 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6033 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6034 genname_str, nof_fps>0?", ":"", formal_par_list, dispname_str);
6035 for (size_t i = 0; i < nof_fps; i++) {
6036 if (i > 0) body = mputstr(body,
6037 "TTCN_Logger::log_event_str(\", \");\n");
6038 body = mputprintf(body, "%s.log();\n",
6039 fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
6040 }
6041 body = mputprintf(body,
6042 "TTCN_Logger::log_event_str(\") on component \");\n"
6043 "component_reference.log();\n"
6044 "TTCN_Logger::log_char('.');\n"
6045 "TTCN_Logger::end_event();\n"
6046 "Text_Buf text_buf;\n"
6047 "TTCN_Runtime::prepare_start_component(component_reference, "
6048 "\"%s\", \"%s\", text_buf);\n",
6049 my_scope->get_scope_mod()->get_modid().get_dispname().c_str(),
6050 dispname_str);
6051 for (size_t i = 0; i < nof_fps; i++) {
6052 body = mputprintf(body, "%s.encode_text(text_buf);\n",
6053 fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
6054 }
6055 body = mputstr(body, "TTCN_Runtime::send_start_component(text_buf);\n"
6056 "}\n\n");
6057 target->source.function_bodies = mputstr(target->source.function_bodies,
6058 body);
6059 Free(body);
6060
6061 // an entry in start_ptc_function
6062 body = mprintf("if (!strcmp(function_name, \"%s\")) {\n",
6063 dispname_str);
6064 if (nof_fps > 0) {
6065 body = fp_list->generate_code_object(body, "", ' ');
6066 for (size_t i = 0; i < nof_fps; i++) {
6067 body = mputprintf(body, "%s.decode_text(function_arguments);\n",
6068 fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
6069 }
6070 body = mputprintf(body,
6071 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
6072 "TTCN_Logger::log_event_str(\"Starting function %s(\");\n",
6073 dispname_str);
6074 for (size_t i = 0; i < nof_fps; i++) {
6075 if (i > 0) body = mputstr(body,
6076 "TTCN_Logger::log_event_str(\", \");\n");
6077 body = mputprintf(body, "%s.log();\n",
6078 fp_list->get_fp_byIndex(i)->get_reference_name(my_scope).c_str());
6079 }
6080 body = mputstr(body, "TTCN_Logger::log_event_str(\").\");\n"
6081 "TTCN_Logger::end_event();\n");
6082 } else {
6083 body = mputprintf(body,
6084 "TTCN_Logger::log_str(TTCN_Logger::PARALLEL_PTC, \"Starting function "
6085 "%s().\");\n", dispname_str);
6086 }
6087 body = mputstr(body,
6088 "TTCN_Runtime::function_started(function_arguments);\n");
6089 char *actual_par_list =
6090 fp_list->generate_code_actual_parlist(memptystr(), "");
6091 bool return_value_kept = false;
6092 if (asstype == A_FUNCTION_RVAL) {
6093 // the return value is kept only if the function returns a value
6094 // (rather than a template) and the return type has the "done"
6095 // extension attribute
6096 for (Type *t = return_type; ; t = t->get_type_refd()) {
6097 if (t->has_done_attribute()) {
6098 return_value_kept = true;
6099 break;
6100 } else if (!t->is_ref()) break;
6101 }
6102 }
6103 if (return_value_kept) {
6104 const string& return_type_dispname = return_type->get_typename();
6105 const char *return_type_dispname_str = return_type_dispname.c_str();
6106 body = mputprintf(body, "%s ret_val(%s(%s));\n"
6107 "TTCN_Logger::begin_event(TTCN_PARALLEL);\n"
6108 "TTCN_Logger::log_event_str(\"Function %s returned %s : \");\n"
6109 "ret_val.log();\n"
6110 "Text_Buf text_buf;\n"
6111 "TTCN_Runtime::prepare_function_finished(\"%s\", text_buf);\n"
6112 "ret_val.encode_text(text_buf);\n"
6113 "TTCN_Runtime::send_function_finished(text_buf);\n",
6114 return_type_str, genname_str, actual_par_list, dispname_str,
6115 return_type_dispname_str, return_type_dispname_str);
6116 } else {
6117 body = mputprintf(body, "%s(%s);\n"
6118 "TTCN_Runtime::function_finished(\"%s\");\n",
6119 genname_str, actual_par_list, dispname_str);
6120 }
6121 Free(actual_par_list);
6122 body = mputstr(body, "return TRUE;\n"
6123 "} else ");
6124 target->functions.start = mputstr(target->functions.start, body);
6125 Free(body);
6126 }
6127 Free(formal_par_list);
6128
6129 target->functions.pre_init = mputprintf(target->functions.pre_init,
6130 "%s.add_function(\"%s\", (genericfunc_t)&%s, ", get_module_object_name(),
6131 dispname_str, genname_str);
6132 if(is_startable)
6133 target->functions.pre_init = mputprintf(target->functions.pre_init,
6134 "(genericfunc_t)&start_%s);\n", genname_str);
6135 else
6136 target->functions.pre_init = mputstr(target->functions.pre_init,
6137 "NULL);\n");
6138 }
6139
6140 void Def_Function::generate_code(CodeGenHelper& cgh) {
6141 generate_code(cgh.get_current_outputstruct());
6142 }
6143
6144 void Def_Function::dump_internal(unsigned level) const
6145 {
6146 DEBUG(level, "Function: %s", id->get_dispname().c_str());
6147 DEBUG(level + 1, "Parameters:");
6148 fp_list->dump(level + 1);
6149 if (runs_on_ref) {
6150 DEBUG(level + 1, "Runs on clause:");
6151 runs_on_ref->dump(level + 2);
6152 }
6153 if (return_type) {
6154 DEBUG(level + 1, "Return type:");
6155 return_type->dump(level + 2);
6156 if (asstype == A_FUNCTION_RTEMP) DEBUG(level + 1, "Returns template");
6157 }
6158 if (prototype != PROTOTYPE_NONE)
6159 DEBUG(level + 1, "Prototype: %s", get_prototype_name());
6160 //DEBUG(level + 1, "Statement block:");
6161 block->dump(level + 1);
6162 }
6163
6164 void Def_Function::set_parent_path(WithAttribPath* p_path) {
6165 Def_Function_Base::set_parent_path(p_path);
6166 block->set_parent_path(w_attrib_path);
6167 }
6168
6169 // =================================
6170 // ===== Def_ExtFunction
6171 // =================================
6172
6173 Def_ExtFunction::~Def_ExtFunction()
6174 {
6175 delete encoding_options;
6176 delete eb_list;
6177 if (NULL != json_printing) {
6178 delete json_printing;
6179 }
6180 }
6181
6182 Def_ExtFunction *Def_ExtFunction::clone() const
6183 {
6184 FATAL_ERROR("Def_ExtFunction::clone");
6185 }
6186
6187 void Def_ExtFunction::set_fullname(const string& p_fullname)
6188 {
6189 Def_Function_Base::set_fullname(p_fullname);
6190 if (eb_list) eb_list->set_fullname(p_fullname + ".<errorbehavior_list>");
6191 }
6192
6193 void Def_ExtFunction::set_encode_parameters(Type::MessageEncodingType_t
6194 p_encoding_type, string *p_encoding_options)
6195 {
6196 function_type = EXTFUNC_ENCODE;
6197 encoding_type = p_encoding_type;
6198 delete encoding_options;
6199 encoding_options = p_encoding_options;
6200 }
6201
6202 void Def_ExtFunction::set_decode_parameters(Type::MessageEncodingType_t
6203 p_encoding_type, string *p_encoding_options)
6204 {
6205 function_type = EXTFUNC_DECODE;
6206 encoding_type = p_encoding_type;
6207 delete encoding_options;
6208 encoding_options = p_encoding_options;
6209 }
6210
6211 void Def_ExtFunction::add_eb_list(Ttcn::ErrorBehaviorList *p_eb_list)
6212 {
6213 if (!p_eb_list) FATAL_ERROR("Def_ExtFunction::add_eb_list()");
6214 if (eb_list) {
6215 eb_list->steal_ebs(p_eb_list);
6216 delete p_eb_list;
6217 } else {
6218 eb_list = p_eb_list;
6219 eb_list->set_fullname(get_fullname() + ".<errorbehavior_list>");
6220 }
6221 }
6222
6223 void Def_ExtFunction::chk_function_type()
6224 {
6225 switch (function_type) {
6226 case EXTFUNC_MANUAL:
6227 if (eb_list) {
6228 eb_list->error("Attribute `errorbehavior' can only be used together "
6229 "with `encode' or `decode'");
6230 eb_list->chk();
6231 }
6232 break;
6233 case EXTFUNC_ENCODE:
6234 switch (prototype) {
6235 case PROTOTYPE_NONE:
6236 error("Attribute `encode' cannot be used without `prototype'");
6237 break;
6238 case PROTOTYPE_BACKTRACK:
6239 case PROTOTYPE_SLIDING:
6240 error("Attribute `encode' cannot be used with `prototype(%s)'",
6241 get_prototype_name());
6242 default: /* CONVERT and FAST allowed */
6243 break;
6244 }
6245
6246 if (input_type) {
6247 if (!input_type->has_encoding(encoding_type)) {
6248 input_type->error("Input type `%s' does not support %s encoding",
6249 input_type->get_typename().c_str(),
6250 Type::get_encoding_name(encoding_type));
6251 }
6252 if (Common::Type::CT_XER == encoding_type
6253 && input_type->get_type_refd_last()->is_untagged()) {
6254 // "untagged" on the (toplevel) input type will have no effect.
6255 warning("UNTAGGED encoding attribute is ignored on top-level type");
6256 }
6257 }
6258 if (output_type) {
6259 Type *stream_type = Type::get_stream_type(encoding_type);
6260 if (!stream_type->is_identical(output_type)) {
6261 output_type->error("The output type of %s encoding should be `%s' "
6262 "instead of `%s'", Type::get_encoding_name(encoding_type),
6263 stream_type->get_typename().c_str(),
6264 output_type->get_typename().c_str());
6265 }
6266 }
6267 if (eb_list) eb_list->chk();
6268 chk_allowed_encode();
6269 break;
6270 case EXTFUNC_DECODE:
6271 if (prototype == PROTOTYPE_NONE) {
6272 error("Attribute `decode' cannot be used without `prototype'");
6273 }
6274 if (input_type) {
6275 Type *stream_type = Type::get_stream_type(encoding_type);
6276 if (!stream_type->is_identical(input_type)) {
6277 input_type->error("The input type of %s encoding should be `%s' "
6278 "instead of `%s'", Type::get_encoding_name(encoding_type),
6279 stream_type->get_typename().c_str(),
6280 input_type->get_typename().c_str());
6281 }
6282 }
6283 if (output_type && !output_type->has_encoding(encoding_type)) {
6284 output_type->error("Output type `%s' does not support %s encoding",
6285 output_type->get_typename().c_str(),
6286 Type::get_encoding_name(encoding_type));
6287 }
6288 if (eb_list) eb_list->chk();
6289 chk_allowed_encode();
6290 break;
6291 default:
6292 FATAL_ERROR("Def_ExtFunction::chk()");
6293 }
6294 }
6295
6296 void Def_ExtFunction::chk_allowed_encode()
6297 {
6298 switch (encoding_type) {
6299 case Type::CT_BER:
6300 if (enable_ber()) return; // ok
6301 break;
6302 case Type::CT_RAW:
6303 if (enable_raw()) return; // ok
6304 break;
6305 case Type::CT_TEXT:
6306 if (enable_text()) return; // ok
6307 break;
6308 case Type::CT_XER:
6309 if (enable_xer()) return; // ok
6310 break;
6311 case Type::CT_PER:
6312 if (enable_per()) return; // ok?
6313 break;
6314 case Type::CT_JSON:
6315 if (enable_json()) return;
6316 break;
6317 default:
6318 FATAL_ERROR("Def_ExtFunction::chk_allowed_encode");
6319 break;
6320 }
6321
6322 error("%s encoding is disallowed by license or commandline options",
6323 Type::get_encoding_name(encoding_type));
6324 }
6325
6326 void Def_ExtFunction::chk()
6327 {
6328 if (checked) return;
6329 checked = true;
6330 Error_Context cntxt(this, "In external function definition `%s'",
6331 id->get_dispname().c_str());
6332 fp_list->chk(asstype);
6333 if (return_type) {
6334 Error_Context cntxt2(return_type, "In return type");
6335 return_type->chk();
6336 return_type->chk_as_return_type(asstype == A_EXT_FUNCTION_RVAL,
6337 "external function");
6338 }
6339 if (!semantic_check_only) fp_list->set_genname(get_genname());
6340 if (w_attrib_path) {
6341 w_attrib_path->chk_global_attrib();
6342 w_attrib_path->chk_no_qualif();
6343 const Ttcn::ExtensionAttributes * extattrs = parse_extattributes(w_attrib_path);
6344 if (extattrs != 0) {
6345 size_t num_atrs = extattrs->size();
6346 for (size_t i=0; i < num_atrs; ++i) {
6347 ExtensionAttribute &ea = extattrs->get(i);
6348 switch (ea.get_type()) {
6349 case ExtensionAttribute::PROTOTYPE: {
6350 if (get_prototype() != Def_Function_Base::PROTOTYPE_NONE) {
6351 ea.error("Duplicate attribute `prototype'");
6352 }
6353 Def_Function_Base::prototype_t proto = ea.get_proto();
6354 set_prototype(proto);
6355 break; }
6356
6357 case ExtensionAttribute::ENCODE: {
6358 switch (get_function_type()) {
6359 case Def_ExtFunction::EXTFUNC_MANUAL:
6360 break;
6361 case Def_ExtFunction::EXTFUNC_ENCODE: {
6362 ea.error("Duplicate attribute `encode'");
6363 break; }
6364 case Def_ExtFunction::EXTFUNC_DECODE: {
6365 ea.error("Attributes `decode' and `encode' "
6366 "cannot be used at the same time");
6367 break; }
6368 default:
6369 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6370 }
6371 Type::MessageEncodingType_t et;
6372 string *opt;
6373 ea.get_encdec_parameters(et, opt);
6374 set_encode_parameters(et, opt);
6375 break; }
6376
6377 case ExtensionAttribute::ERRORBEHAVIOR: {
6378 add_eb_list(ea.get_eb_list());
6379 break; }
6380
6381 case ExtensionAttribute::DECODE: {
6382 switch (get_function_type()) {
6383 case Def_ExtFunction::EXTFUNC_MANUAL:
6384 break;
6385 case Def_ExtFunction::EXTFUNC_ENCODE: {
6386 ea.error("Attributes `encode' and `decode' "
6387 "cannot be used at the same time");
6388 break; }
6389 case Def_ExtFunction::EXTFUNC_DECODE: {
6390 ea.error("Duplicate attribute `decode'");
6391 break; }
6392 default:
6393 FATAL_ERROR("coding_attrib_parse(): invalid external function type");
6394 }
6395 Type::MessageEncodingType_t et;
6396 string *opt;
6397 ea.get_encdec_parameters(et, opt);
6398 set_decode_parameters(et, opt);
6399 break; }
6400
6401 case ExtensionAttribute::PRINTING: {
6402 json_printing = ea.get_printing();
6403 break; }
6404
6405 case ExtensionAttribute::ANYTYPELIST:
6406 // ignore, because we can't distinguish between a local
6407 // "extension anytype" (which is bogus) and an inherited one
6408 // (which was meant for a type definition)
6409 break;
6410
6411 case ExtensionAttribute::NONE:
6412 // Ignore, do not issue "wrong type" error
6413 break;
6414
6415 default:
6416 ea.error(
6417 "Only the following extension attributes may be applied to "
6418 "external functions: 'prototype', 'encode', 'decode', 'errorbehavior'");
6419 break;
6420 } // switch type
6421 } // next attribute
6422 delete extattrs;
6423 } // if extatrs
6424 }
6425 chk_prototype();
6426 chk_function_type();
6427
6428 if (NULL != json_printing && (EXTFUNC_ENCODE != function_type ||
6429 Type::CT_JSON != encoding_type)) {
6430 error("Attribute 'printing' is only allowed for JSON encoding functions.");
6431 }
6432 }
6433
6434 char *Def_ExtFunction::generate_code_encode(char *str)
6435 {
6436 const char *function_name = id->get_dispname().c_str();
6437 const char *first_par_name =
6438 fp_list->get_fp_byIndex(0)->get_id().get_name().c_str();
6439 // producing debug printout of the input PDU
6440 str = mputprintf(str,
6441#ifndef NDEBUG
6442 "// written by %s in " __FILE__ " at %d\n"
6443#endif
6444 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6445 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6446 "TTCN_Logger::log_event_str(\"%s(): Encoding %s: \");\n"
6447 "%s.log();\n"
6448 "TTCN_Logger::end_event();\n"
6449 "}\n"
6450#ifndef NDEBUG
6451 , __FUNCTION__, __LINE__
6452#endif
6453 , function_name, input_type->get_typename().c_str(), first_par_name);
6454 // setting error behavior
6455 if (eb_list) str = eb_list->generate_code(str);
6456 else str = mputstr(str, "TTCN_EncDec::set_error_behavior("
6457 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6458 // encoding PDU into the buffer
6459 str = mputstr(str, "TTCN_Buffer ttcn_buffer;\n");
6460 str = mputprintf(str, "%s.encode(%s_descr_, ttcn_buffer, TTCN_EncDec::CT_%s",
6461 first_par_name,
6462 input_type->get_genname_typedescriptor(my_scope).c_str(),
6463 Type::get_encoding_name(encoding_type));
6464 if (encoding_type == Type::CT_JSON) {
6465 if (json_printing != NULL) {
6466 str = json_printing->generate_code(str);
6467 } else {
6468 str = mputstr(str, ", 0");
6469 }
6470 }
6471 if (encoding_options) str = mputprintf(str, ", %s",
6472 encoding_options->c_str());
6473 str = mputstr(str, ");\n");
6474 const char *result_name;
6475 switch (prototype) {
6476 case PROTOTYPE_CONVERT:
6477 result_name = "ret_val";
6478 // creating a local variable for the result stream
6479 str = mputprintf(str, "%s ret_val;\n",
6480 output_type->get_genname_value(my_scope).c_str());
6481 break;
6482 case PROTOTYPE_FAST:
6483 result_name = fp_list->get_fp_byIndex(1)->get_id().get_name().c_str();
6484 break;
6485 default:
6486 FATAL_ERROR("Def_ExtFunction::generate_code_encode()");
6487 result_name = 0;
6488 }
6489 // taking the result from the buffer and producing debug printout
6490 str = mputprintf(str, "ttcn_buffer.get_string(%s);\n"
6491 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6492 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6493 "TTCN_Logger::log_event_str(\"%s(): Stream after encoding: \");\n"
6494 "%s.log();\n"
6495 "TTCN_Logger::end_event();\n"
6496 "}\n", result_name, function_name, result_name);
6497 // returning the result stream if necessary
6498 if (prototype == PROTOTYPE_CONVERT) str = mputstr(str, "return ret_val;\n");
6499 return str;
6500 }
6501
6502 char *Def_ExtFunction::generate_code_decode(char *str)
6503 {
6504 const char *function_name = id->get_dispname().c_str();
6505 const char *first_par_name =
6506 fp_list->get_fp_byIndex(0)->get_id().get_name().c_str();
6507 // producing debug printout of the input stream
6508 str = mputprintf(str,
6509#ifndef NDEBUG
6510 "// written by %s in " __FILE__ " at %d\n"
6511#endif
6512 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6513 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6514 "TTCN_Logger::log_event_str(\"%s(): Stream before decoding: \");\n"
6515 "%s.log();\n"
6516 "TTCN_Logger::end_event();\n"
6517 "}\n"
6518#ifndef NDEBUG
6519 , __FUNCTION__, __LINE__
6520#endif
6521 , function_name, first_par_name);
6522 // setting error behavior
6523 if (eb_list) str = eb_list->generate_code(str);
6524 else if (prototype == PROTOTYPE_BACKTRACK || prototype == PROTOTYPE_SLIDING) {
6525 str = mputstr(str, "TTCN_EncDec::set_error_behavior("
6526 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_WARNING);\n");
6527 } else str = mputstr(str, "TTCN_EncDec::set_error_behavior("
6528 "TTCN_EncDec::ET_ALL, TTCN_EncDec::EB_DEFAULT);\n");
6529 // creating a buffer from the input stream
6530 str = mputprintf(str, "TTCN_EncDec::clear_error();\n"
6531 "TTCN_Buffer ttcn_buffer(%s);\n", first_par_name);
6532 const char *result_name;
6533 if (prototype == PROTOTYPE_CONVERT) {
6534 // creating a local variable for the result
6535 str = mputprintf(str, "%s ret_val;\n",
6536 output_type->get_genname_value(my_scope).c_str());
6537 result_name = "ret_val";
6538 } else {
6539 result_name = fp_list->get_fp_byIndex(1)->get_id().get_name().c_str();
6540 }
6541 if(encoding_type==Type::CT_TEXT){
6542 str = mputprintf(str,
6543 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6544 " TTCN_EncDec::set_error_behavior(TTCN_EncDec::ET_LOG_MATCHING, TTCN_EncDec::EB_WARNING);\n"
6545 "}\n");
6546 }
6547 str = mputprintf(str, "%s.decode(%s_descr_, ttcn_buffer, "
6548 "TTCN_EncDec::CT_%s", result_name,
6549 output_type->get_genname_typedescriptor(my_scope).c_str(),
6550 Type::get_encoding_name(encoding_type));
6551 if (encoding_options) str = mputprintf(str, ", %s",
6552 encoding_options->c_str());
6553 str = mputstr(str, ");\n");
6554 // producing debug printout of the result PDU
6555 str = mputprintf(str,
6556 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6557 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6558 "TTCN_Logger::log_event_str(\"%s(): Decoded %s: \");\n"
6559 "%s.log();\n"
6560 "TTCN_Logger::end_event();\n"
6561 "}\n", function_name, output_type->get_typename().c_str(), result_name);
6562 if (prototype != PROTOTYPE_SLIDING) {
6563 // checking for remaining data in the buffer if decoding was successful
6564 str = mputprintf(str, "if (TTCN_EncDec::get_last_error_type() == "
6565 "TTCN_EncDec::ET_NONE) {\n"
6566 "if (ttcn_buffer.get_pos() < ttcn_buffer.get_len()-1 && "
6567 "TTCN_Logger::log_this_event(TTCN_WARNING)) {\n"
6568 "ttcn_buffer.cut();\n"
6569 "%s remaining_stream;\n"
6570 "ttcn_buffer.get_string(remaining_stream);\n"
6571 "TTCN_Logger::begin_event(TTCN_WARNING);\n"
6572 "TTCN_Logger::log_event_str(\"%s(): Warning: Data remained at the end "
6573 "of the stream after successful decoding: \");\n"
6574 "remaining_stream.log();\n"
6575 "TTCN_Logger::end_event();\n"
6576 "}\n", input_type->get_genname_value(my_scope).c_str(), function_name);
6577 // closing the block and returning the appropriate result or status code
6578 if (prototype == PROTOTYPE_BACKTRACK) {
6579 str = mputstr(str, "return 0;\n"
6580 "} else return 1;\n");
6581 } else {
6582 str = mputstr(str, "}\n");
6583 if (prototype == PROTOTYPE_CONVERT)
6584 str = mputstr(str, "return ret_val;\n");
6585 }
6586 } else {
6587 // result handling and debug printout for sliding decoders
6588 str = mputprintf(str, "switch (TTCN_EncDec::get_last_error_type()) {\n"
6589 "case TTCN_EncDec::ET_NONE:\n"
6590 // TTCN_Buffer::get_string will call OCTETSTRING::clean_up()
6591 "ttcn_buffer.cut();\n"
6592 "ttcn_buffer.get_string(%s);\n"
6593 "if (TTCN_Logger::log_this_event(TTCN_Logger::DEBUG_ENCDEC)) {\n"
6594 "TTCN_Logger::begin_event(TTCN_Logger::DEBUG_ENCDEC);\n"
6595 "TTCN_Logger::log_event_str(\"%s(): Stream after decoding: \");\n"
6596 "%s.log();\n"
6597 "TTCN_Logger::end_event();\n"
6598 "}\n"
6599 "return 0;\n"
6600 "case TTCN_EncDec::ET_INCOMPL_MSG:\n"
6601 "case TTCN_EncDec::ET_LEN_ERR:\n"
6602 "return 2;\n"
6603 "default:\n"
6604 "return 1;\n"
6605 "}\n", first_par_name, function_name, first_par_name);
6606 }
6607 return str;
6608 }
6609
6610 void Def_ExtFunction::generate_code(output_struct *target, bool)
6611 {
6612 const string& t_genname = get_genname();
6613 const char *genname_str = t_genname.c_str();
6614 string return_type_name;
6615 switch (asstype) {
6616 case A_EXT_FUNCTION:
6617 return_type_name = "void";
6618 break;
6619 case A_EXT_FUNCTION_RVAL:
6620 return_type_name = return_type->get_genname_value(my_scope);
6621 break;
6622 case A_EXT_FUNCTION_RTEMP:
6623 return_type_name = return_type->get_genname_template(my_scope);
6624 break;
6625 default:
6626 FATAL_ERROR("Def_ExtFunction::generate_code()");
6627 }
6628 const char *return_type_str = return_type_name.c_str();
6629 char *formal_par_list = fp_list->generate_code(memptystr());
6630 fp_list->generate_code_defval(target);
6631 // function prototype
6632 target->header.function_prototypes =
6633 mputprintf(target->header.function_prototypes, "extern %s %s(%s);\n",
6634 return_type_str, genname_str, formal_par_list);
6635
6636 if (function_type != EXTFUNC_MANUAL) {
6637 // function body written by the compiler
6638 char *body = 0;
6639#ifndef NDEBUG
6640 body = mprintf("// written by %s in " __FILE__ " at %d\n"
6641 , __FUNCTION__, __LINE__);
6642#endif
6643 body = mputprintf(body,
6644 "%s %s(%s)\n"
6645 "{\n"
6646 , return_type_str, genname_str, formal_par_list);
6647 switch (function_type) {
6648 case EXTFUNC_ENCODE:
6649 body = generate_code_encode(body);
6650 break;
6651 case EXTFUNC_DECODE:
6652 body = generate_code_decode(body);
6653 break;
6654 default:
6655 FATAL_ERROR("Def_ExtFunction::generate_code()");
6656 }
6657 body = mputstr(body, "}\n\n");
6658 target->source.function_bodies = mputstr(target->source.function_bodies,
6659 body);
6660 Free(body);
6661 }
6662
6663 Free(formal_par_list);
6664
6665 target->functions.pre_init = mputprintf(target->functions.pre_init,
6666 "%s.add_function(\"%s\", (genericfunc_t)&%s, NULL);\n",
6667 get_module_object_name(), id->get_dispname().c_str(), genname_str);
6668 }
6669
6670 void Def_ExtFunction::generate_code(CodeGenHelper& cgh) {
6671 generate_code(cgh.get_current_outputstruct());
6672 }
6673
6674 void Def_ExtFunction::dump_internal(unsigned level) const
6675 {
6676 DEBUG(level, "External function: %s", id->get_dispname().c_str());
6677 DEBUG(level + 1, "Parameters:");
6678 fp_list->dump(level + 2);
6679 if (return_type) {
6680 DEBUG(level + 1, "Return type:");
6681 return_type->dump(level + 2);
6682 if(asstype == A_EXT_FUNCTION_RTEMP) DEBUG(level + 1, "Returns template");
6683 }
6684 if (prototype != PROTOTYPE_NONE)
6685 DEBUG(level + 1, "Prototype: %s", get_prototype_name());
6686 if (function_type != EXTFUNC_MANUAL) {
6687 DEBUG(level + 1, "Automatically generated: %s",
6688 function_type == EXTFUNC_ENCODE ? "encoder" : "decoder");
6689 DEBUG(level + 2, "Encoding type: %s",
6690 Type::get_encoding_name(encoding_type));
6691 if (encoding_options)
6692 DEBUG(level + 2, "Encoding options: %s", encoding_options->c_str());
6693 }
6694 if (eb_list) eb_list->dump(level + 1);
6695 }
6696
6697 void Def_ExtFunction::generate_json_schema_ref(map<Type*, JSON_Tokenizer>& json_refs)
6698 {
6699 // only do anything if this is a JSON encoding or decoding function
6700 if (encoding_type == Type::CT_JSON &&
6701 (function_type == EXTFUNC_ENCODE || function_type == EXTFUNC_DECODE)) {
6702 // retrieve the encoded type
6703 Type* type = NULL;
6704 if (function_type == EXTFUNC_ENCODE) {
6705 // for encoding functions it's always the first parameter
6706 type = fp_list->get_fp_byIndex(0)->get_Type();
6707 } else {
6708 // for decoding functions it depends on the prototype
6709 switch (prototype) {
6710 case PROTOTYPE_CONVERT:
6711 type = return_type;
6712 break;
6713 case PROTOTYPE_FAST:
6714 case PROTOTYPE_BACKTRACK:
6715 case PROTOTYPE_SLIDING:
6716 type = fp_list->get_fp_byIndex(1)->get_Type();
6717 break;
6718 default:
6719 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
6720 }
6721 }
6722
6723 // step over the type reference created for this function
6724 type = type->get_type_refd();
6725
6726 JSON_Tokenizer* json = NULL;
6727 if (json_refs.has_key(type)) {
6728 // the schema segment containing the type's reference already exists
6729 json = json_refs[type];
6730 } else {
6731 // the schema segment doesn't exist yet, create it and insert the reference
6732 json = new JSON_Tokenizer;
6733 json_refs.add(type, json);
af710487 6734 type->generate_json_schema_ref(*json);
970ed795
EL
6735 }
6736
6737 // insert a property to specify which function this is (encoding or decoding)
6738 json->put_next_token(JSON_TOKEN_NAME, (function_type == EXTFUNC_ENCODE) ?
6739 "encoding" : "decoding");
6740
6741 // place the function's info in an object
6742 json->put_next_token(JSON_TOKEN_OBJECT_START);
6743
6744 // insert information related to the function's prototype in an array
6745 json->put_next_token(JSON_TOKEN_NAME, "prototype");
6746 json->put_next_token(JSON_TOKEN_ARRAY_START);
6747
6748 // 1st element: external function prototype name (as string)
6749 switch(prototype) {
6750 case PROTOTYPE_CONVERT:
6751 json->put_next_token(JSON_TOKEN_STRING, "\"convert\"");
6752 break;
6753 case PROTOTYPE_FAST:
6754 json->put_next_token(JSON_TOKEN_STRING, "\"fast\"");
6755 break;
6756 case PROTOTYPE_BACKTRACK:
6757 json->put_next_token(JSON_TOKEN_STRING, "\"backtrack\"");
6758 break;
6759 case PROTOTYPE_SLIDING:
6760 json->put_next_token(JSON_TOKEN_STRING, "\"sliding\"");
6761 break;
6762 default:
6763 FATAL_ERROR("Def_ExtFunction::generate_json_schema_ref");
6764 }
6765
6766 // 2nd element: external function name
6767 char* func_name_str = mprintf("\"%s\"", id->get_dispname().c_str());
6768 json->put_next_token(JSON_TOKEN_STRING, func_name_str);
6769 Free(func_name_str);
6770
6771 // the rest of the elements contain the names of the function's parameters (1 or 2)
6772 for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
6773 char* param_str = mprintf("\"%s\"",
6774 fp_list->get_fp_byIndex(i)->get_id().get_dispname().c_str());
6775 json->put_next_token(JSON_TOKEN_STRING, param_str);
6776 Free(param_str);
6777 }
6778
6779 // end of the prototype's array
6780 json->put_next_token(JSON_TOKEN_ARRAY_END);
6781
6782 // insert error behavior data
6783 if (eb_list != NULL) {
6784 json->put_next_token(JSON_TOKEN_NAME, "errorBehavior");
6785 json->put_next_token(JSON_TOKEN_OBJECT_START);
6786
6787 // add each error behavior modification as a property
6788 for (size_t i = 0; i < eb_list->get_nof_ebs(); ++i) {
6789 ErrorBehaviorSetting* eb = eb_list->get_ebs_byIndex(i);
6790 json->put_next_token(JSON_TOKEN_NAME, eb->get_error_type().c_str());
6791 char* handling_str = mprintf("\"%s\"", eb->get_error_handling().c_str());
6792 json->put_next_token(JSON_TOKEN_STRING, handling_str);
6793 Free(handling_str);
6794 }
6795
6796 json->put_next_token(JSON_TOKEN_OBJECT_END);
6797 }
6798
6799 // insert printing type
6800 if (json_printing != NULL) {
6801 json->put_next_token(JSON_TOKEN_NAME, "printing");
6802 json->put_next_token(JSON_TOKEN_STRING,
6803 (json_printing->get_printing() == PrintingType::PT_PRETTY) ?
6804 "\"pretty\"" : "\"compact\"");
6805 }
6806
6807 // end of this function's object
6808 json->put_next_token(JSON_TOKEN_OBJECT_END);
6809 }
6810 }
6811
6812 // =================================
6813 // ===== Def_Altstep
6814 // =================================
6815
6816 Def_Altstep::Def_Altstep(Identifier *p_id, FormalParList *p_fpl,
6817 Reference *p_runs_on_ref, StatementBlock *p_sb,
6818 AltGuards *p_ags)
6819 : Definition(A_ALTSTEP, p_id), fp_list(p_fpl), runs_on_ref(p_runs_on_ref),
6820 runs_on_type(0), sb(p_sb), ags(p_ags)
6821 {
6822 if (!p_fpl || !p_sb || !p_ags)
6823 FATAL_ERROR("Def_Altstep::Def_Altstep()");
6824 fp_list->set_my_def(this);
6825 sb->set_my_def(this);
6826 ags->set_my_def(this);
6827 ags->set_my_sb(sb, 0);
6828 }
6829
6830 Def_Altstep::~Def_Altstep()
6831 {
6832 delete fp_list;
6833 delete runs_on_ref;
6834 delete sb;
6835 delete ags;
6836 }
6837
6838 Def_Altstep *Def_Altstep::clone() const
6839 {
6840 FATAL_ERROR("Def_Altstep::clone");
6841 }
6842
6843 void Def_Altstep::set_fullname(const string& p_fullname)
6844 {
6845 Definition::set_fullname(p_fullname);
6846 fp_list->set_fullname(p_fullname + ".<formal_par_list>");
6847 if (runs_on_ref) runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>");
6848 sb->set_fullname(p_fullname+".<block>");
6849 ags->set_fullname(p_fullname + ".<guards>");
6850 }
6851
6852 void Def_Altstep::set_my_scope(Scope *p_scope)
6853 {
6854 bridgeScope.set_parent_scope(p_scope);
6855 bridgeScope.set_scopeMacro_name(id->get_dispname());
6856
6857 Definition::set_my_scope(&bridgeScope);
6858 // the scope of the parameter list is set during checking
6859 if (runs_on_ref) runs_on_ref->set_my_scope(&bridgeScope);
6860 sb->set_my_scope(fp_list);
6861 ags->set_my_scope(sb);
6862 }
6863
6864 Type *Def_Altstep::get_RunsOnType()
6865 {
6866 if (!checked) chk();
6867 return runs_on_type;
6868 }
6869
6870 FormalParList *Def_Altstep::get_FormalParList()
6871 {
6872 if (!checked) chk();
6873 return fp_list;
6874 }
6875
6876 RunsOnScope *Def_Altstep::get_runs_on_scope(Type *comptype)
6877 {
6878 Module *my_module = dynamic_cast<Module*>(my_scope->get_scope_mod());
6879 if (!my_module) FATAL_ERROR("Def_Altstep::get_runs_on_scope()");
6880 return my_module->get_runs_on_scope(comptype);
6881 }
6882
6883 void Def_Altstep::chk()
6884 {
6885 if (checked) return;
6886 checked = true;
6887 Error_Context cntxt(this, "In altstep definition `%s'",
6888 id->get_dispname().c_str());
6889 Scope *parlist_scope = my_scope;
6890 if (runs_on_ref) {
6891 Error_Context cntxt2(runs_on_ref, "In `runs on' clause");
6892 runs_on_type = runs_on_ref->chk_comptype_ref();
6893 if (runs_on_type) {
6894 Scope *runs_on_scope = get_runs_on_scope(runs_on_type);
6895 runs_on_scope->set_parent_scope(my_scope);
6896 parlist_scope = runs_on_scope;
6897 }
6898 }
6899 fp_list->set_my_scope(parlist_scope);
6900 fp_list->chk(asstype);
6901 sb->chk();
6902 ags->set_is_altstep();
6903 ags->set_my_ags(ags);
6904 ags->set_my_laic_stmt(ags, 0);
6905 ags->chk();
6906 if (!semantic_check_only) {
6907 fp_list->set_genname(get_genname());
6908 sb->set_code_section(GovernedSimple::CS_INLINE);
6909 ags->set_code_section(GovernedSimple::CS_INLINE);
6910 }
6911 if (w_attrib_path) {
6912 w_attrib_path->chk_global_attrib();
6913 w_attrib_path->chk_no_qualif();
6914 }
6915 }
6916
6917 void Def_Altstep::generate_code(output_struct *target, bool)
6918 {
6919 const string& t_genname = get_genname();
6920 const char *genname_str = t_genname.c_str();
6921 const char *dispname_str = id->get_dispname().c_str();
6922 char *formal_par_list = fp_list->generate_code(memptystr());
6923 fp_list->generate_code_defval(target);
6924
6925 // function for altstep instance: prototype
6926 target->header.function_prototypes =
6927 mputprintf(target->header.function_prototypes,
6928 "extern alt_status %s_instance(%s);\n", genname_str, formal_par_list);
6929
6930 // function for altstep instance: body
6931 char *str = mprintf("alt_status %s_instance(%s)\n"
6932 "{\n", genname_str, formal_par_list);
6933 str = create_location_object(str, "ALTSTEP", dispname_str);
6934 str = fp_list->generate_shadow_objects(str);
6935 str = sb->generate_code(str);
6936 str = ags->generate_code_altstep(str);
6937 str = mputstr(str, "}\n\n");
6938 target->source.function_bodies = mputstr(target->source.function_bodies,
6939 str);
6940 Free(str);
6941
6942 char *actual_par_list =
6943 fp_list->generate_code_actual_parlist(memptystr(), "");
6944
6945 // wrapper function for stand-alone instantiation: prototype
6946 target->header.function_prototypes =
6947 mputprintf(target->header.function_prototypes,
6948 "extern void %s(%s);\n", genname_str, formal_par_list);
6949
6950 // wrapper function for stand-alone instantiation: body
6951 target->source.function_bodies =
6952 mputprintf(target->source.function_bodies, "void %s(%s)\n"
6953 "{\n"
6954 "altstep_begin:\n"
6955 "boolean block_flag = FALSE;\n"
6956 "alt_status altstep_flag = ALT_UNCHECKED, "
6957 "default_flag = ALT_UNCHECKED;\n"
6958 "for ( ; ; ) {\n"
6959 "TTCN_Snapshot::take_new(block_flag);\n"
6960 "if (altstep_flag != ALT_NO) {\n"
6961 "altstep_flag = %s_instance(%s);\n"
6962 "if (altstep_flag == ALT_YES || altstep_flag == ALT_BREAK) return;\n"
6963 "else if (altstep_flag == ALT_REPEAT) goto altstep_begin;\n"
6964 "}\n"
6965 "if (default_flag != ALT_NO) {\n"
6966 "default_flag = TTCN_Default::try_altsteps();\n"
6967 "if (default_flag == ALT_YES || default_flag == ALT_BREAK) return;\n"
6968 "else if (default_flag == ALT_REPEAT) goto altstep_begin;\n"
6969 "}\n"
6970 "if (altstep_flag == ALT_NO && default_flag == ALT_NO) "
6971 "TTCN_error(\"None of the branches can be chosen in altstep %s.\");\n"
6972 "else block_flag = TRUE;\n"
6973 "}\n"
6974 "}\n\n", genname_str, formal_par_list, genname_str, actual_par_list,
6975 dispname_str);
6976
6977 // class for keeping the altstep in the default context
6978 // the class is for internal use, we do not need to publish it in the
6979 // header file
6980 str = mprintf("class %s_Default : public Default_Base {\n", genname_str);
6981 str = fp_list->generate_code_object(str, "par_");
6982 str = mputprintf(str, "public:\n"
6983 "%s_Default(%s);\n"
6984 "alt_status call_altstep();\n"
6985 "};\n\n", genname_str, formal_par_list);
6986 target->source.class_defs = mputstr(target->source.class_defs, str);
6987 Free(str);
6988 // member functions of the class
6989 str = mprintf("%s_Default::%s_Default(%s)\n"
6990 " : Default_Base(\"%s\")", genname_str, genname_str, formal_par_list,
6991 dispname_str);
6992 for (size_t i = 0; i < fp_list->get_nof_fps(); i++) {
6993 const char *fp_name_str =
6994 fp_list->get_fp_byIndex(i)->get_id().get_name().c_str();
6995 str = mputprintf(str, ", par_%s(%s)", fp_name_str, fp_name_str);
6996 }
6997 str = mputstr(str, "\n{\n}\n\n");
6998 char *actual_par_list_prefixed =
6999 fp_list->generate_code_actual_parlist(memptystr(), "par_");
7000 str = mputprintf(str, "alt_status %s_Default::call_altstep()\n"
7001 "{\n"
7002 "return %s_instance(%s);\n"
7003 "}\n\n", genname_str, genname_str, actual_par_list_prefixed);
7004 Free(actual_par_list_prefixed);
7005 target->source.methods = mputstr(target->source.methods, str);
7006 Free(str);
7007
7008 // function for default activation: prototype
7009 target->header.function_prototypes =
7010 mputprintf(target->header.function_prototypes,
7011 "extern Default_Base *activate_%s(%s);\n", genname_str,
7012 formal_par_list);
7013
7014 // function for default activation: body
7015 str = mprintf("Default_Base *activate_%s(%s)\n"
7016 "{\n", genname_str, formal_par_list);
7017 str = mputprintf(str, "return new %s_Default(%s);\n"
7018 "}\n\n", genname_str, actual_par_list);
7019 target->source.function_bodies = mputstr(target->source.function_bodies,
7020 str);
7021 Free(str);
7022
7023 Free(formal_par_list);
7024 Free(actual_par_list);
7025
7026 target->functions.pre_init = mputprintf(target->functions.pre_init,
7027 "%s.add_altstep(\"%s\", (genericfunc_t)&%s_instance, (genericfunc_t )&activate_%s, "
7028 "(genericfunc_t )&%s);\n", get_module_object_name(), dispname_str, genname_str,
7029 genname_str, genname_str);
7030 }
7031
7032 void Def_Altstep::generate_code(CodeGenHelper& cgh) {
7033 generate_code(cgh.get_current_outputstruct());
7034 }
7035
7036 void Def_Altstep::dump_internal(unsigned level) const
7037 {
7038 DEBUG(level, "Altstep: %s", id->get_dispname().c_str());
7039 DEBUG(level + 1, "Parameters:");
7040 fp_list->dump(level + 1);
7041 if (runs_on_ref) {
7042 DEBUG(level + 1, "Runs on clause:");
7043 runs_on_ref->dump(level + 2);
7044 }
7045 /*
7046 DEBUG(level + 1, "Local definitions:");
7047 sb->dump(level + 2);
7048 */
7049 DEBUG(level + 1, "Guards:");
7050 ags->dump(level + 2);
7051 }
7052
7053 void Def_Altstep::set_parent_path(WithAttribPath* p_path) {
7054 Definition::set_parent_path(p_path);
7055 sb->set_parent_path(w_attrib_path);
7056 }
7057
7058 // =================================
7059 // ===== Def_Testcase
7060 // =================================
7061
7062 Def_Testcase::Def_Testcase(Identifier *p_id, FormalParList *p_fpl,
7063 Reference *p_runs_on_ref, Reference *p_system_ref,
7064 StatementBlock *p_block)
7065 : Definition(A_TESTCASE, p_id), fp_list(p_fpl), runs_on_ref(p_runs_on_ref),
7066 runs_on_type(0), system_ref(p_system_ref), system_type(0), block(p_block)
7067 {
7068 if (!p_fpl || !p_runs_on_ref || !p_block)
7069 FATAL_ERROR("Def_Testcase::Def_Testcase()");
7070 fp_list->set_my_def(this);
7071 block->set_my_def(this);
7072 }
7073
7074 Def_Testcase::~Def_Testcase()
7075 {
7076 delete fp_list;
7077 delete runs_on_ref;
7078 delete system_ref;
7079 delete block;
7080 }
7081
7082 Def_Testcase *Def_Testcase::clone() const
7083 {
7084 FATAL_ERROR("Def_Testcase::clone");
7085 }
7086
7087 void Def_Testcase::set_fullname(const string& p_fullname)
7088 {
7089 Definition::set_fullname(p_fullname);
7090 fp_list->set_fullname(p_fullname + ".<formal_par_list>");
7091 runs_on_ref->set_fullname(p_fullname + ".<runs_on_type>");
7092 if (system_ref) system_ref->set_fullname(p_fullname + ".<system_type>");
7093 block->set_fullname(p_fullname + ".<statement_block>");
7094 }
7095
7096 void Def_Testcase::set_my_scope(Scope *p_scope)
7097 {
7098 bridgeScope.set_parent_scope(p_scope);
7099 bridgeScope.set_scopeMacro_name(id->get_dispname());
7100
7101 Definition::set_my_scope(&bridgeScope);
7102 // the scope of the parameter list is set during checking
7103 runs_on_ref->set_my_scope(&bridgeScope);
7104 if (system_ref) system_ref->set_my_scope(&bridgeScope);
7105 block->set_my_scope(fp_list);
7106 }
7107
7108 Type *Def_Testcase::get_RunsOnType()
7109 {
7110 if (!checked) chk();
7111 return runs_on_type;
7112 }
7113
7114 Type *Def_Testcase::get_SystemType()
7115 {
7116 if (!checked) chk();
7117 return system_type;
7118 }
7119
7120 FormalParList *Def_Testcase::get_FormalParList()
7121 {
7122 if (!checked) chk();
7123 return fp_list;
7124 }
7125
7126 RunsOnScope *Def_Testcase::get_runs_on_scope(Type *comptype)
7127 {
7128 Module *my_module = dynamic_cast<Module*>(my_scope->get_scope_mod());
7129 if (!my_module) FATAL_ERROR("Def_Testcase::get_runs_on_scope()");
7130 return my_module->get_runs_on_scope(comptype);
7131 }
7132
7133 void Def_Testcase::chk()
7134 {
7135 if (checked) return;
7136 checked = true;
7137 Error_Context cntxt(this, "In testcase definition `%s'",
7138 id->get_dispname().c_str());
7139 Scope *parlist_scope = my_scope;
7140 {
7141 Error_Context cntxt2(runs_on_ref, "In `runs on' clause");
7142 runs_on_type = runs_on_ref->chk_comptype_ref();
7143 if (runs_on_type) {
7144 Scope *runs_on_scope = get_runs_on_scope(runs_on_type);
7145 runs_on_scope->set_parent_scope(my_scope);
7146 parlist_scope = runs_on_scope;
7147 }
7148 }
7149 if (system_ref) {
7150 Error_Context cntxt2(system_ref, "In `system' clause");
7151 system_type = system_ref->chk_comptype_ref();;
7152 }
7153 fp_list->set_my_scope(parlist_scope);
7154 fp_list->chk(asstype);
7155 block->chk();
7156 if (!semantic_check_only) {
7157 fp_list->set_genname(get_genname());
7158 block->set_code_section(GovernedSimple::CS_INLINE);
7159 }
7160 if (w_attrib_path) {
7161 w_attrib_path->chk_global_attrib();
7162 w_attrib_path->chk_no_qualif();
7163 }
7164 }
7165
7166 void Def_Testcase::generate_code(output_struct *target, bool)
7167 {
7168 const string& t_genname = get_genname();
7169 const char *genname_str = t_genname.c_str();
7170 const char *dispname_str = id->get_dispname().c_str();
7171 // formal parameter list
7172 char *formal_par_list = fp_list->generate_code(memptystr());
7173 fp_list->generate_code_defval(target);
7174 if (fp_list->get_nof_fps() > 0)
7175 formal_par_list = mputstr(formal_par_list, ", ");
7176 formal_par_list = mputstr(formal_par_list,
7177 "boolean has_timer, double timer_value");
7178
7179 // function prototype
7180 target->header.function_prototypes =
7181 mputprintf(target->header.function_prototypes,
7182 "extern verdicttype testcase_%s(%s);\n", genname_str, formal_par_list);
7183
7184 // function body
7185 char *body = mprintf("verdicttype testcase_%s(%s)\n"
7186 "{\n", genname_str, formal_par_list);
7187 Free(formal_par_list);
7188 // Checking whether the testcase was invoked from another one.
7189 // At this point the location information should refer to the execute()
7190 // statement rather than this testcase.
7191 body = mputstr(body, "TTCN_Runtime::check_begin_testcase(has_timer, "
7192 "timer_value);\n");
7193 body = create_location_object(body, "TESTCASE", dispname_str);
7194 body = fp_list->generate_shadow_objects(body);
7195 body = mputprintf(body, "try {\n"
7196 "TTCN_Runtime::begin_testcase(\"%s\", \"%s\", ",
7197 my_scope->get_scope_mod()->get_modid().get_dispname().c_str(),
7198 dispname_str);
7199 ComponentTypeBody *runs_on_body = runs_on_type->get_CompBody();
7200 body = runs_on_body->generate_code_comptype_name(body);
7201 body = mputstr(body, ", ");
7202 if (system_type)
7203 body = system_type->get_CompBody()->generate_code_comptype_name(body);
7204 else body = runs_on_body->generate_code_comptype_name(body);
7205 body = mputstr(body, ", has_timer, timer_value);\n");
7206 body = block->generate_code(body);
7207 body = mputprintf(body,
7208 "} catch (const TC_Error& tc_error) {\n"
7209 "} catch (const TC_End& tc_end) {\n"
7210 "TTCN_Logger::log_str(TTCN_FUNCTION, \"Test case %s was stopped.\");\n"
7211 "}\n", dispname_str);
7212 body = mputstr(body, "return TTCN_Runtime::end_testcase();\n"
7213 "}\n\n");
7214 target->source.function_bodies = mputstr(target->source.function_bodies,
7215 body);
7216 Free(body);
7217
7218 if (fp_list->get_nof_fps() == 0) {
7219 // adding to the list of startable testcases
7220 target->functions.pre_init = mputprintf(target->functions.pre_init,
7221 "%s.add_testcase_nonpard(\"%s\", testcase_%s);\n",
7222 get_module_object_name(), dispname_str, genname_str);
7223 } else {
7224 target->functions.pre_init = mputprintf(target->functions.pre_init,
7225 "%s.add_testcase_pard(\"%s\", (genericfunc_t)&testcase_%s);\n",
7226 get_module_object_name(), dispname_str, genname_str);
7227
7228 // If every formal parameter has a default value, the testcase
7229 // might be callable after all.
7230 bool callable = true;
7231 for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
7232 FormalPar *fp = fp_list->get_fp_byIndex(i);
7233 if (!fp->has_defval()) {
7234 callable = false;
7235 break;
7236 }
7237 }
7238
7239 if (callable) {
7240 // Write a wrapper, which acts as a no-param testcase
7241 // by calling the parameterized testcase with the default values.
7242 target->header.function_prototypes =
7243 mputprintf(target->header.function_prototypes,
7244 "extern verdicttype testcase_%s_defparams(boolean has_timer, double timer_value);\n",
7245 genname_str);
7246 target->source.function_bodies = mputprintf(target->source.function_bodies,
7247 "verdicttype testcase_%s_defparams(boolean has_timer, double timer_value) {\n"
7248 " return testcase_%s(",
7249 genname_str, genname_str);
7250
7251 for (size_t i = 0; i < fp_list->get_nof_fps(); ++i) {
7252 FormalPar *fp = fp_list->get_fp_byIndex(i);
7253 ActualPar *ap = fp->get_defval();
7254 switch (ap->get_selection()) {
7255 case ActualPar::AP_VALUE:
7256 target->source.function_bodies = mputstr(target->source.function_bodies,
7257 ap->get_Value()->get_genname_own(my_scope).c_str());
7258 break;
7259 case ActualPar::AP_TEMPLATE:
7260 target->source.function_bodies = mputstr(target->source.function_bodies,
7261 ap->get_TemplateInstance()->get_Template()->get_genname_own(my_scope).c_str());
7262 break;
7263 case ActualPar::AP_REF:
7264 target->source.function_bodies = mputstr(target->source.function_bodies,
7265 ap->get_Ref()->get_refd_assignment()->get_genname_from_scope(my_scope).c_str());
7266 break;
7267 case ActualPar::AP_DEFAULT:
7268 // Can't happen. This ActualPar was created by
7269 // Ttcn::FormalPar::chk_actual_par as the default value for
7270 // a FormalPar, and it only ever creates vale, template or ref.
7271 // no break
7272 default:
7273 FATAL_ERROR("Def_Testcase::generate_code()");
7274 }
7275
7276 // always append a comma, because has_timer and timer_value follows
7277 target->source.function_bodies = mputstrn(target->source.function_bodies,
7278 ", ", 2);
7279 }
7280
7281 target->source.function_bodies = mputstr(target->source.function_bodies,
7282 "has_timer, timer_value);\n"
7283 "}\n\n");
7284 // Add the non-parameterized wrapper *after* the parameterized one,
7285 // with the same name. Linear search will always find the first
7286 // (user-visible, parameterized) testcase.
7287 // TTCN_Module::execute_testcase knows that if after a parameterized
7288 // testcase another testcase with the same name follows,
7289 // it's the callable, non-parameterized wrapper.
7290 //
7291 // TTCN_Module::list_testcases skips parameterized testcases;
7292 // it will now list the non-parameterized wrapper.
7293 target->functions.pre_init = mputprintf(target->functions.pre_init,
7294 "%s.add_testcase_nonpard(\"%s\", testcase_%s_defparams);\n",
7295 get_module_object_name(), dispname_str, genname_str);
7296 }
7297 } // has formal parameters
7298 }
7299
7300 void Def_Testcase::generate_code(CodeGenHelper& cgh) {
7301 generate_code(cgh.get_current_outputstruct());
7302 }
7303
7304 void Def_Testcase::dump_internal(unsigned level) const
7305 {
7306 DEBUG(level, "Testcase: %s", id->get_dispname().c_str());
7307 DEBUG(level + 1, "Parameters:");
7308 fp_list->dump(level + 1);
7309 DEBUG(level + 1, "Runs on clause:");
7310 runs_on_ref->dump(level + 2);
7311 if (system_ref) {
7312 DEBUG(level + 1, "System clause:");
7313 system_ref->dump(level + 2);
7314 }
7315 DEBUG(level + 1, "Statement block:");
7316 block->dump(level + 2);
7317 }
7318
7319 void Def_Testcase::set_parent_path(WithAttribPath* p_path) {
7320 Definition::set_parent_path(p_path);
7321 if (block)
7322 block->set_parent_path(w_attrib_path);
7323 }
7324
7325 // =================================
7326 // ===== FormalPar
7327 // =================================
7328
7329 FormalPar::FormalPar(asstype_t p_asstype, Type *p_type, Identifier* p_name,
7330 TemplateInstance *p_defval, bool p_lazy_eval)
7331 : Definition(p_asstype, p_name), type(p_type), my_parlist(0),
7332 used_as_lvalue(false), template_restriction(TR_NONE),
7333 lazy_eval(p_lazy_eval)
7334 {
7335 switch (p_asstype) {
7336 case A_PAR_VAL:
7337 case A_PAR_VAL_IN:
7338 case A_PAR_VAL_OUT:
7339 case A_PAR_VAL_INOUT:
7340 case A_PAR_TEMPL_IN:
7341 case A_PAR_TEMPL_OUT:
7342 case A_PAR_TEMPL_INOUT:
7343 case A_PAR_PORT:
7344 break;
7345 default:
7346 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7347 }
7348 if (!p_type)
7349 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7350 type->set_ownertype(Type::OT_FORMAL_PAR, this);
7351 defval.ti = p_defval;
7352 }
7353
7354 FormalPar::FormalPar(asstype_t p_asstype,
7355 template_restriction_t p_template_restriction, Type *p_type,
7356 Identifier* p_name, TemplateInstance *p_defval, bool p_lazy_eval)
7357 : Definition(p_asstype, p_name), type(p_type), my_parlist(0),
7358 used_as_lvalue(false), template_restriction(p_template_restriction),
7359 lazy_eval(p_lazy_eval)
7360 {
7361 switch (p_asstype) {
7362 case A_PAR_TEMPL_IN:
7363 case A_PAR_TEMPL_OUT:
7364 case A_PAR_TEMPL_INOUT:
7365 break;
7366 default:
7367 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): parameter not template");
7368 }
7369 if (!p_type)
7370 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): NULL pointer");
7371 type->set_ownertype(Type::OT_FORMAL_PAR, this);
7372 defval.ti = p_defval;
7373 }
7374
7375 FormalPar::FormalPar(asstype_t p_asstype, Identifier* p_name,
7376 TemplateInstance *p_defval)
7377 : Definition(p_asstype, p_name), type(0), my_parlist(0),
7378 used_as_lvalue(false), template_restriction(TR_NONE), lazy_eval(false)
7379 {
7380 if (p_asstype != A_PAR_TIMER)
7381 FATAL_ERROR("Ttcn::FormalPar::FormalPar(): invalid parameter type");
7382 defval.ti = p_defval;
7383 }
7384
7385 FormalPar::~FormalPar()
7386 {
7387 delete type;
7388 if (checked) delete defval.ap;
7389 else delete defval.ti;
7390 }
7391
7392 FormalPar* FormalPar::clone() const
7393 {
7394 FATAL_ERROR("FormalPar::clone");
7395 }
7396
7397 void FormalPar::set_fullname(const string& p_fullname)
7398 {
7399 Definition::set_fullname(p_fullname);
7400 if (type) type->set_fullname(p_fullname + ".<type>");
7401 if (checked) {
7402 if (defval.ap) defval.ap->set_fullname(p_fullname + ".<default_value>");
7403 } else {
7404 if (defval.ti) defval.ti->set_fullname(p_fullname + ".<default_value>");
7405 }
7406 }
7407
7408 void FormalPar::set_my_scope(Scope *p_scope)
7409 {
7410 Definition::set_my_scope(p_scope);
7411 if (type) type->set_my_scope(p_scope);
7412 if (checked) {
7413 if (defval.ap) defval.ap->set_my_scope(p_scope);
7414 } else {
7415 if (defval.ti) defval.ti->set_my_scope(p_scope);
7416 }
7417 }
7418
7419 bool FormalPar::is_local() const
7420 {
7421 return true;
7422 }
7423
7424 Type *FormalPar::get_Type()
7425 {
7426 if (!checked) chk();
7427 if (!type) FATAL_ERROR("FormalPar::get_Type()");
7428 return type;
7429 }
7430
7431 void FormalPar::chk()
7432 {
7433 if (checked) return;
7434 checked = true;
7435 TemplateInstance *default_value = defval.ti;
7436 defval.ti = 0;
7437 if (type) {
7438 type->chk();
7439 Type *t = type->get_type_refd_last();
7440 // checks for forbidden type <-> parameter combinations
7441 switch (t->get_typetype()) {
7442 case Type::T_PORT:
7443 switch (asstype) {
7444 case A_PAR_VAL:
7445 case A_PAR_VAL_INOUT:
7446 asstype = A_PAR_PORT;
7447 break;
7448 default:
7449 error("Port type `%s' cannot be used as %s",
7450 t->get_fullname().c_str(), get_assname());
7451 }
7452 break;
7453 case Type::T_SIGNATURE:
7454 switch (asstype) {
7455 case A_PAR_TEMPL_IN:
7456 case A_PAR_TEMPL_OUT:
7457 case A_PAR_TEMPL_INOUT:
7458 break;
7459 default:
7460 error("Signature `%s' cannot be used as %s",
7461 t->get_fullname().c_str(), get_assname());
7462 }
7463 break;
7464 default:
7465 switch (asstype) {
7466 case A_PAR_PORT:
7467 case A_PAR_TIMER:
7468 FATAL_ERROR("FormalPar::chk()");
7469 case A_PAR_VAL:
7470 asstype = A_PAR_VAL_IN;
7471 default:
7472 break;
7473 }
7474 }
7475 } else if (asstype != A_PAR_TIMER) FATAL_ERROR("FormalPar::chk()");
7476
7477 if (default_value) {
7478 Error_Context cntxt(default_value, "In default value");
7479 defval.ap = chk_actual_par(default_value, Type::EXPECTED_STATIC_VALUE);
7480 delete default_value;
7481 if (!semantic_check_only)
7482 defval.ap->set_code_section(GovernedSimple::CS_POST_INIT);
7483 }
7484 }
7485
7486 bool FormalPar::has_defval() const
7487 {
7488 if (checked) return defval.ap != 0;
7489 else return defval.ti != 0;
7490 }
7491
7492 bool FormalPar::has_notused_defval() const
7493 {
7494 if (checked) FATAL_ERROR("FormalPar::has_notused_defval");
7495 if (!defval.ti || !defval.ti->get_Template())
7496 return false;
7497 return defval.ti->get_Template()->get_templatetype()
7498 == Template::TEMPLATE_NOTUSED;
7499 }
7500
7501 ActualPar *FormalPar::get_defval() const
7502 {
7503 if (!checked) FATAL_ERROR("FormalPar::get_defval()");
7504 return defval.ap;
7505 }
7506
7507 // Extract the TemplateInstance from an ActualPar.
7508 void FormalPar::set_defval(ActualPar *defpar)
7509 {
7510 // ActualPar::clone() is not implemented, since we need such a function
7511 // only here only for AP_{VALUE,TEMPLATE} parameters. AP_ERROR can also
7512 // happen for Def_Template nodes, but they will be errors later.
7513 // FIXME: This function is Def_Template specific.
7514 if (!defval.ti->get_Template() || defval.ti->get_Template()
7515 ->get_templatetype() != Template::TEMPLATE_NOTUSED)
7516 FATAL_ERROR("FormalPar::set_defval()");
7517 TemplateInstance *reversed_ti = 0;
7518 switch (defpar->get_selection()) {
7519 case ActualPar::AP_VALUE:
7520 reversed_ti = new TemplateInstance(type->clone(), 0, new Template
7521 (defpar->get_Value()->clone())); // Trust the clone().
7522 break;
7523 case ActualPar::AP_TEMPLATE:
7524 reversed_ti = defpar->get_TemplateInstance()->clone();
7525 break;
7526 case ActualPar::AP_ERROR:
7527 break; // Can happen, but let it go.
7528 case ActualPar::AP_REF:
7529 case ActualPar::AP_DEFAULT:
7530 default:
7531 FATAL_ERROR("FormalPar::set_defval()");
7532 }
7533 if (reversed_ti) {
7534 delete defval.ti;
7535 reversed_ti->set_my_scope(get_my_scope());
7536 defval.ti = reversed_ti;
7537 }
7538 }
7539
7540 ActualPar *FormalPar::chk_actual_par(TemplateInstance *actual_par,
7541 Type::expected_value_t exp_val)
7542 {
7543 if (!checked) chk();
7544 switch (asstype) {
7545 case A_PAR_VAL:
7546 case A_PAR_VAL_IN:
7547 return chk_actual_par_value(actual_par, exp_val);
7548 case A_PAR_VAL_OUT:
7549 case A_PAR_VAL_INOUT:
7550 return chk_actual_par_by_ref(actual_par, false, exp_val);
7551 case A_PAR_TEMPL_IN:
7552 return chk_actual_par_template(actual_par, exp_val);
7553 case A_PAR_TEMPL_OUT:
7554 case A_PAR_TEMPL_INOUT:
7555 return chk_actual_par_by_ref(actual_par, true, exp_val);
7556 case A_PAR_TIMER:
7557 return chk_actual_par_timer(actual_par, exp_val);
7558 case A_PAR_PORT:
7559 return chk_actual_par_port(actual_par, exp_val);
7560 default:
7561 FATAL_ERROR("FormalPar::chk_actual_par()");
7562 }
7563 return 0; // to avoid warnings
7564 }
7565
7566 ActualPar *FormalPar::chk_actual_par_value(TemplateInstance *actual_par,
7567 Type::expected_value_t exp_val)
7568 {
7569 actual_par->chk_Type(type);
7570 Ref_base *derived_ref = actual_par->get_DerivedRef();
7571 if (derived_ref) {
7572 derived_ref->error("An in-line modified template cannot be used as %s",
7573 get_assname());
7574 actual_par->chk_DerivedRef(type);
7575 }
7576 Template *ap_template = actual_par->get_Template();
7577 if (ap_template->is_Value()) {
7578 Value *v = ap_template->get_Value();
7579 v->set_my_governor(type);
7580 type->chk_this_value_ref(v);
7581 type->chk_this_value(v, 0, exp_val, INCOMPLETE_NOT_ALLOWED,
7582 OMIT_NOT_ALLOWED, SUB_CHK);
7583 return new ActualPar(v);
7584 } else {
7585 actual_par->error("A specific value without matching symbols "
7586 "was expected for a %s", get_assname());
7587 return new ActualPar();
7588 }
7589 }
7590
7591 static void chk_defpar_value(const Value* v)
7592 {
7593 Common::Reference *vref = v->get_reference();
7594 Common::Assignment *ass2 = vref->get_refd_assignment();
7595 ass2->chk();
7596 Scope *scope = ass2->get_my_scope();
7597 ComponentTypeBody *ctb = dynamic_cast<ComponentTypeBody *>(scope);
7598 if (ctb) { // this is a component variable
7599 v->error("default value cannot refer to"
7600 " a template field of the component in the `runs on' clause");
7601 }
7602 }
7603
7604 static void chk_defpar_template(const Template *body,
7605 Type::expected_value_t exp_val)
7606 {
7607 switch (body->get_templatetype()) {
7608 case Template::TEMPLATE_ERROR:
7609 break; // could be erroneous in the source; skip it
7610 case Template::TEMPLATE_NOTUSED:
7611 case Template::OMIT_VALUE:
7612 case Template::ANY_VALUE:
7613 case Template::ANY_OR_OMIT:
7614 break; // acceptable (?)
7615 case Template::TEMPLATE_INVOKE: // calling a function is not acceptable
7616 body->error("default value can not be a function invocation");
7617 break;
7618 case Template::VALUE_RANGE: {
7619 ValueRange *range = body->get_value_range();
7620 Value *low = range->get_min_v();
7621 Type::typetype_t tt_low = low->get_expr_returntype(exp_val);
7622 Value *high = range->get_max_v();
7623 Type::typetype_t tt_high = high->get_expr_returntype(exp_val);
7624 if (tt_low == tt_high) break;
7625 break; }
7626
7627 case Template::BSTR_PATTERN:
7628 case Template::HSTR_PATTERN:
7629 case Template::OSTR_PATTERN:
7630 case Template::CSTR_PATTERN:
7631 case Template::USTR_PATTERN:
7632 break; // should be acceptable in all cases (if only fixed strings possible)
7633
7634 case Template::SPECIFIC_VALUE: {
7635 Common::Value *v = body->get_specific_value();
7636 if (v->get_valuetype() == Value::V_REFD) chk_defpar_value(v);
7637 break; }
7638
7639 case Template::ALL_FROM:
7640 case Template::VALUE_LIST_ALL_FROM:
7641 FATAL_ERROR("should have been flattened");
7642 break;
7643 case Template::SUPERSET_MATCH:
7644 case Template::SUBSET_MATCH:
7645 case Template::PERMUTATION_MATCH:
7646 case Template::TEMPLATE_LIST:
7647 case Template::COMPLEMENTED_LIST:
7648 case Template::VALUE_LIST: {
7649 // in template charstring par := charstring : ("foo", "bar", "baz")
7650 size_t num = body->get_nof_comps();
7651 for (size_t i = 0; i < num; ++i) {
7652 const Template *tpl = body->get_temp_byIndex(i);
7653 chk_defpar_template(tpl, exp_val);
7654 }
7655 break; }
7656
7657 case Template::NAMED_TEMPLATE_LIST: {
7658 size_t num = body->get_nof_comps();
7659 for (size_t i = 0; i < num; ++i) {
7660 const NamedTemplate *nt = body->get_namedtemp_byIndex(i);
7661 const Template *tpl = nt->get_template();
7662 chk_defpar_template(tpl, exp_val);
7663 }
7664 break; }
7665
7666 case Template::INDEXED_TEMPLATE_LIST: {
7667 size_t num = body->get_nof_comps();
7668 for (size_t i = 0; i < num; ++i) {
7669 const IndexedTemplate *it = body->get_indexedtemp_byIndex(i);
7670 const Template *tpl = it->get_template();
7671 chk_defpar_template(tpl, exp_val);
7672 }
7673 break; }
7674
7675 case Template::TEMPLATE_REFD: {
7676 Ref_base *ref = body->get_reference();
7677
7678 Ttcn::ActualParList *aplist = ref->get_parlist();
7679 if (!aplist) break;
7680 size_t num = aplist->get_nof_pars();
7681 for (size_t i = 0; i < num; ++i) {
7682 const Ttcn::ActualPar *ap = aplist->get_par(i);
7683 deeper:
7684 switch (ap->get_selection()) {
7685 case ActualPar::AP_ERROR: {
7686 break; }
7687 case ActualPar::AP_VALUE: {
7688 Value *v = ap->get_Value(); // "v_variable" as the parameter of the template
7689 v->chk();
7690 switch (v->get_valuetype()) {
7691 case Value::V_REFD: {
7692 chk_defpar_value(v);
7693 break; }
7694 default:
7695 break;
7696 }
7697 break; }
7698 case ActualPar::AP_TEMPLATE: {
7699 // A component cannot contain a template definition, parameterized or not.
7700 // Therefore the template this actual par references, cannot be
7701 // a field of a component => no error possible, nothing to do.
7702 break; }
7703 case ActualPar::AP_REF: {
7704 // A template cannot have an out/inout parameter
7705 FATAL_ERROR("Template with out parameter?");
7706 break; }
7707 case ActualPar::AP_DEFAULT: {
7708 ap = ap->get_ActualPar();
7709 goto deeper;
7710 break; }
7711 // no default
7712 } // switch actual par selection
7713 } // next
7714
7715 break; }
7716 } // switch templatetype
7717
7718 }
7719
7720 // This function is called in two situations:
7721 // 1. FormalParList::chk calls FormalPar::chk to compute the default value
7722 // (make an ActualPar from a TemplateInstance).
7723 // In this case, defval.ti==0, and actual_par contains its old value.
7724 // This case is called only if the formal par has a default value.
7725 // 2. FormalParList::chk_actual_parlist calls FormalPar::chk_actual_par
7726 // to check the parameters supplied by the execute statement to the tc.
7727 // In this case, defval.ap has the value computed in case 1.
7728 ActualPar *FormalPar::chk_actual_par_template(TemplateInstance *actual_par,
7729 Type::expected_value_t exp_val)
7730 {
7731 actual_par->chk(type);
7732 // actual_par->template_body may change: SPECIFIC_VALUE to TEMPLATE_REFD
7733 Definition *fplist_def = my_parlist->get_my_def();
7734 // The parameter list belongs to this definition. If it's a function
7735 // or testcase, it may have a "runs on" clause.
7736 Def_Function *parent_fn = dynamic_cast<Def_Function *>(fplist_def);
7737 Type *runs_on_type = 0;
7738 if (parent_fn) runs_on_type = parent_fn->get_RunsOnType();
7739 else { // not a function; maybe a testcase
7740 Def_Testcase *parent_tc = dynamic_cast<Def_Testcase *>(fplist_def);
7741 if (parent_tc) runs_on_type = parent_tc->get_RunsOnType();
7742 }
7743 if (runs_on_type) {
7744 // If it _has_ a runs on clause, the type must be a component.
7745 if (runs_on_type->get_typetype() != Type::T_COMPONENT) FATAL_ERROR("not component?");
7746 // The default value "shall not refer to elements of the component type
7747 // in the runs on clause"
7748 ComponentTypeBody *runs_on_component = runs_on_type->get_CompBody();
7749 size_t compass = runs_on_component->get_nof_asss();
7750 for (size_t c = 0; c < compass; c++) {
7751 Assignment *ass = runs_on_component->get_ass_byIndex(c);
7752 (void)ass;
7753 }
7754 }
7755
7756 Ttcn::Template * body = actual_par->get_Template();
7757 if (exp_val == Type::EXPECTED_STATIC_VALUE
7758 ||exp_val == Type::EXPECTED_CONSTANT) {
7759 chk_defpar_template(body, exp_val);
7760 }
7761 // Rip out the type, derived ref and template from actual_par
7762 // (which may come from a function invocation or the definition
7763 // of the default value) and give it to the new ActualPar.
7764 ActualPar *ret_val = new ActualPar(
7765 new TemplateInstance(actual_par->get_Type(),
7766 actual_par->get_DerivedRef(), actual_par->get_Template()));
7767 // Zero out these members because the caller will soon call delete
7768 // on actual_par, but they now belong to ret_val.
7769 // FIXME: should this really be in here, or outside in the caller before the delete ?
7770 actual_par->release();
7771
7772 if (template_restriction!=TR_NONE) {
7773 bool needs_runtime_check =
7774 ret_val->get_TemplateInstance()->chk_restriction(
7775 "template formal parameter", template_restriction);
7776 if (needs_runtime_check)
7777 ret_val->set_gen_restriction_check(template_restriction);
7778 }
7779 return ret_val;
7780 }
7781
7782 ActualPar *FormalPar::chk_actual_par_by_ref(TemplateInstance *actual_par,
7783 bool is_template, Type::expected_value_t exp_val)
7784 {
7785 Type *ap_type = actual_par->get_Type();
7786 if (ap_type) {
7787 ap_type->warning("Explicit type specification is useless for an %s",
7788 get_assname());
7789 actual_par->chk_Type(type);
7790 }
7791 Ref_base *derived_ref = actual_par->get_DerivedRef();
7792 if (derived_ref) {
7793 derived_ref->error("An in-line modified template cannot be used as %s",
7794 get_assname());
7795 actual_par->chk_DerivedRef(type);
7796 }
7797 // needed for the error messages
7798 const char *expected_string = is_template ?
7799 "template variable or template parameter" :
7800 "variable or value parameter";
7801 Template *ap_template = actual_par->get_Template();
7802 if (ap_template->is_Ref()) {
7803 Ref_base *ref = ap_template->get_Ref();
7804 Common::Assignment *ass = ref->get_refd_assignment();
7805 if (!ass) {
7806 delete ref;
7807 return new ActualPar();
7808 }
7809 bool asstype_correct = false;
7810 switch (ass->get_asstype()) {
7811 case A_PAR_VAL_IN:
7812 ass->use_as_lvalue(*ref);
7813 if (get_asstype() == A_PAR_VAL_OUT || get_asstype() == A_PAR_TEMPL_OUT) {
7814 ass->warning("Passing an `in' parameter as another function's `out' parameter");
7815 }
7816 // no break
7817 case A_VAR:
7818 case A_PAR_VAL_OUT:
7819 case A_PAR_VAL_INOUT:
7820 if (!is_template) asstype_correct = true;
7821 break;
7822 case A_PAR_TEMPL_IN:
7823 ass->use_as_lvalue(*ref);
7824 if (get_asstype() == A_PAR_VAL_OUT || get_asstype() == A_PAR_TEMPL_OUT) {
7825 ass->warning("Passing an `in' parameter as another function's `out' parameter");
7826 }
7827 // no break
7828 case A_VAR_TEMPLATE:
7829 case A_PAR_TEMPL_OUT:
7830 case A_PAR_TEMPL_INOUT:
7831 if (is_template) asstype_correct = true;
7832 break;
7833 default:
7834 break;
7835 }
7836 if (asstype_correct) {
7837 FieldOrArrayRefs *t_subrefs = ref->get_subrefs();
7838 Type *ref_type = ass->get_Type()->get_field_type(t_subrefs, exp_val);
7839 if (ref_type) {
7840 if (!type->is_identical(ref_type)) {
7841 ref->error("Type mismatch: Reference to a %s of type "
7842 "`%s' was expected instead of `%s'", expected_string,
7843 type->get_typename().c_str(), ref_type->get_typename().c_str());
7844 } else if (type->get_sub_type() && ref_type->get_sub_type() &&
7845 (type->get_sub_type()->get_subtypetype()==ref_type->get_sub_type()->get_subtypetype()) &&
7846 (!type->get_sub_type()->is_compatible(ref_type->get_sub_type()))) {
7847 ref->error("Subtype mismatch: subtype %s has no common value with subtype %s",
7848 type->get_sub_type()->to_string().c_str(),
7849 ref_type->get_sub_type()->to_string().c_str());
7850 }
7851 if (t_subrefs && t_subrefs->refers_to_string_element()) {
7852 ref->error("Reference to a string element of type `%s' cannot be "
7853 "used in this context", ref_type->get_typename().c_str());
7854 }
7855 }
7856 } else {
7857 ref->error("Reference to a %s was expected for an %s instead of %s",
7858 expected_string, get_assname(), ass->get_description().c_str());
7859 }
7860 ActualPar* ret_val_ap = new ActualPar(ref);
7861 // restriction checking if this is a reference to a template variable
7862 // this is an 'out' or 'inout' template parameter
7863 if (is_template && asstype_correct) {
7864 template_restriction_t refd_tr;
7865 switch (ass->get_asstype()) {
7866 case A_VAR_TEMPLATE: {
7867 Def_Var_Template* dvt = dynamic_cast<Def_Var_Template*>(ass);
7868 if (!dvt) FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
7869 refd_tr = dvt->get_template_restriction();
7870 } break;
7871 case A_PAR_TEMPL_IN:
7872 case A_PAR_TEMPL_OUT:
7873 case A_PAR_TEMPL_INOUT: {
7874 FormalPar* fp = dynamic_cast<FormalPar*>(ass);
7875 if (!fp) FATAL_ERROR("Template::chk_restriction_refd()");
7876 refd_tr = fp->get_template_restriction();
7877 } break;
7878 default:
7879 FATAL_ERROR("FormalPar::chk_actual_par_by_ref()");
7880 break;
7881 }
7882 refd_tr = Template::get_sub_restriction(refd_tr, ref);
7883 if (template_restriction!=refd_tr) {
7884 bool pre_call_check =
7885 Template::is_less_restrictive(template_restriction, refd_tr);
7886 bool post_call_check =
7887 Template::is_less_restrictive(refd_tr, template_restriction);
7888 if (pre_call_check || post_call_check) {
7889 ref->warning("Inadequate restriction on the referenced %s `%s', "
7890 "this may cause a dynamic test case error at runtime",
7891 ass->get_assname(), ref->get_dispname().c_str());
7892 ass->note("Referenced %s is here", ass->get_assname());
7893 }
7894 if (pre_call_check)
7895 ret_val_ap->set_gen_restriction_check(template_restriction);
7896 if (post_call_check)
7897 ret_val_ap->set_gen_post_restriction_check(refd_tr);
7898 }
7899 // for out and inout template parameters of external functions
7900 // always check because we do not trust user written C++ code
7901 if (refd_tr!=TR_NONE) {
7902 switch (my_parlist->get_my_def()->get_asstype()) {
7903 case A_EXT_FUNCTION:
7904 case A_EXT_FUNCTION_RVAL:
7905 case A_EXT_FUNCTION_RTEMP:
7906 ret_val_ap->set_gen_post_restriction_check(refd_tr);
7907 break;
7908 default:
7909 break;
7910 }
7911 }
7912 }
7913 return ret_val_ap;
7914 } else {
7915 actual_par->error("Reference to a %s was expected for an %s",
7916 expected_string, get_assname());
7917 return new ActualPar();
7918 }
7919 }
7920
7921 ActualPar *FormalPar::chk_actual_par_timer(TemplateInstance *actual_par,
7922 Type::expected_value_t exp_val)
7923 {
7924 Type *ap_type = actual_par->get_Type();
7925 if (ap_type) {
7926 ap_type->error("Explicit type specification cannot be used for a "
7927 "timer parameter");
7928 actual_par->chk_Type(0);
7929 }
7930 Ref_base *derived_ref = actual_par->get_DerivedRef();
7931 if (derived_ref) {
7932 derived_ref->error("An in-line modified template cannot be used as "
7933 "timer parameter");
7934 actual_par->chk_DerivedRef(0);
7935 }
7936 Template *ap_template = actual_par->get_Template();
7937 if (ap_template->is_Ref()) {
7938 Ref_base *ref = ap_template->get_Ref();
7939 Common::Assignment *ass = ref->get_refd_assignment();
7940 if (!ass) {
7941 delete ref;
7942 return new ActualPar();
7943 }
7944 switch (ass->get_asstype()) {
7945 case A_TIMER: {
7946 ArrayDimensions *dims = ass->get_Dimensions();
7947 if (dims) dims->chk_indices(ref, "timer", false, exp_val);
7948 else if (ref->get_subrefs()) ref->error("Reference to single %s "
7949 "cannot have field or array sub-references",
7950 ass->get_description().c_str());
7951 break; }
7952 case A_PAR_TIMER:
7953 if (ref->get_subrefs()) ref->error("Reference to %s cannot have "
7954 "field or array sub-references", ass->get_description().c_str());
7955 break;
7956 default:
7957 ref->error("Reference to a timer or timer parameter was expected for "
7958 "a timer parameter instead of %s", ass->get_description().c_str());
7959 }
7960 return new ActualPar(ref);
7961 } else {
7962 actual_par->error("Reference to a timer or timer parameter was "
7963 "expected for a timer parameter");
7964 return new ActualPar();
7965 }
7966 }
7967
7968 ActualPar *FormalPar::chk_actual_par_port(TemplateInstance *actual_par,
7969 Type::expected_value_t exp_val)
7970 {
7971 Type *ap_type = actual_par->get_Type();
7972 if (ap_type) {
7973 ap_type->warning("Explicit type specification is useless for a port "
7974 "parameter");
7975 actual_par->chk_Type(type);
7976 }
7977 Ref_base *derived_ref = actual_par->get_DerivedRef();
7978 if (derived_ref) {
7979 derived_ref->error("An in-line modified template cannot be used as "
7980 "port parameter");
7981 actual_par->chk_DerivedRef(type);
7982 }
7983 Template *ap_template = actual_par->get_Template();
7984 if (ap_template->is_Ref()) {
7985 Ref_base *ref = ap_template->get_Ref();
7986 Common::Assignment *ass = ref->get_refd_assignment();
7987 if (!ass) {
7988 delete ref;
7989 return new ActualPar();
7990 }
7991 bool asstype_correct = false;
7992 switch (ass->get_asstype()) {
7993 case A_PORT: {
7994 ArrayDimensions *dims = ass->get_Dimensions();
7995 if (dims) dims->chk_indices(ref, "port", false, exp_val);
7996 else if (ref->get_subrefs()) ref->error("Reference to single %s "
7997 "cannot have field or array sub-references",
7998 ass->get_description().c_str());
7999 asstype_correct = true;
8000 break; }
8001 case A_PAR_PORT:
8002 if (ref->get_subrefs()) ref->error("Reference to %s cannot have "
8003 "field or array sub-references", ass->get_description().c_str());
8004 asstype_correct = true;
8005 break;
8006 default:
8007 ref->error("Reference to a port or port parameter was expected for a "
8008 "port parameter instead of %s", ass->get_description().c_str());
8009 }
8010 if (asstype_correct) {
8011 Type *ref_type = ass->get_Type();
8012 if (ref_type && !type->is_identical(ref_type))
8013 ref->error("Type mismatch: Reference to a port or port parameter "
8014 "of type `%s' was expected instead of `%s'",
8015 type->get_typename().c_str(), ref_type->get_typename().c_str());
8016 }
8017 return new ActualPar(ref);
8018 } else {
8019 actual_par->error("Reference to a port or port parameter was expected "
8020 "for a port parameter");
8021 return new ActualPar();
8022 }
8023 }
8024
8025 void FormalPar::use_as_lvalue(const Location& p_loc)
8026 {
8027 switch (asstype) {
8028 case A_PAR_VAL_IN:
8029 case A_PAR_TEMPL_IN:
8030 break;
8031 default:
8032 FATAL_ERROR("FormalPar::use_as_lvalue()");
8033 }
8034 if (!used_as_lvalue) {
8035 Definition *my_def = my_parlist->get_my_def();
8036 if (!my_def) FATAL_ERROR("FormalPar::use_as_lvalue()");
8037 if (my_def->get_asstype() == A_TEMPLATE)
8038 p_loc.error("Parameter `%s' of the template cannot be passed further "
8039 "as `out' or `inout' parameter", id->get_dispname().c_str());
8040 else {
8041 // update the genname so that all references in the generated code
8042 // will point to the shadow object
8043 if (!lazy_eval) {
8044 set_genname(id->get_name() + "_shadow");
8045 }
8046 used_as_lvalue = true;
8047 }
8048 }
8049 }
8050
8051 void FormalPar::generate_code_defval(output_struct *target, bool)
8052 {
8053 if (!defval.ap) return;
8054 switch (defval.ap->get_selection()) {
8055 case ActualPar::AP_VALUE: {
8056 Value *val = defval.ap->get_Value();
8057 const_def cdef;
8058 Code::init_cdef(&cdef);
8059 type->generate_code_object(&cdef, val);
8060 Code::merge_cdef(target, &cdef);
8061 Code::free_cdef(&cdef);
8062 if (use_runtime_2 && TypeConv::needs_conv_refd(val)) {
8063 target->functions.post_init = TypeConv::gen_conv_code_refd(target->
8064 functions.post_init, val->get_lhs_name().c_str(), val);
8065 } else {
8066 target->functions.post_init = val->generate_code_init(
8067 target->functions.post_init, val->get_lhs_name().c_str());
8068 }
8069 break; }
8070 case ActualPar::AP_TEMPLATE: {
8071 TemplateInstance *ti = defval.ap->get_TemplateInstance();
8072 Template *temp = ti->get_Template();
8073 const_def cdef;
8074 Code::init_cdef(&cdef);
8075 type->generate_code_object(&cdef, temp);
8076 Code::merge_cdef(target, &cdef);
8077 Code::free_cdef(&cdef);
8078 Ref_base *dref = ti->get_DerivedRef();
8079 if (dref) {
8080 expression_struct expr;
8081 Code::init_expr(&expr);
8082 expr.expr = mputprintf(expr.expr, "%s = ",
8083 temp->get_lhs_name().c_str());
8084 dref->generate_code(&expr);
8085 target->functions.post_init =
8086 Code::merge_free_expr(target->functions.post_init, &expr, false);
8087 }
8088 if (use_runtime_2 && TypeConv::needs_conv_refd(temp)) {
8089 target->functions.post_init = TypeConv::gen_conv_code_refd(target->
8090 functions.post_init, temp->get_lhs_name().c_str(), temp);
8091 } else {
8092 target->functions.post_init =
8093 temp->generate_code_init(target->functions.post_init,
8094 temp->get_lhs_name().c_str());
8095 }
8096 if (defval.ap->get_gen_restriction_check() != TR_NONE) {
8097 target->functions.post_init =
8098 Template::generate_restriction_check_code(
8099 target->functions.post_init, temp->get_lhs_name().c_str(),
8100 defval.ap->get_gen_restriction_check());
8101 }
8102 break; }
8103 case ActualPar::AP_REF:
8104 break;
8105 default:
8106 FATAL_ERROR("FormalPar::generate_code()");
8107 }
8108 }
8109
8110 char *FormalPar::generate_code_fpar(char *str)
8111 {
8112 const char *name_str = id->get_name().c_str();
8113 switch (asstype) {
8114 case A_PAR_VAL_IN:
8115 if (lazy_eval) {
8116 str = mputprintf(str, "Lazy_Param<%s>& %s", type->get_genname_value(my_scope).c_str(), name_str);
8117 } else {
8118 str = mputprintf(str, "const %s& %s", type->get_genname_value(my_scope).c_str(), name_str);
8119 }
8120 break;
8121 case A_PAR_VAL_OUT:
8122 case A_PAR_VAL_INOUT:
8123 case A_PAR_PORT:
8124 str = mputprintf(str, "%s& %s", type->get_genname_value(my_scope).c_str(),
8125 name_str);
8126 break;
8127 case A_PAR_TEMPL_IN:
8128 if (lazy_eval) {
8129 str = mputprintf(str, "Lazy_Param<%s>& %s", type->get_genname_template(my_scope).c_str(), name_str);
8130 } else {
8131 str = mputprintf(str, "const %s& %s", type->get_genname_template(my_scope).c_str(), name_str);
8132 }
8133 break;
8134 case A_PAR_TEMPL_OUT:
8135 case A_PAR_TEMPL_INOUT:
8136 str = mputprintf(str, "%s& %s",
8137 type->get_genname_template(my_scope).c_str(), name_str);
8138 break;
8139 case A_PAR_TIMER:
8140 str = mputprintf(str, "TIMER& %s", name_str);
8141 break;
8142 default:
8143 FATAL_ERROR("FormalPar::generate_code()");
8144 }
8145 return str;
8146 }
8147
8148 string FormalPar::get_reference_name(Scope* scope) const
8149 {
8150 string ret_val;
8151 if (lazy_eval) {
8152 ret_val += "((";
8153 switch (asstype) {
8154 case A_PAR_TEMPL_IN:
8155 ret_val += type->get_genname_template(scope);
8156 break;
8157 default:
8158 ret_val += type->get_genname_value(scope);
8159 break;
8160 }
8161 ret_val += "&)";
8162 }
8163 ret_val += get_id().get_name();
8164 if (lazy_eval) {
8165 ret_val += ")";
8166 }
8167 return ret_val;
8168 }
8169
8170 char *FormalPar::generate_code_object(char *str, const char *p_prefix, char refch)
8171 {
8172 const char *name_str = id->get_name().c_str();
8173 switch (asstype) {
8174 case A_PAR_VAL_IN:
8175 if (lazy_eval) {
8176 str = mputprintf(str, "Lazy_Param<%s> %s%s;\n", type->get_genname_value(my_scope).c_str(), p_prefix, name_str);
8177 } else {
8178 str = mputprintf(str, "%s %s%s;\n", type->get_genname_value(my_scope).c_str(), p_prefix, name_str);
8179 }
8180 break;
8181 case A_PAR_VAL_OUT:
8182 case A_PAR_VAL_INOUT:
8183 case A_PAR_PORT:
8184 str = mputprintf(str, "%s%c %s%s;\n",
8185 type->get_genname_value(my_scope).c_str(), refch, p_prefix, name_str);
8186 break;
8187 case A_PAR_TEMPL_IN:
8188 if (lazy_eval) {
8189 str = mputprintf(str, "Lazy_Param<%s> %s%s;\n", type->get_genname_template(my_scope).c_str(), p_prefix, name_str);
8190 } else {
8191 str = mputprintf(str, "%s %s%s;\n", type->get_genname_template(my_scope).c_str(), p_prefix, name_str);
8192 }
8193 break;
8194 case A_PAR_TEMPL_OUT:
8195 case A_PAR_TEMPL_INOUT:
8196 str = mputprintf(str, "%s%c %s%s;\n",
8197 type->get_genname_template(my_scope).c_str(), refch, p_prefix, name_str);
8198 break;
8199 case A_PAR_TIMER:
8200 str = mputprintf(str, "TIMER& %s%s;\n", p_prefix, name_str);
8201 break;
8202 default:
8203 FATAL_ERROR("FormalPar::generate_code_object()");
8204 }
8205 return str;
8206 }
8207
8208 char *FormalPar::generate_shadow_object(char *str) const
8209 {
8210 if (used_as_lvalue && !lazy_eval) {
8211 const string& t_genname = get_genname();
8212 const char *genname_str = t_genname.c_str();
8213 const char *name_str = id->get_name().c_str();
8214 switch (asstype) {
8215 case A_PAR_VAL_IN:
8216 str = mputprintf(str, "%s %s(%s);\n",
8217 type->get_genname_value(my_scope).c_str(), genname_str, name_str);
8218 break;
8219 case A_PAR_TEMPL_IN:
8220 str = mputprintf(str, "%s %s(%s);\n",
8221 type->get_genname_template(my_scope).c_str(), genname_str, name_str);
8222 break;
8223 default:
8224 FATAL_ERROR("FormalPar::generate_shadow_object()");
8225 }
8226 }
8227 return str;
8228 }
8229
8230 char *FormalPar::generate_code_set_unbound(char *str) const
8231 {
8232 switch (asstype) {
8233 case A_PAR_TEMPL_OUT:
8234 case A_PAR_VAL_OUT:
8235 str = mputprintf(str, "%s.clean_up();\n", id->get_name().c_str());
8236 break;
8237 default:
8238 break;
8239 }
8240 return str;
8241 }
8242
8243 void FormalPar::dump_internal(unsigned level) const
8244 {
8245 DEBUG(level, "%s: %s", get_assname(), id->get_dispname().c_str());
8246 if (type) type->dump(level + 1);
8247 if (checked) {
8248 if (defval.ap) {
8249 DEBUG(level + 1, "default value:");
8250 defval.ap->dump(level + 2);
8251 }
8252 } else {
8253 if (defval.ti) {
8254 DEBUG(level + 1, "default value:");
8255 defval.ti->dump(level + 2);
8256 }
8257 }
8258 }
8259
8260 // =================================
8261 // ===== FormalParList
8262 // =================================
8263
8264 FormalParList::~FormalParList()
8265 {
8266 size_t nof_pars = pars_v.size();
8267 for (size_t i = 0; i < nof_pars; i++) delete pars_v[i];
8268 pars_v.clear();
8269 pars_m.clear();
8270 }
8271
8272 FormalParList *FormalParList::clone() const
8273 {
8274 FATAL_ERROR("FormalParList::clone");
8275 }
8276
8277 void FormalParList::set_fullname(const string& p_fullname)
8278 {
8279 Node::set_fullname(p_fullname);
8280 for (size_t i = 0; i < pars_v.size(); i++) {
8281 FormalPar *par = pars_v[i];
8282 par->set_fullname(p_fullname + "." + par->get_id().get_dispname());
8283 }
8284 }
8285
8286 void FormalParList::set_my_scope(Scope *p_scope)
8287 {
8288 set_parent_scope(p_scope);
8289 Node::set_my_scope(p_scope);
8290 // the scope of parameters is set to the parent scope instead of this
8291 // because they cannot refer to each other
8292 for (size_t i = 0; i < pars_v.size(); i++) pars_v[i]->set_my_scope(p_scope);
8293 }
8294
8295 void FormalParList::add_fp(FormalPar *p_fp)
8296 {
8297 if (!p_fp) FATAL_ERROR("NULL parameter: Ttcn::FormalParList::add_fp()");
8298 pars_v.add(p_fp);
8299 p_fp->set_my_parlist(this);
8300 checked = false;
8301 }
8302
8303 bool FormalParList::has_notused_defval() const
8304 {
8305 for (size_t i = 0; i < pars_v.size(); i++) {
8306 if (pars_v[i]->has_notused_defval())
8307 return true;
8308 }
8309 return false;
8310 }
8311
8312 bool FormalParList::has_only_default_values() const
8313 {
8314 for (size_t i = 0; i < pars_v.size(); i++) {
8315 if (!pars_v[i]->has_defval()) {
8316 return false;
8317 }
8318 }
8319
8320 return true;
8321 }
8322
8323 bool FormalParList::has_fp_withName(const Identifier& p_name)
8324 {
8325 if (!checked) chk(Definition::A_UNDEF);
8326 return pars_m.has_key(p_name.get_name());
8327 }
8328
8329 FormalPar *FormalParList::get_fp_byName(const Identifier& p_name)
8330 {
8331 if (!checked) chk(Definition::A_UNDEF);
8332 return pars_m[p_name.get_name()];
8333 }
8334
8335 bool FormalParList::get_startability()
8336 {
8337 if(!checked) FATAL_ERROR("FormalParList::get_startability()");
8338 return is_startable;
8339 }
8340
8341 Common::Assignment *FormalParList::get_ass_bySRef(Common::Ref_simple *p_ref)
8342 {
8343 if (!p_ref || !checked) FATAL_ERROR("FormalParList::get_ass_bySRef()");
8344 if (p_ref->get_modid()) return parent_scope->get_ass_bySRef(p_ref);
8345 else {
8346 const string& name = p_ref->get_id()->get_name();
8347 if (pars_m.has_key(name)) return pars_m[name];
8348 else return parent_scope->get_ass_bySRef(p_ref);
8349 }
8350 }
8351
8352 bool FormalParList::has_ass_withId(const Identifier& p_id)
8353 {
8354 if (!checked) FATAL_ERROR("Ttcn::FormalParList::has_ass_withId()");
8355 return pars_m.has_key(p_id.get_name())
8356 || parent_scope->has_ass_withId(p_id);
8357 }
8358
8359 void FormalParList::set_genname(const string& p_prefix)
8360 {
8361 for (size_t i = 0; i < pars_v.size(); i++) {
8362 FormalPar *par = pars_v[i];
8363 const string& par_name = par->get_id().get_name();
8364 if (par->get_asstype() != Definition::A_PAR_TIMER)
8365 par->get_Type()->set_genname(p_prefix, par_name);
8366 if (par->has_defval()) {
8367 string embedded_genname(p_prefix);
8368 embedded_genname += '_';
8369 embedded_genname += par_name;
8370 embedded_genname += "_defval";
8371 ActualPar *defval = par->get_defval();
8372 switch (defval->get_selection()) {
8373 case ActualPar::AP_ERROR:
8374 case ActualPar::AP_REF:
8375 break;
8376 case ActualPar::AP_VALUE: {
8377 Value *v = defval->get_Value();
8378 v->set_genname_prefix("const_");
8379 v->set_genname_recursive(embedded_genname);
8380 break; }
8381 case ActualPar::AP_TEMPLATE: {
8382 Template *t = defval->get_TemplateInstance()->get_Template();
8383 t->set_genname_prefix("template_");
8384 t->set_genname_recursive(embedded_genname);
8385 break; }
8386 default:
8387 FATAL_ERROR("FormalParList::set_genname()");
8388 }
8389 }
8390 }
8391 }
8392
8393 void FormalParList::chk(Definition::asstype_t deftype)
8394 {
8395 if (checked) return;
8396 checked = true;
8397 min_nof_pars = 0;
8398 is_startable = true;
8399 Error_Context cntxt(this, "In formal parameter list");
8400 for (size_t i = 0; i < pars_v.size(); i++) {
8401 FormalPar *par = pars_v[i];
8402 const Identifier& id = par->get_id();
8403 const string& name = id.get_name();
8404 const char *dispname = id.get_dispname().c_str();
8405 if (pars_m.has_key(name)) {
8406 par->error("Duplicate parameter with name `%s'", dispname);
8407 pars_m[name]->note("Previous definition of `%s' is here", dispname);
8408 } else {
8409 pars_m.add(name, par);
8410 if (parent_scope && parent_scope->has_ass_withId(id)) {
8411 par->error("Parameter name `%s' is not unique in the scope "
8412 "hierarchy", dispname);
8413 Reference ref(0, id.clone());
8414 Common::Assignment *ass = parent_scope->get_ass_bySRef(&ref);
8415 if (!ass) FATAL_ERROR("FormalParList::chk()");
8416 ass->note("Symbol `%s' is already defined here in a higher scope "
8417 "unit", dispname);
8418 }
8419 }
8420 Error_Context cntxt2(par, "In parameter `%s'", dispname);
8421 par->chk();
8422 // check whether the parameter type is allowed
8423 switch (deftype) {
8424 case Definition::A_TEMPLATE:
8425 switch (par->get_asstype()) {
8426 case Definition::A_PAR_VAL_IN:
8427 case Definition::A_PAR_TEMPL_IN:
8428 // these are allowed
8429 break;
8430 default:
8431 par->error("A template cannot have %s", par->get_assname());
8432 }
8433 break;
8434 case Definition::A_TESTCASE:
8435 switch (par->get_asstype()) {
8436 case Definition::A_PAR_TIMER:
8437 case Definition::A_PAR_PORT:
8438 // these are forbidden
8439 par->error("A testcase cannot have %s", par->get_assname());
8440 default:
8441 break;
8442 }
8443 default:
8444 // everything is allowed for functions and altsteps
8445 break;
8446 }
8447 //startability chk
8448 switch(par->get_asstype()) {
8449 case Common::Assignment::A_PAR_VAL_IN:
8450 case Common::Assignment::A_PAR_TEMPL_IN:
8451 case Common::Assignment::A_PAR_VAL_INOUT:
8452 case Common::Assignment::A_PAR_TEMPL_INOUT:
8453 if (is_startable && par->get_Type()->is_component_internal())
8454 is_startable = false;
8455 break;
8456 default:
8457 is_startable = false;
8458 break;
8459 }
8460 if (!par->has_defval()) min_nof_pars = i + 1;
8461 // the last parameter without a default value determines the minimum
8462 }
8463 }
8464
8465 // check that @lazy paramterization not used in cases currently unsupported
8466 void FormalParList::chk_noLazyParams() {
8467 Error_Context cntxt(this, "In formal parameter list");
8468 for (size_t i = 0; i < pars_v.size(); i++) {
8469 FormalPar *par = pars_v[i];
8470 if (par->get_lazy_eval()) {
8471 par->error("Formal parameter `%s' cannot be @lazy, not supported in this case.",
8472 par->get_id().get_dispname().c_str());
8473 }
8474 }
8475 }
8476
8477 void FormalParList::chk_startability(const char *p_what, const char *p_name)
8478 {
8479 if(!checked) FATAL_ERROR("FormalParList::chk_startability()");
8480 if (is_startable) return;
8481 for (size_t i = 0; i < pars_v.size(); i++) {
8482 FormalPar *par = pars_v[i];
8483 switch (par->get_asstype()) {
8484 case Common::Assignment::A_PAR_VAL_IN:
8485 case Common::Assignment::A_PAR_TEMPL_IN:
8486 case Common::Assignment::A_PAR_VAL_INOUT:
8487 case Common::Assignment::A_PAR_TEMPL_INOUT:
8488 if (par->get_Type()->is_component_internal()) {
8489 map<Type*,void> type_chain;
8490 char* err_str = mprintf("a parameter or embedded in a parameter of "
8491 "a function used in a start operation. "
8492 "%s `%s' cannot be started on a parallel test component "
8493 "because of `%s'", p_what, p_name, par->get_description().c_str());
8494 par->get_Type()->chk_component_internal(type_chain, err_str);
8495 Free(err_str);
8496 }
8497 break;
8498 default:
8499 par->error("%s `%s' cannot be started on a parallel test component "
8500 "because it has %s", p_what, p_name, par->get_description().c_str());
8501 }
8502 }
8503 }
8504
8505 void FormalParList::chk_compatibility(FormalParList* p_fp_list,
8506 const char* where)
8507 {
8508 size_t nof_type_pars = pars_v.size();
8509 size_t nof_function_pars = p_fp_list->pars_v.size();
8510 // check for the number of parameters
8511 if (nof_type_pars != nof_function_pars) {
8512 p_fp_list->error("Too %s parameters: %lu was expected instead of %lu",
8513 nof_type_pars < nof_function_pars ? "many" : "few",
8514 (unsigned long) nof_type_pars, (unsigned long) nof_function_pars);
8515 }
8516 size_t upper_limit =
8517 nof_type_pars < nof_function_pars ? nof_type_pars : nof_function_pars;
8518 for (size_t i = 0; i < upper_limit; i++) {
8519 FormalPar *type_par = pars_v[i];
8520 FormalPar *function_par = p_fp_list->pars_v[i];
8521 Error_Context cntxt(function_par, "In parameter #%lu",
8522 (unsigned long) (i + 1));
8523 FormalPar::asstype_t type_par_asstype = type_par->get_asstype();
8524 FormalPar::asstype_t function_par_asstype = function_par->get_asstype();
8525 // check for parameter kind equivalence
8526 // (in, out or inout / value or template)
8527 if (type_par_asstype != function_par_asstype) {
8528 function_par->error("The kind of the parameter is not the same as in "
8529 "type `%s': %s was expected instead of %s", where,
8530 type_par->get_assname(), function_par->get_assname());
8531 }
8532 // check for type equivalence
8533 if (type_par_asstype != FormalPar::A_PAR_TIMER &&
8534 function_par_asstype != FormalPar::A_PAR_TIMER) {
8535 Type *type_par_type = type_par->get_Type();
8536 Type *function_par_type = function_par->get_Type();
8537 if (!type_par_type->is_identical(function_par_type)) {
8538 function_par_type->error("The type of the parameter is not the same "
8539 "as in type `%s': `%s' was expected instead of `%s'", where,
8540 type_par_type->get_typename().c_str(),
8541 function_par_type->get_typename().c_str());
8542 } else if (type_par_type->get_sub_type() && function_par_type->get_sub_type() &&
8543 (type_par_type->get_sub_type()->get_subtypetype()==function_par_type->get_sub_type()->get_subtypetype()) &&
8544 (!type_par_type->get_sub_type()->is_compatible(function_par_type->get_sub_type()))) {
8545 // TODO: maybe equivalence should be checked, or maybe that is too strict
8546 function_par_type->error(
8547 "Subtype mismatch: subtype %s has no common value with subtype %s",
8548 type_par_type->get_sub_type()->to_string().c_str(),
8549 function_par_type->get_sub_type()->to_string().c_str());
8550 }
8551 }
8552 // check for template restriction equivalence
8553 if (type_par->get_template_restriction()!=
8554 function_par->get_template_restriction()) {
8555 function_par->error("The template restriction of the parameter is "
8556 "not the same as in type `%s': %s restriction was expected instead "
8557 "of %s restriction", where,
8558 type_par->get_template_restriction()==TR_NONE ? "no" :
8559 Template::get_restriction_name(type_par->get_template_restriction()),
8560 function_par->get_template_restriction()==TR_NONE ? "no" :
8561 Template::get_restriction_name(function_par->
8562 get_template_restriction()));
8563 }
8564 // check for @lazy equivalence
8565 if (type_par->get_lazy_eval()!=function_par->get_lazy_eval()) {
8566 function_par->error("Parameter @lazy-ness mismatch");
8567 }
8568 // check for name equivalence
8569 const Identifier& type_par_id = type_par->get_id();
8570 const Identifier& function_par_id = function_par->get_id();
8571 if (type_par_id != function_par_id) {
8572 function_par->warning("The name of the parameter is not the same "
8573 "as in type `%s': `%s' was expected instead of `%s'", where,
8574 type_par_id.get_dispname().c_str(),
8575 function_par_id.get_dispname().c_str());
8576 }
8577 }
8578 }
8579
8580 bool FormalParList::fold_named_and_chk(ParsedActualParameters *p_paps,
8581 ActualParList *p_aplist)
8582 {
8583 const size_t num_named = p_paps->get_nof_nps();
8584 const size_t num_unnamed = p_paps->get_nof_tis();
8585 size_t num_actual = num_unnamed;
8586
8587 // Construct a map to tell us what index a FormalPar has
8588 typedef map<FormalPar*, size_t> formalpar_map_t;
8589 formalpar_map_t formalpar_map;
8590
8591 size_t num_fp = get_nof_fps();
8592 for (size_t fpx = 0; fpx < num_fp; ++fpx) {
8593 FormalPar *fp = get_fp_byIndex(fpx);
8594 formalpar_map.add(fp, new size_t(fpx));
8595 }
8596
8597 // Go through the named parameters
8598 for (size_t i = 0; i < num_named; ++i) {
8599 NamedParam *np = p_paps->extract_np_byIndex(i);
8600 // We are now responsible for np.
8601
8602 if (has_fp_withName(*np->get_name())) {
8603 // there is a formal parameter with that name
8604 FormalPar *fp = get_fp_byName(*np->get_name());
8605 const size_t is_at = *formalpar_map[fp]; // the index of the formal par
8606 if (is_at >= num_actual) {
8607 // There is no actual par in the unnamed part.
8608 // Create one from the named param.
8609
8610 // First, pad the gap with '-'
8611 for (; num_actual < is_at; ++num_actual) {
8612 Template *not_used;
8613 if (pars_v[num_actual]->has_defval()) {
8614 not_used = new Template(Template::TEMPLATE_NOTUSED);
8615 }
8616 else { // cannot use '-' if no default value
8617 not_used = new Template(Template::TEMPLATE_ERROR);
8618 }
8619 TemplateInstance *new_ti = new TemplateInstance(0, 0, not_used);
8620 // Conjure a location info at the beginning of the unnamed part
8621 // (that is, the beginning of the actual parameter list)
8622 new_ti->set_location(p_paps->get_tis()->get_filename(),
8623 p_paps->get_tis()->get_first_line(),
8624 p_paps->get_tis()->get_first_column(), 0, 0);
8625 p_paps->get_tis()->add_ti(new_ti);
8626 }
8627 TemplateInstance * namedti = np->extract_ti();
8628 p_paps->get_tis()->add_ti(namedti);
8629 ++num_actual;
8630 } else {
8631 // There is already an actual par at that position, fetch it
8632 TemplateInstance * ti = p_paps->get_tis()->get_ti_byIndex(is_at);
8633 Template::templatetype_t tt = ti->get_Template()->get_templatetype();
8634
8635 if (is_at >= num_unnamed && !ti->get_Type() && !ti->get_DerivedRef()
8636 && (tt == Template::TEMPLATE_NOTUSED || tt == Template::TEMPLATE_ERROR)) {
8637 // NotUsed in the named part => padding
8638 np->error("Named parameter `%s' out of order",
8639 np->get_name()->get_dispname().c_str());
8640 } else {
8641 // attempt to override an original unnamed param with a named one
8642 np->error("Formal parameter `%s' assigned more than once",
8643 np->get_name()->get_dispname().c_str());
8644 }
8645 }
8646 }
8647 else { // no formal parameter with that name
8648 char * nam = 0;
8649 switch (my_def->get_asstype()) {
8650 case Common::Assignment::A_TYPE: {
8651 Type *t = my_def->get_Type();
8652
8653 switch (t ? t->get_typetype() : 0) {
8654 case Type::T_FUNCTION:
8655 nam = mcopystr("Function reference");
8656 break;
8657 case Type::T_ALTSTEP:
8658 nam = mcopystr("Altstep reference");
8659 break;
8660 case Type::T_TESTCASE:
8661 nam = mcopystr("Testcase reference");
8662 break;
8663 default:
8664 FATAL_ERROR("FormalParList::chk_actual_parlist() "
8665 "Unexpected type %s", t->get_typename().c_str());
8666 } // switch(typetype)
8667 break; }
8668 default:
8669 nam = mcopystr(my_def->get_assname());
8670 break;
8671 } // switch(asstype)
8672
8673 *nam &= ~('a'-'A'); // Make the first letter uppercase
8674 p_paps->get_tis()->error("%s `%s' has no formal parameter `%s'",
8675 nam,
8676 my_def->get_fullname().c_str(),
8677 np->get_name()->get_dispname().c_str());
8678 Free(nam);
8679 }
8680 delete np;
8681 }
8682
8683 // Cleanup
8684 for (size_t fpx = 0; fpx < num_fp; ++fpx) {
8685 delete formalpar_map.get_nth_elem(fpx);
8686 }
8687 formalpar_map.clear();
8688
8689 return chk_actual_parlist(p_paps->get_tis(), p_aplist);
8690 }
8691
8692 bool FormalParList::chk_actual_parlist(TemplateInstances *p_tis,
8693 ActualParList *p_aplist)
8694 {
8695 size_t formal_pars = pars_v.size();
8696 size_t actual_pars = p_tis->get_nof_tis();
8697 // p_aplist->get_nof_pars() is usually 0 on entry
8698 bool error_flag = false;
8699
8700 if (min_nof_pars == formal_pars) {
8701 // none of the parameters have default value
8702 if (actual_pars != formal_pars) {
8703 p_tis->error("Too %s parameters: %lu was expected "
8704 "instead of %lu", actual_pars < formal_pars ? "few" : "many",
8705 (unsigned long) formal_pars, (unsigned long) actual_pars);
8706 error_flag = true;
8707 }
8708 } else {
8709 // some parameters have default value
8710 if (actual_pars < min_nof_pars) {
8711 p_tis->error("Too few parameters: at least %lu "
8712 "was expected instead of %lu",
8713 (unsigned long) min_nof_pars, (unsigned long) actual_pars);
8714 error_flag = true;
8715 } else if (actual_pars > formal_pars) {
8716 p_tis->error("Too many parameters: at most %lu "
8717 "was expected instead of %lu",
8718 (unsigned long) formal_pars, (unsigned long) actual_pars);
8719 error_flag = true;
8720 }
8721 }
8722
8723 // Do not check actual parameters in excess of the formal ones
8724 size_t upper_limit = actual_pars < formal_pars ? actual_pars : formal_pars;
8725 for (size_t i = 0; i < upper_limit; i++) {
8726 TemplateInstance *ti = p_tis->get_ti_byIndex(i);
8727
8728 // the formal parameter for the current actual parameter
8729 FormalPar *fp = pars_v[i];
8730 Error_Context cntxt(ti, "In parameter #%lu for `%s'",
8731 (unsigned long) (i + 1), fp->get_id().get_dispname().c_str());
8732 if (!ti->get_Type() && !ti->get_DerivedRef() && ti->get_Template()
8733 ->get_templatetype() == Template::TEMPLATE_NOTUSED) {
8734 if (fp->has_defval()) {
8735 ActualPar *defval = fp->get_defval();
8736 p_aplist->add(new ActualPar(defval));
8737 if (defval->is_erroneous()) error_flag = true;
8738 } else {
8739 ti->error("Not used symbol (`-') cannot be used for parameter "
8740 "that does not have default value");
8741 p_aplist->add(new ActualPar());
8742 error_flag = true;
8743 }
8744 } else if (!ti->get_Type() && !ti->get_DerivedRef() && ti->get_Template()
8745 ->get_templatetype() == Template::TEMPLATE_ERROR) {
8746 ti->error("Parameter not specified");
8747 } else {
8748 ActualPar *ap = fp->chk_actual_par(ti, Type::EXPECTED_DYNAMIC_VALUE);
8749 p_aplist->add(ap);
8750 if (ap->is_erroneous()) error_flag = true;
8751 }
8752 }
8753
8754 // The rest of formal parameters have no corresponding actual parameters.
8755 // Create actual parameters for them based on their default values
8756 // (which must exist).
8757 for (size_t i = upper_limit; i < formal_pars; i++) {
8758 FormalPar *fp = pars_v[i];
8759 if (fp->has_defval()) {
8760 ActualPar *defval = fp->get_defval();
8761 p_aplist->add(new ActualPar(defval));
8762 if (defval->is_erroneous()) error_flag = true;
8763 } else {
8764 p_aplist->add(new ActualPar()); // erroneous
8765 error_flag = true;
8766 }
8767 }
8768 return error_flag;
8769 }
8770
8771 bool FormalParList::chk_activate_argument(ActualParList *p_aplist,
8772 const char* p_description)
8773 {
8774 bool ret_val = true;
8775 for(size_t i = 0; i < p_aplist->get_nof_pars(); i++) {
8776 ActualPar *t_ap = p_aplist->get_par(i);
8777 if(t_ap->get_selection() != ActualPar::AP_REF) continue;
8778 FormalPar *t_fp = pars_v[i];
8779 switch(t_fp->get_asstype()) {
8780 case Common::Assignment::A_PAR_VAL_OUT:
8781 case Common::Assignment::A_PAR_VAL_INOUT:
8782 case Common::Assignment::A_PAR_TEMPL_OUT:
8783 case Common::Assignment::A_PAR_TEMPL_INOUT:
8784 case Common::Assignment::A_PAR_TIMER:
8785 //the checking shall be performed for these parameter types
8786 break;
8787 case Common::Assignment::A_PAR_PORT:
8788 // port parameters are always correct because ports can be defined
8789 // only in component types
8790 continue;
8791 default:
8792 FATAL_ERROR("FormalParList::chk_activate_argument()");
8793 }
8794 Ref_base *t_ref = t_ap->get_Ref();
8795 Common::Assignment *t_par_ass = t_ref->get_refd_assignment();
8796 if(!t_par_ass) FATAL_ERROR("FormalParList::chk_activate_argument()");
8797 switch (t_par_ass->get_asstype()) {
8798 case Common::Assignment::A_VAR:
8799 case Common::Assignment::A_VAR_TEMPLATE:
8800 case Common::Assignment::A_TIMER:
8801 // it is not allowed to pass references of local variables or timers
8802 if (t_par_ass->is_local()) {
8803 t_ref->error("Parameter #%lu of %s refers to %s, which is a local "
8804 "definition within a statement block and may have shorter "
8805 "lifespan than the activated default. Only references to "
8806 "variables and timers defined in the component type can be passed "
8807 "to activated defaults", (unsigned long) (i + 1), p_description,
8808 t_par_ass->get_description().c_str());
8809 ret_val = false;
8810 }
8811 break;
8812 case Common::Assignment::A_PAR_VAL_IN:
8813 case Common::Assignment::A_PAR_VAL_OUT:
8814 case Common::Assignment::A_PAR_VAL_INOUT:
8815 case Common::Assignment::A_PAR_TEMPL_IN:
8816 case Common::Assignment::A_PAR_TEMPL_OUT:
8817 case Common::Assignment::A_PAR_TEMPL_INOUT:
8818 case Common::Assignment::A_PAR_TIMER: {
8819 // it is not allowed to pass references pointing to formal parameters
8820 // except for activate() statements within testcases
8821 // note: all defaults are deactivated at the end of the testcase
8822 FormalPar *t_refd_fp = dynamic_cast<FormalPar*>(t_par_ass);
8823 if (!t_refd_fp) FATAL_ERROR("FormalParList::chk_activate_argument()");
8824 FormalParList *t_fpl = t_refd_fp->get_my_parlist();
8825 if (!t_fpl || !t_fpl->my_def)
8826 FATAL_ERROR("FormalParList::chk_activate_argument()");
8827 if (t_fpl->my_def->get_asstype() != Common::Assignment::A_TESTCASE) {
8828 t_ref->error("Parameter #%lu of %s refers to %s, which may have "
8829 "shorter lifespan than the activated default. Only references to "
8830 "variables and timers defined in the component type can be passed "
8831 "to activated defaults", (unsigned long) (i + 1), p_description,
8832 t_par_ass->get_description().c_str());
8833 ret_val = false;
8834 } }
8835 default:
8836 break;
8837 }
8838 }
8839 return ret_val;
8840 }
8841
8842 char *FormalParList::generate_code(char *str)
8843 {
8844 for (size_t i = 0; i < pars_v.size(); i++) {
8845 if (i > 0) str = mputstr(str, ", ");
8846 str = pars_v[i]->generate_code_fpar(str);
8847 }
8848 return str;
8849 }
8850
8851 void FormalParList::generate_code_defval(output_struct *target)
8852 {
8853 for (size_t i = 0; i < pars_v.size(); i++)
8854 pars_v[i]->generate_code_defval(target);
8855 }
8856
8857 char *FormalParList::generate_code_actual_parlist(char *str,
8858 const char *p_prefix)
8859 {
8860 for (size_t i = 0; i < pars_v.size(); i++) {
8861 if (i > 0) str = mputstr(str, ", ");
8862 str = mputstr(str, p_prefix);
8863 str = mputstr(str, pars_v[i]->get_id().get_name().c_str());
8864 }
8865 return str;
8866 }
8867
8868 char *FormalParList::generate_code_object(char *str, const char *p_prefix, char refch)
8869 {
8870 for (size_t i = 0; i < pars_v.size(); i++)
8871 str = pars_v[i]->generate_code_object(str, p_prefix, refch);
8872 return str;
8873 }
8874
8875 char *FormalParList::generate_shadow_objects(char *str) const
8876 {
8877 for (size_t i = 0; i < pars_v.size(); i++)
8878 str = pars_v[i]->generate_shadow_object(str);
8879 return str;
8880 }
8881
8882 char *FormalParList::generate_code_set_unbound(char *str) const
8883 {
8884 if (enable_set_bound_out_param) return str;
8885 for (size_t i = 0; i < pars_v.size(); i++)
8886 str = pars_v[i]->generate_code_set_unbound(str);
8887 return str;
8888 }
8889
8890
8891 void FormalParList::dump(unsigned level) const
8892 {
8893 size_t nof_pars = pars_v.size();
8894 DEBUG(level, "formal parameters: %lu pcs.", (unsigned long) nof_pars);
8895 for(size_t i = 0; i < nof_pars; i++) pars_v[i]->dump(level + 1);
8896 }
8897
8898 // =================================
8899 // ===== ActualPar
8900 // =================================
8901
8902 ActualPar::ActualPar(Value *v)
8903 : Node(), selection(AP_VALUE), my_scope(0), gen_restriction_check(TR_NONE),
8904 gen_post_restriction_check(TR_NONE)
8905 {
8906 if (!v) FATAL_ERROR("ActualPar::ActualPar()");
8907 val = v;
8908 }
8909
8910 ActualPar::ActualPar(TemplateInstance *t)
8911 : Node(), selection(AP_TEMPLATE), my_scope(0),
8912 gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE)
8913 {
8914 if (!t) FATAL_ERROR("ActualPar::ActualPar()");
8915 temp = t;
8916 }
8917
8918 ActualPar::ActualPar(Ref_base *r)
8919 : Node(), selection(AP_REF), my_scope(0), gen_restriction_check(TR_NONE),
8920 gen_post_restriction_check(TR_NONE)
8921 {
8922 if (!r) FATAL_ERROR("ActualPar::ActualPar()");
8923 ref = r;
8924 }
8925
8926 ActualPar::ActualPar(ActualPar *a)
8927 : Node(), selection(AP_DEFAULT), my_scope(0),
8928 gen_restriction_check(TR_NONE), gen_post_restriction_check(TR_NONE)
8929 {
8930 if (!a) FATAL_ERROR("ActualPar::ActualPar()");
8931 act = a;
8932 }
8933
8934 ActualPar::~ActualPar()
8935 {
8936 switch(selection) {
8937 case AP_ERROR:
8938 break;
8939 case AP_VALUE:
8940 delete val;
8941 break;
8942 case AP_TEMPLATE:
8943 delete temp;
8944 break;
8945 case AP_REF:
8946 delete ref;
8947 break;
8948 case AP_DEFAULT:
8949 break; // nothing to do with act
8950 default:
8951 FATAL_ERROR("ActualPar::~ActualPar()");
8952 }
8953 }
8954
8955 ActualPar *ActualPar::clone() const
8956 {
8957 FATAL_ERROR("ActualPar::clone");
8958 }
8959
8960 void ActualPar::set_fullname(const string& p_fullname)
8961 {
8962 Node::set_fullname(p_fullname);
8963 switch(selection) {
8964 case AP_ERROR:
8965 break;
8966 case AP_VALUE:
8967 val->set_fullname(p_fullname);
8968 break;
8969 case AP_TEMPLATE:
8970 temp->set_fullname(p_fullname);
8971 break;
8972 case AP_REF:
8973 ref->set_fullname(p_fullname);
8974 break;
8975 case AP_DEFAULT:
8976 break;
8977 default:
8978 FATAL_ERROR("ActualPar::set_fullname()");
8979 }
8980 }
8981
8982 void ActualPar::set_my_scope(Scope *p_scope)
8983 {
8984 my_scope = p_scope;
8985 switch(selection) {
8986 case AP_ERROR:
8987 break;
8988 case AP_VALUE:
8989 val->set_my_scope(p_scope);
8990 break;
8991 case AP_TEMPLATE:
8992 temp->set_my_scope(p_scope);
8993 break;
8994 case AP_REF:
8995 ref->set_my_scope(p_scope);
8996 break;
8997 case AP_DEFAULT:
8998 switch (act->selection) {
8999 case AP_REF:
9000 ref->set_my_scope(p_scope);
9001 break;
9002 case AP_VALUE:
9003 break;
9004 case AP_TEMPLATE:
9005 break;
9006 default:
9007 FATAL_ERROR("ActualPar::set_my_scope()");
9008 }
9009 break;
9010 default:
9011 FATAL_ERROR("ActualPar::set_my_scope()");
9012 }
9013 }
9014
9015 Value *ActualPar::get_Value() const
9016 {
9017 if (selection != AP_VALUE) FATAL_ERROR("ActualPar::get_Value()");
9018 return val;
9019 }
9020
9021 TemplateInstance *ActualPar::get_TemplateInstance() const
9022 {
9023 if (selection != AP_TEMPLATE)
9024 FATAL_ERROR("ActualPar::get_TemplateInstance()");
9025 return temp;
9026 }
9027
9028 Ref_base *ActualPar::get_Ref() const
9029 {
9030 if (selection != AP_REF) FATAL_ERROR("ActualPar::get_Ref()");
9031 return ref;
9032 }
9033
9034 ActualPar *ActualPar::get_ActualPar() const
9035 {
9036 if (selection != AP_DEFAULT) FATAL_ERROR("ActualPar::get_ActualPar()");
9037 return act;
9038 }
9039
9040 void ActualPar::chk_recursions(ReferenceChain& refch)
9041 {
9042 switch (selection) {
9043 case AP_VALUE:
9044 refch.mark_state();
9045 val->chk_recursions(refch);
9046 refch.prev_state();
9047 break;
9048 case AP_TEMPLATE: {
9049 Ref_base *derived_ref = temp->get_DerivedRef();
9050 if (derived_ref) {
9051 ActualParList *parlist = derived_ref->get_parlist();
9052 if (parlist) {
9053 refch.mark_state();
9054 parlist->chk_recursions(refch);
9055 refch.prev_state();
9056 }
9057 }
9058
9059 Ttcn::Def_Template* defTemp = temp->get_Referenced_Base_Template();
9060 if (defTemp) {
9061 refch.mark_state();
9062 refch.add(defTemp->get_fullname());
9063 refch.prev_state();
9064 }
9065 refch.mark_state();
9066 temp->get_Template()->chk_recursions(refch);
9067 refch.prev_state();
9068 }
9069 default:
9070 break;
9071 }
9072 }
9073
9074 bool ActualPar::has_single_expr()
9075 {
9076 switch (selection) {
9077 case AP_VALUE:
9078 return val->has_single_expr();
9079 case AP_TEMPLATE:
9080 if (gen_restriction_check!=TR_NONE ||
9081 gen_post_restriction_check!=TR_NONE) return false;
9082 return temp->has_single_expr();
9083 case AP_REF:
9084 if (gen_restriction_check!=TR_NONE ||
9085 gen_post_restriction_check!=TR_NONE) return false;
af710487 9086 if (use_runtime_2 && ref->get_subrefs() != NULL) {
970ed795
EL
9087 FieldOrArrayRefs* subrefs = ref->get_subrefs();
9088 for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
9089 if (FieldOrArrayRef::ARRAY_REF == subrefs->get_ref(i)->get_type()) {
9090 return false;
9091 }
9092 }
9093 }
9094 return ref->has_single_expr();
9095 case AP_DEFAULT:
9096 return true;
9097 default:
9098 FATAL_ERROR("ActualPar::has_single_expr()");
9099 return false;
9100 }
9101 }
9102
9103 void ActualPar::set_code_section(
9104 GovernedSimple::code_section_t p_code_section)
9105 {
9106 switch (selection) {
9107 case AP_VALUE:
9108 val->set_code_section(p_code_section);
9109 break;
9110 case AP_TEMPLATE:
9111 temp->set_code_section(p_code_section);
9112 break;
9113 case AP_REF:
9114 ref->set_code_section(p_code_section);
9115 default:
9116 break;
9117 }
9118 }
9119
9120 void ActualPar::generate_code(expression_struct *expr, bool copy_needed, bool lazy_param, bool used_as_lvalue) const
9121 {
9122 switch (selection) {
9123 case AP_VALUE:
9124 if (lazy_param) { // copy_needed doesn't matter in this case
9125 LazyParamData::init(used_as_lvalue);
9126 LazyParamData::generate_code(expr, val, my_scope);
9127 LazyParamData::clean();
9128 } else {
9129 if (copy_needed) expr->expr = mputprintf(expr->expr, "%s(",
9130 val->get_my_governor()->get_genname_value(my_scope).c_str());
9131 if (use_runtime_2 && TypeConv::needs_conv_refd(val)) {
9132 // Generate everything to preamble to be able to tackle the wrapper
9133 // constructor call. TODO: Reduce the number of temporaries created.
9134 const string& tmp_id = val->get_temporary_id();
9135 const char *tmp_id_str = tmp_id.c_str();
9136 expr->preamble = mputprintf(expr->preamble, "%s %s;\n",
9137 val->get_my_governor()->get_genname_value(my_scope).c_str(),
9138 tmp_id_str);
9139 expr->preamble = TypeConv::gen_conv_code_refd(expr->preamble,
9140 tmp_id_str, val);
9141 expr->expr = mputstr(expr->expr, tmp_id_str);
9142 } else val->generate_code_expr(expr);
9143 if (copy_needed) expr->expr = mputc(expr->expr, ')');
9144 }
9145 break;
9146 case AP_TEMPLATE:
9147 if (lazy_param) { // copy_needed doesn't matter in this case
9148 LazyParamData::init(used_as_lvalue);
9149 LazyParamData::generate_code(expr, temp, gen_restriction_check, my_scope);
9150 LazyParamData::clean();
9151 } else {
9152 if (copy_needed)
9153 expr->expr = mputprintf(expr->expr, "%s(", temp->get_Template()
9154 ->get_my_governor()->get_genname_template(my_scope).c_str());
9155 if (use_runtime_2 && TypeConv::needs_conv_refd(temp->get_Template())) {
9156 const string& tmp_id = temp->get_Template()->get_temporary_id();
9157 const char *tmp_id_str = tmp_id.c_str();
9158 expr->preamble = mputprintf(expr->preamble, "%s %s;\n",
9159 temp->get_Template()->get_my_governor()
9160 ->get_genname_template(my_scope).c_str(), tmp_id_str);
9161 expr->preamble = TypeConv::gen_conv_code_refd(expr->preamble,
9162 tmp_id_str, temp->get_Template());
9163 // Not incorporated into gen_conv_code() yet.
9164 if (gen_restriction_check != TR_NONE)
9165 expr->preamble = Template::generate_restriction_check_code(
9166 expr->preamble, tmp_id_str, gen_restriction_check);
9167 expr->expr = mputstr(expr->expr, tmp_id_str);
9168 } else temp->generate_code(expr, gen_restriction_check);
9169 if (copy_needed) expr->expr = mputc(expr->expr, ')');
9170 }
9171 break;
9172 case AP_REF:
9173 if (lazy_param) FATAL_ERROR("ActualPar::generate_code()"); // syntax error should have already happened
9174 if (copy_needed) FATAL_ERROR("ActualPar::generate_code()");
9175 if (gen_restriction_check != TR_NONE ||
9176 gen_post_restriction_check != TR_NONE) {
9177 // generate runtime check for restricted templates
9178 // code for reference + restriction check
9179 Common::Assignment *ass = ref->get_refd_assignment();
9180 const string& tmp_id= my_scope->get_scope_mod_gen()->get_temporary_id();
9181 const char *tmp_id_str = tmp_id.c_str();
9182 expression_struct ref_expr;
9183 Code::init_expr(&ref_expr);
9184 ref->generate_code_const_ref(&ref_expr);
9185 ref_expr.preamble = mputprintf(ref_expr.preamble, "%s& %s = %s;\n",
9186 ass->get_Type()->get_genname_template(ref->get_my_scope()).c_str(),
9187 tmp_id_str, ref_expr.expr);
9188 if (gen_restriction_check != TR_NONE) {
9189 ref_expr.preamble = Template::generate_restriction_check_code(
9190 ref_expr.preamble, tmp_id_str, gen_restriction_check);
9191 }
9192 if (gen_post_restriction_check != TR_NONE) {
9193 ref_expr.postamble = Template::generate_restriction_check_code(
9194 ref_expr.postamble, tmp_id_str, gen_post_restriction_check);
9195 }
9196 // copy content of ref_expr to expr
9197 expr->preamble = mputstr(expr->preamble, ref_expr.preamble);
9198 expr->expr = mputprintf(expr->expr, "%s", tmp_id_str);
9199 expr->postamble = mputstr(expr->postamble, ref_expr.postamble);
9200 Code::free_expr(&ref_expr);
9201 } else {
9202 ref->generate_code(expr);
9203 }
9204 break;
9205 case AP_DEFAULT:
9206 if (copy_needed) FATAL_ERROR("ActualPar::generate_code()");
9207 switch (act->selection) {
9208 case AP_REF:
9209 if (lazy_param) {
9210 LazyParamData::generate_code_ap_default_ref(expr, act->ref, my_scope);
9211 } else {
9212 act->ref->generate_code(expr);
9213 }
9214 break;
9215 case AP_VALUE:
9216 if (lazy_param) {
9217 LazyParamData::generate_code_ap_default_value(expr, act->val, my_scope);
9218 } else {
9219 expr->expr = mputstr(expr->expr, act->val->get_genname_own(my_scope).c_str());
9220 }
9221 break;
9222 case AP_TEMPLATE:
9223 if (lazy_param) {
9224 LazyParamData::generate_code_ap_default_ti(expr, act->temp, my_scope);
9225 } else {
9226 expr->expr = mputstr(expr->expr, act->temp->get_Template()->get_genname_own(my_scope).c_str());
9227 }
9228 break;
9229 default:
9230 FATAL_ERROR("ActualPar::generate_code()");
9231 }
9232 break;
9233 default:
9234 FATAL_ERROR("ActualPar::generate_code()");
9235 }
9236 }
9237
9238 char *ActualPar::rearrange_init_code(char *str, bool is_local)
9239 {
9240 switch (selection) {
9241 case AP_VALUE:
9242 str = val->rearrange_init_code(str);
9243 break;
9244 case AP_TEMPLATE:
9245 str = temp->rearrange_init_code(str);
9246 case AP_REF:
9247 break;
9248 case AP_DEFAULT:
9249 if (is_local) str = act->rearrange_init_code_defval(str);
9250 break;
9251 default:
9252 FATAL_ERROR("ActualPar::rearrange_init_code()");
9253 }
9254 return str;
9255 }
9256
9257 char *ActualPar::rearrange_init_code_defval(char *str)
9258 {
9259 switch (selection) {
9260 case AP_VALUE:
9261 str = val->generate_code_init(str, val->get_lhs_name().c_str());
9262 break;
9263 case AP_TEMPLATE: {
9264 str = temp->rearrange_init_code(str);
9265 Ref_base *dref = temp->get_DerivedRef();
9266 Template *t = temp->get_Template();
9267 if (dref) {
9268 expression_struct expr;
9269 Code::init_expr(&expr);
9270 expr.expr = mputprintf(expr.expr, "%s = ", t->get_lhs_name().c_str());
9271 dref->generate_code(&expr);
9272 str = Code::merge_free_expr(str, &expr, false);
9273 }
9274 str = t->generate_code_init(str, t->get_lhs_name().c_str());
9275 break; }
9276 default:
9277 FATAL_ERROR("ActualPar::rearrange_init_code_defval()");
9278 }
9279 return str;
9280 }
9281
9282 void ActualPar::append_stringRepr(string& str) const
9283 {
9284 switch (selection) {
9285 case AP_VALUE:
9286 str += val->get_stringRepr();
9287 break;
9288 case AP_TEMPLATE:
9289 temp->append_stringRepr(str);
9290 break;
9291 case AP_REF:
9292 str += ref->get_dispname();
9293 break;
9294 case AP_DEFAULT:
9295 str += '-';
9296 break;
9297 default:
9298 str += "<erroneous actual parameter>";
9299 }
9300 }
9301
9302 void ActualPar::dump(unsigned level) const
9303 {
9304 switch (selection) {
9305 case AP_VALUE:
9306 DEBUG(level, "actual parameter: value");
9307 val->dump(level + 1);
9308 break;
9309 case AP_TEMPLATE:
9310 DEBUG(level, "actual parameter: template");
9311 temp->dump(level + 1);
9312 break;
9313 case AP_REF:
9314 DEBUG(level, "actual parameter: referecne");
9315 ref->dump(level + 1);
9316 break;
9317 case AP_DEFAULT:
9318 DEBUG(level, "actual parameter: default");
9319 break;
9320 default:
9321 DEBUG(level, "actual parameter: erroneous");
9322 }
9323 }
9324
9325 // =================================
9326 // ===== ActualParList
9327 // =================================
9328
9329 ActualParList::ActualParList(const ActualParList& p)
9330 : Node(p)
9331 {
9332 size_t nof_pars = p.params.size();
9333 for (size_t i = 0; i < nof_pars; i++) params.add(p.params[i]->clone());
9334 }
9335
9336 ActualParList::~ActualParList()
9337 {
9338 size_t nof_pars = params.size();
9339 for (size_t i = 0; i < nof_pars; i++) delete params[i];
9340 params.clear();
9341 }
9342
9343 ActualParList *ActualParList::clone() const
9344 {
9345 return new ActualParList(*this);
9346 }
9347
9348 void ActualParList::set_fullname(const string& p_fullname)
9349 {
9350 Node::set_fullname(p_fullname);
9351 size_t nof_pars = params.size();
9352 for(size_t i = 0; i < nof_pars; i++)
9353 params[i]->set_fullname(p_fullname +
9354 ".<parameter" + Int2string(i + 1) + ">");
9355 }
9356
9357 void ActualParList::set_my_scope(Scope *p_scope)
9358 {
9359 size_t nof_pars = params.size();
9360 for (size_t i = 0; i < nof_pars; i++) params[i]->set_my_scope(p_scope);
9361 }
9362
9363 void ActualParList::chk_recursions(ReferenceChain& refch)
9364 {
9365 size_t nof_pars = params.size();
9366 for (size_t i = 0; i < nof_pars; i++)
9367 params[i]->chk_recursions(refch);
9368 }
9369
9370 void ActualParList::generate_code_noalias(expression_struct *expr, FormalParList *p_fpl)
9371 {
9372 size_t nof_pars = params.size();
9373 for (size_t i = 0; i < nof_pars; i++) {
9374 if (i > 0) expr->expr = mputstr(expr->expr, ", ");
9375 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());
9376 }
9377 }
9378
9379 void ActualParList::generate_code_alias(expression_struct *expr,
9380 FormalParList *p_fpl, Type *p_comptype, bool p_compself)
9381 {
9382 size_t nof_pars = params.size();
9383 // collect all value and template definitions that are passed by reference
9384 map<Common::Assignment*, void> value_refs, template_refs;
9385 for (size_t i = 0; i < nof_pars; i++) {
9386 ActualPar *par = params[i];
9387 if (par->get_selection() == ActualPar::AP_DEFAULT)
9388 par = par->get_ActualPar();
9389 if (par->get_selection() == ActualPar::AP_REF) {
9390 Common::Assignment *ass = par->get_Ref()->get_refd_assignment();
9391 switch (ass->get_asstype()) {
9392 case Common::Assignment::A_VAR:
9393 case Common::Assignment::A_PAR_VAL_IN:
9394 case Common::Assignment::A_PAR_VAL_OUT:
9395 case Common::Assignment::A_PAR_VAL_INOUT:
9396 if (!value_refs.has_key(ass)) value_refs.add(ass, 0);
9397 break;
9398 case Common::Assignment::A_VAR_TEMPLATE:
9399 case Common::Assignment::A_PAR_TEMPL_IN:
9400 case Common::Assignment::A_PAR_TEMPL_OUT:
9401 case Common::Assignment::A_PAR_TEMPL_INOUT:
9402 if (!template_refs.has_key(ass)) template_refs.add(ass, 0);
9403 default:
9404 break;
9405 }
9406 }
9407 }
9408 // walk through the parameter list and generate the code
9409 // add an extra copy constructor call to the referenced value and template
9410 // parameters if the referred definition is also passed by reference to
9411 // another parameter
9412 for (size_t i = 0; i < nof_pars; i++) {
9413 if (i > 0) expr->expr = mputstr(expr->expr, ", ");
9414 ActualPar *par = params[i];
9415 bool copy_needed = false;
9416 // the copy constructor call is not needed if the parameter is copied
9417 // into a shadow object in the body of the called function
9418 if (!p_fpl || !p_fpl->get_fp_byIndex(i)->get_used_as_lvalue()) {
9419 switch (par->get_selection()) {
9420 case ActualPar::AP_VALUE: {
9421 Value *v = par->get_Value();
9422 if (v->get_valuetype() == Value::V_REFD) {
9423 Common::Assignment *t_ass =
9424 v->get_reference()->get_refd_assignment();
9425 if (value_refs.has_key(t_ass)) {
9426 // a reference to the same variable is also passed to the called
9427 // definition
9428 copy_needed = true;
9429 } else if (p_comptype || p_compself) {
9430 // the called definition has a 'runs on' clause so it can access
9431 // component variables
9432 switch (t_ass->get_asstype()) {
9433 case Common::Assignment::A_PAR_VAL_OUT:
9434 case Common::Assignment::A_PAR_VAL_INOUT:
9435 // the parameter may be an alias of a component variable
9436 copy_needed = true;
9437 break;
9438 case Common::Assignment::A_VAR:
9439 // copy is needed if t_ass is a component variable that is
9440 // visible by the called definition
9441 if (!t_ass->is_local()) copy_needed = true;
9442 /** \todo component type compatibility: check whether t_ass is
9443 * visible from p_comptype (otherwise copy is not needed) */
9444 default:
9445 break;
9446 }
9447 }
9448 }
9449 break; }
9450 case ActualPar::AP_TEMPLATE: {
9451 TemplateInstance *ti = par->get_TemplateInstance();
9452 if (!ti->get_DerivedRef()) {
9453 Template *t = ti->get_Template();
9454 if (t->get_templatetype() == Template::TEMPLATE_REFD) {
9455 Common::Assignment *t_ass =
9456 t->get_reference()->get_refd_assignment();
9457 if (template_refs.has_key(t_ass)) {
9458 // a reference to the same variable is also passed to the called
9459 // definition
9460 copy_needed = true;
9461 } else if (p_comptype || p_compself) {
9462 // the called definition has a 'runs on' clause so it can access
9463 // component variables
9464 switch (t_ass->get_asstype()) {
9465 case Common::Assignment::A_PAR_TEMPL_OUT:
9466 case Common::Assignment::A_PAR_TEMPL_INOUT:
9467 // the parameter may be an alias of a component variable
9468 copy_needed = true;
9469 break;
9470 case Common::Assignment::A_VAR_TEMPLATE:
9471 // copy is needed if t_ass is a component variable that is
9472 // visible by the called definition
9473 if (!t_ass->is_local()) copy_needed = true;
9474 /** \todo component type compatibility: check whether t_ass is
9475 * visible from p_comptype (otherwise copy is not needed) */
9476 default:
9477 break;
9478 }
9479 }
9480 }
9481 } }
9482 default:
9483 break;
9484 }
9485 }
9486
af710487 9487 if (use_runtime_2 && ActualPar::AP_REF == par->get_selection()) {
970ed795
EL
9488 // if the parameter references an element of a record of/set of, then
9489 // the record of object needs to know, so it doesn't delete the referenced
9490 // element
9491 Ref_base* ref = par->get_Ref();
9492 FieldOrArrayRefs* subrefs = ref->get_subrefs();
9493 if (subrefs != NULL) {
9494 Common::Assignment* ass = ref->get_refd_assignment();
9495 size_t ref_i;
9496 for (ref_i = 0; ref_i < subrefs->get_nof_refs(); ++ref_i) {
9497 FieldOrArrayRef* subref = subrefs->get_ref(ref_i);
9498 if (FieldOrArrayRef::ARRAY_REF == subref->get_type()) {
9499 // set the referenced index in each array in the subrefs
9500 expression_struct array_expr;
9501 Code::init_expr(&array_expr);
9502 // the array object's name contains the reference, followed by
9503 // the subrefs before the current array ref
9504 array_expr.expr = mcopystr(LazyParamData::in_lazy() ?
9505 LazyParamData::add_ref_genname(ass, ref->get_my_scope()).c_str() :
9506 ass->get_genname_from_scope(ref->get_my_scope()).c_str());
9507 if (ref_i > 0) {
9508 subrefs->generate_code(&array_expr, ass, ref_i);
9509 }
9510 expression_struct index_expr;
9511 Code::init_expr(&index_expr);
9512 subrefs->get_ref(ref_i)->get_val()->generate_code_expr(&index_expr);
9513 // insert any preambles the array object or the index might have
9514 if (array_expr.preamble != NULL) {
9515 expr->preamble = mputstr(expr->preamble, array_expr.preamble);
9516 expr->postamble = mputstr(expr->postamble, array_expr.preamble);
9517 }
9518 if (index_expr.preamble != NULL) {
9519 expr->preamble = mputstr(expr->preamble, index_expr.preamble);
9520 expr->postamble = mputstr(expr->postamble, index_expr.preamble);
9521 }
9522 // let the array object know that the index is referenced before
9523 // calling the function, and let it know that it's now longer
9524 // referenced after the function call
af710487 9525 expr->preamble = mputprintf(expr->preamble,
509718e0 9526 "%s.add_refd_index(%s);\n",
af710487 9527 array_expr.expr, index_expr.expr);
509718e0 9528 expr->postamble = mputprintf(expr->postamble,
af710487 9529 "%s.remove_refd_index(%s);\n",
9530 array_expr.expr, index_expr.expr);
970ed795
EL
9531 // insert any postambles the array object or the index might have
9532 if (array_expr.postamble != NULL) {
9533 expr->preamble = mputstr(expr->preamble, array_expr.postamble);
9534 expr->postamble = mputstr(expr->postamble, array_expr.postamble);
9535 }
9536 if (index_expr.postamble != NULL) {
9537 expr->preamble = mputstr(expr->preamble, index_expr.postamble);
9538 expr->postamble = mputstr(expr->postamble, index_expr.postamble);
9539 }
9540 Code::free_expr(&array_expr);
9541 Code::free_expr(&index_expr);
9542 } // if (FieldOrArrayRef::ARRAY_REF == subref->get_type())
9543 } // for cycle
9544 } // if (subrefs != NULL)
9545 } // if (ActualPar::AP_REF == par->get_selection())
9546
9547 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());
9548 }
9549 value_refs.clear();
9550 template_refs.clear();
9551 }
9552
9553 char *ActualParList::rearrange_init_code(char *str, bool is_local)
9554 {
9555 for (size_t i = 0; i < params.size(); i++)
9556 str = params[i]->rearrange_init_code(str, is_local);
9557 return str;
9558 }
9559
9560 void ActualParList::dump(unsigned level) const
9561 {
9562 DEBUG(level, "actual parameter list: %lu parameters",
9563 (unsigned long) params.size());
9564 for (size_t i = 0; i < params.size(); i++)
9565 params[i]->dump(level + 1);
9566 }
9567}
This page took 0.397982 seconds and 5 git commands to generate.