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