Sync with 5.4.2
[deliverable/titan.core.git] / compiler2 / ttcn3 / TtcnTemplate.cc
CommitLineData
970ed795 1///////////////////////////////////////////////////////////////////////////////
3abe9331 2// Copyright (c) 2000-2015 Ericsson Telecom AB
970ed795
EL
3// All rights reserved. This program and the accompanying materials
4// are made available under the terms of the Eclipse Public License v1.0
5// which accompanies this distribution, and is available at
6// http://www.eclipse.org/legal/epl-v10.html
7///////////////////////////////////////////////////////////////////////////////
8#include "TtcnTemplate.hh"
9#include "../Identifier.hh"
10#include "Templatestuff.hh"
11#include "../Type.hh"
12#include "../TypeCompat.hh"
13#include "../SigParam.hh"
14#include "../CompField.hh"
15#include "../Valuestuff.hh"
16#include "ArrayDimensions.hh"
17#include "PatternString.hh"
18#include "../main.hh"
19#include "../../common/dbgnew.hh"
20#include "Attributes.hh"
21
22namespace Ttcn {
23
24 // =================================
25 // ===== Template
26 // =================================
27
28 Template::Template(const Template& p) : GovernedSimple(p),
29 templatetype(p.templatetype), my_governor(p.my_governor),
30 is_ifpresent(p.is_ifpresent), specific_value_checked(false),
31 has_permutation(p.has_permutation), base_template(p.base_template)
32 {
33 switch (templatetype) {
34 case TEMPLATE_ERROR:
35 case TEMPLATE_NOTUSED:
36 case OMIT_VALUE:
37 case ANY_VALUE:
38 case ANY_OR_OMIT:
39 break;
40 case SPECIFIC_VALUE:
41 u.specific_value = p.u.specific_value->clone();
42 break;
43 case TEMPLATE_REFD:
44 u.ref.ref = p.u.ref.ref->clone();
45 u.ref.refd = 0;
46 u.ref.refd_last = 0;
47 break;
48 case TEMPLATE_INVOKE:
49 u.invoke.v = p.u.invoke.v->clone();
50 u.invoke.t_list = p.u.invoke.t_list ? p.u.invoke.t_list->clone() : 0;
51 u.invoke.ap_list = p.u.invoke.ap_list ? p.u.invoke.ap_list->clone() : 0;
52 break;
53 case ALL_FROM:
54 case VALUE_LIST_ALL_FROM:
55 u.all_from = p.u.all_from->clone();
56 break;
57 case TEMPLATE_LIST:
58 case VALUE_LIST:
59 case COMPLEMENTED_LIST:
60 case SUPERSET_MATCH:
61 case SUBSET_MATCH:
62 case PERMUTATION_MATCH:
63 u.templates = p.u.templates->clone(); // FATAL_ERROR
64 break;
65 case NAMED_TEMPLATE_LIST:
3f84031e 66 u.named_templates = p.u.named_templates->clone();
970ed795
EL
67 break;
68 case INDEXED_TEMPLATE_LIST:
3f84031e 69 u.indexed_templates = p.u.indexed_templates->clone();
970ed795
EL
70 break;
71 case VALUE_RANGE:
72 u.value_range = p.u.value_range->clone();
73 break;
74 case BSTR_PATTERN:
75 case HSTR_PATTERN:
76 case OSTR_PATTERN:
77 u.pattern = new string(*p.u.pattern);
78 break;
79 case CSTR_PATTERN:
80 case USTR_PATTERN:
81 u.pstring = p.u.pstring->clone();
82 break;
83// default:
84// FATAL_ERROR("Template::Template()");
85 }
86 length_restriction =
87 p.length_restriction ? p.length_restriction->clone() : 0; // FATAL_ERR
88 }
89
90 void Template::clean_up()
91 {
92 switch(templatetype) {
93 case TEMPLATE_ERROR:
94 case TEMPLATE_NOTUSED:
95 case OMIT_VALUE:
96 case ANY_VALUE:
97 case ANY_OR_OMIT:
98 break;
99 case SPECIFIC_VALUE:
100 delete u.specific_value;
101 break;
102 case TEMPLATE_REFD:
103 delete u.ref.ref;
104 break;
105 case TEMPLATE_INVOKE:
106 delete u.invoke.v;
107 delete u.invoke.t_list;
108 delete u.invoke.ap_list;
109 break;
110 case TEMPLATE_LIST:
111 case VALUE_LIST:
112 case COMPLEMENTED_LIST:
113 case SUPERSET_MATCH:
114 case SUBSET_MATCH:
115 case PERMUTATION_MATCH:
116 delete u.templates;
117 break;
118 case ALL_FROM:
119 case VALUE_LIST_ALL_FROM:
120 delete u.all_from;
121 break;
122 case NAMED_TEMPLATE_LIST:
123 delete u.named_templates;
124 break;
125 case INDEXED_TEMPLATE_LIST:
126 delete u.indexed_templates;
127 break;
128 case VALUE_RANGE:
129 delete u.value_range;
130 break;
131 case BSTR_PATTERN:
132 case HSTR_PATTERN:
133 case OSTR_PATTERN:
134 delete u.pattern;
135 break;
136 case CSTR_PATTERN:
137 case USTR_PATTERN:
138 delete u.pstring;
139 break;
140// default:
141// FATAL_ERROR("Template::clean_up()");
142 }
143 }
144
145 string Template::create_stringRepr()
146 {
147 string ret_val;
148 switch (templatetype) {
149 case TEMPLATE_ERROR:
150 ret_val += "<erroneous template>";
151 break;
152 case TEMPLATE_NOTUSED:
153 ret_val += "-";
154 break;
155 case OMIT_VALUE:
156 ret_val += "omit";
157 break;
158 case ANY_VALUE:
159 ret_val += "?";
160 break;
161 case ANY_OR_OMIT:
162 ret_val += "*";
163 break;
164 case SPECIFIC_VALUE:
165 ret_val += u.specific_value->get_stringRepr();
166 break;
167 case TEMPLATE_REFD: {
168 Template *t_last = get_template_refd_last();
169 if (t_last->templatetype == TEMPLATE_REFD)
170 ret_val += u.ref.ref->get_dispname();
171 else ret_val += t_last->get_stringRepr();
172 break; }
173 case TEMPLATE_INVOKE: {
174 ret_val += u.invoke.v->get_stringRepr();
175 ret_val += ".invoke(";
176 if(u.invoke.ap_list)
177 for(size_t i = 0; i < u.invoke.ap_list->get_nof_pars(); i++) {
178 if(i>0) ret_val += ", ";
179 ret_val += u.invoke.ap_list->get_par(i)->get_fullname();
180 }
181 ret_val += ")";
182 break; }
183 case TEMPLATE_LIST:
184 if (u.templates->get_nof_ts() > 0) {
185 ret_val += "{ ";
186 u.templates->append_stringRepr(ret_val);
187 ret_val += " }";
188 } else ret_val += "{ }";
189 break;
190 case NAMED_TEMPLATE_LIST:
191 ret_val += "{";
192 for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++) {
193 if (i > 0) ret_val += ", ";
194 else ret_val += " ";
195 NamedTemplate *nt = u.named_templates->get_nt_byIndex(i);
196 ret_val += nt->get_name().get_dispname();
197 ret_val += " := ";
198 ret_val += nt->get_template()->get_stringRepr();
199 }
200 ret_val += " }";
201 break;
202 case INDEXED_TEMPLATE_LIST:
203 ret_val += "{";
204 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++) {
205 if (i > 0) ret_val += ", ";
206 else ret_val += " [";
207 IndexedTemplate *it = u.indexed_templates->get_it_byIndex(i);
208 (it->get_index()).append_stringRepr(ret_val);
209 ret_val += "] := ";
210 ret_val += it->get_template()->get_stringRepr();
211 }
212 ret_val += "}";
213 break;
214 case VALUE_LIST:
215 ret_val += "(";
216 u.templates->append_stringRepr(ret_val);
217 ret_val += ")";
218 break;
219 case COMPLEMENTED_LIST:
220 ret_val += "complement(";
221 u.templates->append_stringRepr(ret_val);
222 ret_val += ")";
223 break;
224 case VALUE_RANGE:
225 u.value_range->append_stringRepr(ret_val);
226 break;
227 case SUPERSET_MATCH:
228 ret_val += "superset(";
229 u.templates->append_stringRepr(ret_val);
230 ret_val += ")";
231 break;
232 case SUBSET_MATCH:
233 ret_val += "subset(";
234 u.templates->append_stringRepr(ret_val);
235 ret_val += ")";
236 break;
237 case PERMUTATION_MATCH:
238 ret_val += "permutation(";
239 u.templates->append_stringRepr(ret_val);
240 ret_val += ")";
241 break;
242 case BSTR_PATTERN:
243 ret_val += "'";
244 ret_val += *u.pattern;
245 ret_val += "'B";
246 break;
247 case HSTR_PATTERN:
248 ret_val += "'";
249 ret_val += *u.pattern;
250 ret_val += "'H";
251 break;
252 case OSTR_PATTERN:
253 ret_val += "'";
254 ret_val += *u.pattern;
255 ret_val += "'O";
256 break;
257 case CSTR_PATTERN:
258 case USTR_PATTERN:
259 ret_val += "pattern \"";
260 ret_val += u.pstring->get_full_str();
261 ret_val += "\"";
262 break;
263 default:
264 ret_val += "<unknown template>";
265 break;
266 }
267 if (length_restriction) length_restriction->append_stringRepr(ret_val);
268 if (is_ifpresent) ret_val += " ifpresent";
269 return ret_val;
270 }
271
272 Template::Template(templatetype_t tt)
273 : GovernedSimple(S_TEMPLATE),
274 templatetype(tt), my_governor(0), length_restriction(0),
275 is_ifpresent(false), specific_value_checked(false),
276 has_permutation(false), flattened(true), base_template(0)
277 {
278 switch (tt) {
279 case TEMPLATE_ERROR:
280 case TEMPLATE_NOTUSED:
281 case OMIT_VALUE:
282 case ANY_VALUE:
283 case ANY_OR_OMIT:
284 break;
285 default:
286 FATAL_ERROR("Template::Template()");
287 }
288 }
289
290 Template::Template(Value *v)
291 : GovernedSimple(S_TEMPLATE),
292 templatetype(SPECIFIC_VALUE), my_governor(0), length_restriction(0),
293 is_ifpresent(false), specific_value_checked(false),
294 has_permutation(false), flattened(true), base_template(0)
295 {
296 if (!v) FATAL_ERROR("Template::Template()");
297 u.specific_value = v;
298 }
299
300 Template::Template(Ref_base *p_ref)
301 : GovernedSimple(S_TEMPLATE),
302 templatetype(TEMPLATE_REFD), my_governor(0), length_restriction(0),
303 is_ifpresent(false), specific_value_checked(false),
304 has_permutation(false), base_template(0)
305 {
306 if(!p_ref) FATAL_ERROR("Template::Template()");
307 u.ref.ref=p_ref;
308 u.ref.refd=0;
309 u.ref.refd_last=0;
310 }
311
312 Template::Template(templatetype_t tt, Templates *ts)
313 : GovernedSimple(S_TEMPLATE),
314 templatetype(tt), my_governor(0), length_restriction(0),
315 is_ifpresent(false), specific_value_checked(false),
316 has_permutation(false), flattened(true), base_template(0)
317 {
318 switch (tt) {
319 case TEMPLATE_LIST:
320 case VALUE_LIST:
321 case COMPLEMENTED_LIST:
322 case SUPERSET_MATCH:
323 case SUBSET_MATCH:
324 case PERMUTATION_MATCH:
325 break;
326 default:
327 FATAL_ERROR("Template::Template()");
328 }
329 if (!ts) FATAL_ERROR("Template::Template()");
330 u.templates = ts;
331 if (tt == TEMPLATE_LIST) {
332 size_t nof_ts = ts->get_nof_ts();
333 for (size_t i = 0; i < nof_ts; i++) {
334 if (ts->get_t_byIndex(i)->templatetype == PERMUTATION_MATCH) {
335 has_permutation = true;
336 break;
337 }
338 }
339 }
340 }
341
342 Template::Template(Template *t)
343 : GovernedSimple(S_TEMPLATE)
344 , templatetype(ALL_FROM), my_governor(0), length_restriction(0)
345 , is_ifpresent(false), specific_value_checked(false)
346 , has_permutation(false), flattened(true), base_template(0)
347 {
348 u.all_from = t;
349 // t is usually a SPECIFIC_VALUE
350 // t->u.specific_value is a V_UNDEF_LOWERID
351 // calling set_lowerid_to_ref is too soon (my_scope is not set yet)
352 }
353
354 Template::Template(templatetype_t tt, Template *t)
355 : GovernedSimple(S_TEMPLATE)
356 , templatetype(VALUE_LIST_ALL_FROM), my_governor(0), length_restriction(0)
357 , is_ifpresent(false), specific_value_checked(false)
358 , has_permutation(false), flattened(true), base_template(0)
359 {
360 if (tt != VALUE_LIST_ALL_FROM) FATAL_ERROR("Template::Template()");
361 u.all_from = t->u.all_from; // take it over
362 t->u.all_from = NULL;
363 delete t;
364 }
365
366 Template::Template(NamedTemplates *nts)
367 : GovernedSimple(S_TEMPLATE),
368 templatetype(NAMED_TEMPLATE_LIST), my_governor(0), length_restriction(0),
369 is_ifpresent(false), specific_value_checked(false),
370 has_permutation(false), flattened(true), base_template(0)
371 {
372 if (!nts) FATAL_ERROR("Template::Template()");
373 u.named_templates = nts;
374 }
375
376 Template::Template(IndexedTemplates *its)
377 : GovernedSimple(S_TEMPLATE),
378 templatetype(INDEXED_TEMPLATE_LIST), my_governor(0),
379 length_restriction(0), is_ifpresent(false),
380 specific_value_checked(false), has_permutation(false), flattened(true),
381 base_template(0)
382 {
383 if (!its) FATAL_ERROR("Template::Template()");
384 u.indexed_templates = its;
385 size_t nof_its = its->get_nof_its();
386 for (size_t i = 0; i < nof_its; i++) {
387 if (its->get_it_byIndex(i)->get_template()->templatetype ==
388 PERMUTATION_MATCH) {
389 has_permutation = true;
390 break;
391 }
392 }
393 }
394
395 Template::Template(ValueRange *vr)
396 : GovernedSimple(S_TEMPLATE),
397 templatetype(VALUE_RANGE), my_governor(0), length_restriction(0),
398 is_ifpresent(false), specific_value_checked(false),
399 has_permutation(false), flattened(true), base_template(0)
400 {
401 if (!vr) FATAL_ERROR("Template::Template()");
402 u.value_range = vr;
403 }
404
405 Template::Template(templatetype_t tt, string *p_patt)
406 : GovernedSimple(S_TEMPLATE),
407 templatetype(tt), my_governor(0), length_restriction(0),
408 is_ifpresent(false), specific_value_checked(false),
409 has_permutation(false), flattened(true), base_template(0)
410 {
411 switch (tt) {
412 case BSTR_PATTERN:
413 case HSTR_PATTERN:
414 case OSTR_PATTERN:
415 break;
416 default:
417 FATAL_ERROR("Template::Template()");
418 }
419 if (!p_patt) FATAL_ERROR("Template::Template()");
420 u.pattern = p_patt;
421 }
422
423 Template::Template(PatternString *p_ps)
424 : GovernedSimple(S_TEMPLATE),
425 templatetype(CSTR_PATTERN), my_governor(0), length_restriction(0),
426 is_ifpresent(false), specific_value_checked(false),
427 has_permutation(false), flattened(true), base_template(0)
428 {
429 if (!p_ps) FATAL_ERROR("Template::Template()");
430 u.pstring = p_ps;
431 }
432
433 Template::~Template()
434 {
435 clean_up();
436 delete length_restriction;
437 }
438
439 Template *Template::clone() const
440 {
441 return new Template(*this);
442 }
443
444 void Template::set_fullname(const string& p_fullname)
445 {
446 GovernedSimple::set_fullname(p_fullname);
447 switch (templatetype) {
448 case TEMPLATE_ERROR:
449 case TEMPLATE_NOTUSED:
450 case OMIT_VALUE:
451 case ANY_VALUE:
452 case ANY_OR_OMIT:
453 case BSTR_PATTERN:
454 case HSTR_PATTERN:
455 case OSTR_PATTERN:
456 break;
457 case SPECIFIC_VALUE:
458 u.specific_value->set_fullname(p_fullname);
459 break;
460 case TEMPLATE_REFD:
461 u.ref.ref->set_fullname(p_fullname);
462 break;
463 case TEMPLATE_INVOKE:
464 u.invoke.v->set_fullname(p_fullname);
465 if(u.invoke.t_list) u.invoke.t_list->set_fullname(p_fullname);
466 if(u.invoke.ap_list) u.invoke.ap_list->set_fullname(p_fullname);
467 break;
468 case TEMPLATE_LIST:
469 u.templates->set_fullname(p_fullname);
470 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
471 u.templates->get_t_byIndex(i)->set_fullname(
472 p_fullname + "[" + Int2string(i) + "]");
473 break;
474 case INDEXED_TEMPLATE_LIST:
475 u.indexed_templates->set_fullname(p_fullname);
476 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++)
477 u.indexed_templates->get_it_byIndex(i)->set_fullname(
478 p_fullname + "[" + Int2string(i) + "]");
479 break;
480 case NAMED_TEMPLATE_LIST:
481 u.named_templates->set_fullname(p_fullname);
482 break;
483 case ALL_FROM:
484 case VALUE_LIST_ALL_FROM:
485 u.all_from->set_fullname(p_fullname);
486 break;
487 case VALUE_LIST:
488 case COMPLEMENTED_LIST:
489 case SUPERSET_MATCH:
490 case SUBSET_MATCH:
491 case PERMUTATION_MATCH:
492 u.templates->set_fullname(p_fullname);
493 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
494 u.templates->get_t_byIndex(i)->set_fullname(
495 p_fullname + ".list_item(" + Int2string(i) + ")");
496 break;
497 case VALUE_RANGE:
498 u.value_range->set_fullname(p_fullname);
499 break;
500 case CSTR_PATTERN:
501 case USTR_PATTERN:
502 u.pstring->set_fullname(p_fullname);
503 break;
504// default:
505// FATAL_ERROR("Template::set_fullname()");
506 }
507 if (length_restriction)
508 length_restriction->set_fullname(p_fullname + ".<length_restriction>");
509 }
510
511 void Template::set_my_scope(Scope *p_scope)
512 {
513 GovernedSimple::set_my_scope(p_scope);
514 switch (templatetype) {
515 case TEMPLATE_ERROR:
516 case TEMPLATE_NOTUSED:
517 case OMIT_VALUE:
518 case ANY_VALUE:
519 case ANY_OR_OMIT:
520 case BSTR_PATTERN:
521 case HSTR_PATTERN:
522 case OSTR_PATTERN:
523 break;
524 case SPECIFIC_VALUE:
525 u.specific_value->set_my_scope(p_scope);
526 break;
527 case TEMPLATE_REFD:
528 u.ref.ref->set_my_scope(p_scope);
529 break;
530 case TEMPLATE_INVOKE:
531 u.invoke.v->set_my_scope(p_scope);
532 if(u.invoke.t_list) u.invoke.t_list->set_my_scope(p_scope);
533 if(u.invoke.ap_list) u.invoke.ap_list->set_my_scope(p_scope);
534 break;
535 case ALL_FROM:
536 case VALUE_LIST_ALL_FROM:
537 u.all_from->set_my_scope(p_scope);
538 break;
539 case TEMPLATE_LIST:
540 case VALUE_LIST:
541 case COMPLEMENTED_LIST:
542 case SUPERSET_MATCH:
543 case SUBSET_MATCH:
544 case PERMUTATION_MATCH:
545 u.templates->set_my_scope(p_scope);
546 break;
547 case NAMED_TEMPLATE_LIST:
548 u.named_templates->set_my_scope(p_scope);
549 break;
550 case INDEXED_TEMPLATE_LIST:
551 u.indexed_templates->set_my_scope(p_scope);
552 break;
553 case VALUE_RANGE:
554 u.value_range->set_my_scope(p_scope);
555 break;
556 case CSTR_PATTERN:
557 case USTR_PATTERN:
558 u.pstring->set_my_scope(p_scope);
559 break;
560// default:
561// FATAL_ERROR("Template::set_my_scope()");
562 }
563 if (length_restriction) length_restriction->set_my_scope(p_scope);
564 }
565
566 void Template::set_genname_recursive(const string& p_genname)
567 {
568 set_genname(p_genname);
569 switch (templatetype) {
570 case TEMPLATE_LIST: {
571 if (!my_governor) return; // error recovery
572 Type *type = my_governor->get_type_refd_last();
573 Int offset;
574 if (type->get_typetype() == Type::T_ARRAY)
575 offset = type->get_dimension()->get_offset();
576 else offset = 0;
577 size_t nof_ts = u.templates->get_nof_ts();
578 for (size_t i = 0; i < nof_ts; i++) {
579 string embedded_genname(p_genname);
580 embedded_genname += '[';
581 embedded_genname += Int2string(offset + i);
582 embedded_genname += ']';
583 u.templates->get_t_byIndex(i)->set_genname_recursive(embedded_genname);
584 }
585 break; }
586 case NAMED_TEMPLATE_LIST: {
587 if (!my_governor) return; // error recovery
588 Type *type = my_governor->get_type_refd_last();
589 size_t nof_nts = u.named_templates->get_nof_nts();
590 for (size_t i = 0; i < nof_nts; i++) {
591 NamedTemplate *nt = u.named_templates->get_nt_byIndex(i);
592 string embedded_genname(p_genname);
593 embedded_genname += '.';
594 if (type->get_typetype() == Type::T_ANYTYPE)
595 embedded_genname += "AT_";
596 embedded_genname += nt->get_name().get_name();
597 embedded_genname += "()";
598 nt->get_template()->set_genname_recursive(embedded_genname);
599 }
600 break; }
601 default:
602 break;
603 }
604 }
605
606 void Template::set_genname_prefix(const char *p_genname_prefix)
607 {
608 GovernedSimple::set_genname_prefix(p_genname_prefix);
609 switch (templatetype) {
610 case TEMPLATE_LIST:
611 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
612 u.templates->get_t_byIndex(i)->set_genname_prefix(p_genname_prefix);
613 break;
614 case NAMED_TEMPLATE_LIST:
615 for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++)
616 u.named_templates->get_nt_byIndex(i)->get_template()
617 ->set_genname_prefix(p_genname_prefix);
618 break;
619 case INDEXED_TEMPLATE_LIST:
620 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++)
621 u.indexed_templates->get_it_byIndex(i)->get_template()
622 ->set_genname_prefix(p_genname_prefix);
623 break;
624 default:
625 break;
626 }
627 }
628
629 void Template::set_code_section(code_section_t p_code_section)
630 {
631 GovernedSimple::set_code_section(p_code_section);
632 switch (templatetype) {
633 case SPECIFIC_VALUE:
634 u.specific_value->set_code_section(p_code_section);
635 break;
636 case TEMPLATE_REFD:
637 u.ref.ref->set_code_section(p_code_section);
638 break;
639 case TEMPLATE_INVOKE:
640 u.invoke.v->set_code_section(p_code_section);
641 if(u.invoke.t_list) u.invoke.t_list->set_code_section(p_code_section);
642 if(u.invoke.ap_list)
643 for(size_t i = 0; i < u.invoke.ap_list->get_nof_pars(); i++)
644 u.invoke.ap_list->get_par(i)->set_code_section(p_code_section);
645 break;
646 case TEMPLATE_LIST:
647 case VALUE_LIST:
648 case COMPLEMENTED_LIST:
649 case SUPERSET_MATCH:
650 case SUBSET_MATCH:
651 case PERMUTATION_MATCH:
652 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
653 u.templates->get_t_byIndex(i)->set_code_section(p_code_section);
654 break;
655 case NAMED_TEMPLATE_LIST:
656 for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++)
657 u.named_templates->get_nt_byIndex(i)->get_template()
658 ->set_code_section(p_code_section);
659 break;
660 case INDEXED_TEMPLATE_LIST:
661 for (size_t i = 0; i <u.indexed_templates->get_nof_its(); i++)
662 u.indexed_templates->get_it_byIndex(i)
663 ->set_code_section(p_code_section);
664 break;
665 case VALUE_RANGE:
666 u.value_range->set_code_section(p_code_section);
667 break;
668 case CSTR_PATTERN:
669 case USTR_PATTERN:
670 u.pstring->set_code_section(p_code_section);
671 break;
672 default:
673 break;
674 }
675 if (length_restriction)
676 length_restriction->set_code_section(p_code_section);
677 }
678
679 void Template::set_templatetype(templatetype_t p_templatetype)
680 {
681 if (p_templatetype == templatetype) return;
682 if (p_templatetype == TEMPLATE_ERROR) {
683 clean_up();
684 templatetype = TEMPLATE_ERROR;
685 return;
686 }
687 switch (templatetype) {
688 case SPECIFIC_VALUE: // current type
689 switch(p_templatetype) {
690 case TEMPLATE_REFD: {
691 Value *v = u.specific_value;
692 u.ref.ref = v->steal_ttcn_ref_base();
693 u.ref.refd = 0;
694 u.ref.refd_last = 0;
695 delete v;
696 break; }
697 case TEMPLATE_INVOKE: {
698 Value *v = u.specific_value;
699 v->steal_invoke_data(u.invoke.v, u.invoke.t_list, u.invoke.ap_list);
700 delete v;
701 break; }
702 default:
703 FATAL_ERROR("Template::set_templatetype()");
704 }
705 break;
706 case TEMPLATE_LIST: // current type
707 if (p_templatetype == NAMED_TEMPLATE_LIST) {
708 // TEMPLATE_LIST -> NAMED_TEMPLATE_LIST:
709 // value list -> assignment notation
710 // applicable to record types, signatures and empty set types
711 if (!my_governor) FATAL_ERROR("Template::set_templatetype()");
712 Type *t = my_governor->get_type_refd_last();
713 size_t nof_comps = t->get_nof_comps(); // "expected" nr of components
714 Templates *sts = u.templates;
715 size_t nof_temps = sts->get_nof_ts(); // "actual" nr in the list
716 Type::typetype_t tt = t->get_typetype();
717 switch (tt) {
718 case Type::T_SEQ_T:
719 case Type::T_SEQ_A:
720 case Type::T_SIGNATURE:
721 break;
722 case Type::T_SET_A:
723 case Type::T_SET_T:
724 if (nof_temps == 0 && nof_comps == 0) break;
725 default:
726 FATAL_ERROR("Template::set_templatetype()");
727 }
728 // If it's a record or set template, allow fewer elements than
729 // what is required, because implicit omit may take care of it.
730 // If it's a signature template, be precise.
731 bool allow_fewer = false;
732 switch (my_governor->get_typetype()) {
733 case Type::T_SEQ_T: case Type::T_SET_T:
734 allow_fewer = true;
735 break;
736 case Type::T_SIGNATURE: // be precise
737 break;
738 default: // not possible, fatal error ?
739 break;
740 }
741 if ( nof_temps > nof_comps
742 || (!allow_fewer && (nof_temps < nof_comps))) {
743 error("Too %s elements in value list notation for type `%s': "
744 "%lu was expected instead of %lu",
745 nof_temps > nof_comps ? "many" : "few",
746 t->get_typename().c_str(),
747 (unsigned long) nof_comps, (unsigned long) nof_temps);
748 }
749 size_t upper_limit; // min(nof_temps, nof_comps)
750 bool all_notused;
751 if (nof_temps <= nof_comps) {
752 upper_limit = nof_temps;
753 all_notused = true;
754 } else {
755 upper_limit = nof_comps;
756 all_notused = false;
757 }
758 u.named_templates = new NamedTemplates;
759 for (size_t i = 0; i < upper_limit; i++) {
760 Template*& temp = sts->get_t_byIndex(i);
761 if (temp->templatetype == TEMPLATE_NOTUSED) continue;
762 all_notused = false;
763 NamedTemplate *nt = new
764 NamedTemplate(t->get_comp_id_byIndex(i).clone(), temp);
765 nt->set_location(*temp);
766 u.named_templates->add_nt(nt);
767 temp = 0;
768 }
769 u.named_templates->set_my_scope(get_my_scope());
770 u.named_templates->set_fullname(get_fullname());
771 delete sts;
772 if (all_notused && nof_temps > 0 && tt != Type::T_SIGNATURE)
773 warning("All elements of value list notation for type `%s' are "
774 "not used symbols (`-')", t->get_typename().c_str());
775 } else FATAL_ERROR("Template::set_templatetype()");
776 break;
777 case CSTR_PATTERN: // current type
778 if (p_templatetype == USTR_PATTERN)
779 templatetype = USTR_PATTERN;
780 else
781 FATAL_ERROR("Template::set_templatetype()");
782 break;
783 default:
784 FATAL_ERROR("Template::set_templatetype()");
785 }
786 templatetype = p_templatetype;
787 }
788
789 const char *Template::get_templatetype_str() const
790 {
791 switch(templatetype) {
792 case TEMPLATE_ERROR:
793 return "erroneous template";
794 case TEMPLATE_NOTUSED:
795 return "not used symbol";
796 case OMIT_VALUE:
797 return "omit value";
798 case ANY_VALUE:
799 return "any value";
800 case ANY_OR_OMIT:
801 return "any or omit";
802 case SPECIFIC_VALUE:
803 return "specific value";
804 case TEMPLATE_REFD:
805 return "referenced template";
806 case TEMPLATE_INVOKE:
807 return "template returning invoke";
808 case ALL_FROM:
809 case VALUE_LIST_ALL_FROM:
810 return "template with 'all from'";
811 case TEMPLATE_LIST:
812 return "value list notation";
813 case NAMED_TEMPLATE_LIST:
814 return "assignment notation";
815 case INDEXED_TEMPLATE_LIST:
816 return "assignment notation with array indices";
817 case VALUE_RANGE:
818 return "value range match";
819 case VALUE_LIST:
820 return "value list match";
821 case COMPLEMENTED_LIST:
822 return "complemented list match";
823 case SUPERSET_MATCH:
824 return "superset match";
825 case SUBSET_MATCH:
826 return "subset match";
827 case PERMUTATION_MATCH:
828 return "permutation match";
829 case BSTR_PATTERN:
830 return "bitstring pattern";
831 case HSTR_PATTERN:
832 return "hexstring pattern";
833 case OSTR_PATTERN:
834 return "octetstring pattern";
835 case CSTR_PATTERN:
836 return "character string pattern";
837 case USTR_PATTERN:
838 return "universal string pattern";
839 default:
840 return "unknown template";
841 }
842 }
843
844 bool Template::is_undef_lowerid()
845 {
846 return templatetype == SPECIFIC_VALUE &&
847 u.specific_value->is_undef_lowerid();
848 }
849
850 void Template::set_lowerid_to_ref()
851 {
852 switch (templatetype) {
853 case SPECIFIC_VALUE:
854 u.specific_value->set_lowerid_to_ref();
855 if (u.specific_value->get_valuetype() == Value::V_REFD) {
856 Common::Assignment *t_ass =
857 u.specific_value->get_reference()->get_refd_assignment(false);
858 if (t_ass) {
859 switch (t_ass->get_asstype()) {
860 case Common::Assignment::A_MODULEPAR_TEMP:
861 case Common::Assignment::A_TEMPLATE:
862 case Common::Assignment::A_VAR_TEMPLATE:
863 case Common::Assignment::A_PAR_TEMPL_IN:
864 case Common::Assignment::A_PAR_TEMPL_OUT:
865 case Common::Assignment::A_PAR_TEMPL_INOUT:
866 case Common::Assignment::A_FUNCTION_RTEMP:
867 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
868 set_templatetype(TEMPLATE_REFD);
869 default:
870 break;
871 }
872 } else set_templatetype(TEMPLATE_ERROR);
873 }
874 break;
875 case VALUE_LIST:
876 case COMPLEMENTED_LIST:
877 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
878 u.templates->get_t_byIndex(i)->set_lowerid_to_ref();
879 break;
880 case VALUE_RANGE:
881 u.value_range->set_lowerid_to_ref();
882 break;
883 default:
884 break;
885 }
886 }
887
888 Type::typetype_t Template::get_expr_returntype(Type::expected_value_t exp_val)
889 {
890 switch (templatetype) {
891 case TEMPLATE_ERROR:
892 return Type::T_ERROR;
893 case SPECIFIC_VALUE:
894 return u.specific_value->get_expr_returntype(exp_val);
895 case TEMPLATE_REFD: {
896 Type *t = get_expr_governor(exp_val);
897 if (t) return t->get_type_refd_last()->get_typetype_ttcn3();
898 else return Type::T_ERROR; }
899 case TEMPLATE_INVOKE: {
900 Type *t = get_expr_governor(exp_val);
901 if(t) return t->get_type_refd_last()->get_typetype_ttcn3();
902 else return Type::T_ERROR; }
903 case VALUE_LIST:
904 case COMPLEMENTED_LIST:
905 for (size_t i = 0; i < u.templates->get_nof_ts(); i++) {
906 Type::typetype_t tt = u.templates->get_t_byIndex(i)
907 ->get_expr_returntype(exp_val);
908 if (tt != Type::T_UNDEF) return tt;
909 }
910 return Type::T_UNDEF;
911 case VALUE_RANGE:
912 return u.value_range->get_expr_returntype(exp_val);
913 case SUPERSET_MATCH:
914 case SUBSET_MATCH:
915 return Type::T_SETOF;
916 case BSTR_PATTERN:
917 return Type::T_BSTR;
918 case HSTR_PATTERN:
919 return Type::T_HSTR;
920 case OSTR_PATTERN:
921 return Type::T_OSTR;
922 case CSTR_PATTERN:
923 return Type::T_CSTR;
924 case USTR_PATTERN:
925 return Type::T_USTR;
926 default:
927 return Type::T_UNDEF;
928 }
929 }
930
931 Type *Template::get_expr_governor(Type::expected_value_t exp_val)
932 {
933 if (my_governor) return my_governor;
934 switch (templatetype) {
935 case SPECIFIC_VALUE:
936 return u.specific_value->get_expr_governor(exp_val);
937 case VALUE_LIST:
938 case COMPLEMENTED_LIST:
939 for (size_t i = 0; i < u.templates->get_nof_ts(); i++) {
940 Type *t = u.templates->get_t_byIndex(i)->get_expr_governor(exp_val);
941 if (t) return t;
942 }
943 return 0;
944 case VALUE_RANGE:
945 return u.value_range->get_expr_governor(exp_val);
946 case TEMPLATE_REFD: {
947 Type *t = u.ref.ref->get_refd_assignment()->get_Type()
948 ->get_field_type(u.ref.ref->get_subrefs(), exp_val);
949 if (!t) set_templatetype(TEMPLATE_ERROR);
950 return t;
951 }
952 case TEMPLATE_INVOKE: {
953 Type *t = u.invoke.v->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE);
954 if(!t) {
955 if(u.invoke.v->get_valuetype() != Value::V_ERROR)
956 u.invoke.v->error("A value of type function expected");
957 goto error;
958 }
959 t = t->get_type_refd_last();
960 switch(t->get_typetype()) {
961 case Type::T_FUNCTION:
962 if(exp_val==Type::EXPECTED_DYNAMIC_VALUE && t->get_returns_template()){
963 error("Reference to a value was expected instead of a "
964 "template of type `%s'"
965 , t->get_function_return_type()->get_typename().c_str());
966 goto error;
967 }
968 return t->get_function_return_type();
969 case Type::T_ALTSTEP:
970 goto error;
971 default:
972 u.invoke.v->error("A value of type function expected instead of `%s'",
973 t->get_typename().c_str());
974 goto error;
975 }
976 break; }
977 default:
978 return Type::get_pooltype(get_expr_returntype(exp_val));
979 }
980 error:
981 set_templatetype(TEMPLATE_ERROR);
982 return 0;
983 }
984
985 void Template::set_my_governor(Type *p_gov)
986 {
987 if (!p_gov)
988 FATAL_ERROR("Template::set_my_governor(): NULL parameter");
989 my_governor=p_gov;
990 }
991
992 Type *Template::get_my_governor() const
993 {
994 return my_governor;
995 }
996
997 void Template::set_length_restriction(LengthRestriction *p_lr)
998 {
999 if (length_restriction) FATAL_ERROR("Template::set_length_restriction()");
1000 length_restriction = p_lr;
1001 }
1002
1003 Template::completeness_t
1004 Template::get_completeness_condition_seof(bool incomplete_allowed)
1005 {
1006 if (!incomplete_allowed) return C_MUST_COMPLETE;
1007 else if (!base_template) return C_MAY_INCOMPLETE;
1008 else {
1009 Template *t = base_template->get_template_refd_last();
1010 switch (t->templatetype) {
1011 // partial overwriting is allowed
1012 case TEMPLATE_ERROR: // to suppress more errors
1013 case TEMPLATE_NOTUSED: // modifying a modified template
1014 case ANY_VALUE: // in case of ?
1015 case ANY_OR_OMIT: // in case of *
1016 case TEMPLATE_REFD: // e.g. the actual value of a formal parameter
1017 case TEMPLATE_INVOKE:
1018 case NAMED_TEMPLATE_LIST: // t is erroneous
1019 case INDEXED_TEMPLATE_LIST:
1020 return C_MAY_INCOMPLETE;
1021 case TEMPLATE_LIST:
1022 switch (my_governor->get_type_refd_last()->get_typetype()) {
1023 case Type::T_SEQOF:
1024 case Type::T_SETOF:
1025 // only the first elements can be incomplete
1026 return C_PARTIAL;
1027 default:
1028 // we are in error recovery
1029 return C_MAY_INCOMPLETE;
1030 }
1031 break; // should not get here
1032 default:
1033 // partial overwriting is not allowed for literal specific values,
1034 // matching ranges/lists/sets and patterns
1035 return C_MUST_COMPLETE;
1036 }
1037 }
1038 }
1039
1040 Template::completeness_t Template::get_completeness_condition_choice
1041 (bool incomplete_allowed, const Identifier& p_fieldname)
1042 {
1043 if (!incomplete_allowed) return C_MUST_COMPLETE;
1044 else if (!base_template) return C_MAY_INCOMPLETE;
1045 else {
1046 Template *t = base_template->get_template_refd_last();
1047 switch (t->templatetype) {
1048 // partial overwriting is allowed
1049 case TEMPLATE_ERROR: // to suppress more errors
1050 case TEMPLATE_NOTUSED: // t is erroneous
1051 case ANY_VALUE: // in case of ?
1052 case ANY_OR_OMIT: // in case of *
1053 case TEMPLATE_REFD: // e.g. the actual value of a formal parameter
1054 case TEMPLATE_INVOKE:
1055 case TEMPLATE_LIST: // t is erroneous
1056 return C_MAY_INCOMPLETE;
1057 case NAMED_TEMPLATE_LIST: // some fields may be missing
1058 if (t->u.named_templates->has_nt_withName(p_fieldname))
1059 return C_MAY_INCOMPLETE;
1060 else return C_MUST_COMPLETE;
1061 default:
1062 // partial overwriting is not allowed for literal specific values,
1063 // matching ranges/lists/sets and patterns
1064 return C_MUST_COMPLETE;
1065 }
1066 }
1067 }
1068
1069 void Template::add_named_temp(NamedTemplate* nt) {
1070 if (templatetype != NAMED_TEMPLATE_LIST)
1071 FATAL_ERROR("Template::add_named_temp()");
1072 u.named_templates->add_nt(nt);
1073 }
1074
1075 Value *Template::get_specific_value() const
1076 {
1077 if (templatetype != SPECIFIC_VALUE)
1078 FATAL_ERROR("Template::get_specific_value()");
1079 return u.specific_value;
1080 }
1081
1082 Ref_base *Template::get_reference() const
1083 {
1084 if (templatetype != TEMPLATE_REFD)
1085 FATAL_ERROR("Template::get_reference()");
1086 return u.ref.ref;
1087 }
1088
1089 ValueRange *Template::get_value_range() const
1090 {
1091 if (templatetype != VALUE_RANGE)
1092 FATAL_ERROR("Template::get_value_range()");
1093 return u.value_range;
1094 }
1095
1096 PatternString* Template::get_cstr_pattern() const
1097 {
1098 if (templatetype != CSTR_PATTERN)
1099 FATAL_ERROR("Template::get_cstr_pattern()");
1100 return u.pstring;
1101 }
1102
1103 PatternString* Template::get_ustr_pattern() const
1104 {
1105 if (templatetype != USTR_PATTERN)
1106 FATAL_ERROR("Template::get_ustr_pattern()");
1107 return u.pstring;
1108 }
1109
1110 size_t Template::get_nof_comps() const
1111 {
1112 switch (templatetype) {
1113 case TEMPLATE_LIST:
1114 case VALUE_LIST:
1115 case COMPLEMENTED_LIST:
1116 case SUPERSET_MATCH:
1117 case SUBSET_MATCH:
1118 case PERMUTATION_MATCH:
1119 return u.templates->get_nof_ts();
1120 case NAMED_TEMPLATE_LIST:
1121 return u.named_templates->get_nof_nts();
1122 case INDEXED_TEMPLATE_LIST:
1123 return u.indexed_templates->get_nof_its();
1124 default:
1125 FATAL_ERROR("Template::get_of_comps()");
1126 return 0;
1127 }
1128 }
1129
1130 Template *Template::get_temp_byIndex(size_t n) const
1131 {
1132 switch (templatetype) {
1133 case TEMPLATE_LIST:
1134 case VALUE_LIST:
1135 case COMPLEMENTED_LIST:
1136 case SUPERSET_MATCH:
1137 case SUBSET_MATCH:
1138 case PERMUTATION_MATCH:
1139 return u.templates->get_t_byIndex(n);
1140 default:
1141 FATAL_ERROR("Template::get_temp_byIndex()");
1142 return 0;
1143 }
1144 }
1145
1146 IndexedTemplate *Template::get_indexedtemp_byIndex(size_t n) const
1147 {
1148 if (templatetype != INDEXED_TEMPLATE_LIST)
1149 FATAL_ERROR("Template::get_indexedtemp_byIndex()");
1150 return u.indexed_templates->get_it_byIndex(n);
1151 }
1152
1153 NamedTemplate *Template::get_namedtemp_byIndex(size_t n) const
1154 {
1155 if (templatetype != NAMED_TEMPLATE_LIST)
1156 FATAL_ERROR("Template::get_namedtemp_byIndex()");
1157 return u.named_templates->get_nt_byIndex(n);
1158 }
1159
1160 Template *Template::get_all_from() const
1161 {
1162 if (templatetype != ALL_FROM
1163 &&templatetype != VALUE_LIST_ALL_FROM)
1164 FATAL_ERROR("Template::get_all_from()");
1165 return u.all_from;
1166 }
1167
1168 // Not applicable to INDEXED_TEMPLATE_LIST nodes. The actual number of
1169 // elements is not known.
1170 size_t Template::get_nof_listitems() const
1171 {
1172 if (templatetype != TEMPLATE_LIST)
1173 FATAL_ERROR("Template::get_nof_listitems()");
1174 if (has_permutation) {
1175 size_t nof_ts = u.templates->get_nof_ts(), ret_val = 0;
1176 for (size_t i = 0; i < nof_ts; i++) {
1177 Template *t = u.templates->get_t_byIndex(i);
1178 if (t->templatetype == PERMUTATION_MATCH)
1179 ret_val += t->u.templates->get_nof_ts();
1180 else ret_val++;
1181 }
1182 return ret_val;
1183 } else return u.templates->get_nof_ts();
1184 }
1185
1186 Template *Template::get_listitem_byIndex(size_t n) const
1187 {
1188 if (templatetype != TEMPLATE_LIST)
1189 FATAL_ERROR("Template::get_listitam_byIndex()");
1190 if (has_permutation) {
1191 size_t nof_ts = u.templates->get_nof_ts(), index = 0;
1192 for (size_t i = 0; i < nof_ts; i++) {
1193 Template *t = u.templates->get_t_byIndex(i);
1194 if (t->templatetype == PERMUTATION_MATCH) {
1195 size_t nof_perm_ts = t->u.templates->get_nof_ts();
1196 if (n < index + nof_perm_ts)
1197 return t->u.templates->get_t_byIndex(n - index);
1198 else index += nof_perm_ts;
1199 } else {
1200 if (n == index) return t;
1201 else index++;
1202 }
1203 }
1204 FATAL_ERROR("Template::get_listitem_byIndex(): index overflow");
1205 return 0;
1206 } else return u.templates->get_t_byIndex(n);
1207 }
1208
1209 /** \todo revise and merge with get_template_refd() */
1210 Template* Template::get_template_refd_last(ReferenceChain *refch)
1211 {
1212 // return this for non-referenced templates
1213 if (templatetype != TEMPLATE_REFD) return this;
1214 // use the cached template if present
1215 else if (u.ref.refd_last) return u.ref.refd_last;
1216 else {
1217 Common::Assignment *t_ass = u.ref.ref->get_refd_assignment();
1218 // escape from invalid recursion loops
1219 if (templatetype != TEMPLATE_REFD) return this;
1220 if (!t_ass) FATAL_ERROR("Template::get_template_refd_last()");
1221 if (t_ass->get_asstype() != Common::Assignment::A_TEMPLATE) {
1222 // return this if the reference does not point to a template
1223 u.ref.refd_last = this;
1224 return u.ref.refd_last;
1225 }
1226 }
1227 // otherwise evaluate the reference
1228 bool destroy_refch;
1229 if (refch) {
1230 refch->mark_state();
1231 destroy_refch = false;
1232 } else {
1233 refch = new ReferenceChain(this, "While searching referenced template");
1234 destroy_refch = true;
1235 }
1236 Template *ret_val;
1237 if (refch->add(get_fullname())) {
1238 Template *t_refd = get_template_refd(refch);
1239 // get_template_refd() may set u.ref.refd_last if there are unfoldable
1240 // sub-references in u.ref.ref
1241 if (!u.ref.refd_last) {
1242 u.ref.refd_last = t_refd->get_template_refd_last(refch);
1243 }
1244 ret_val = u.ref.refd_last;
1245 } else {
1246 // a circular reference was found
1247 set_templatetype(TEMPLATE_ERROR);
1248 ret_val = this;
1249 }
1250 if (destroy_refch) delete refch;
1251 else refch->prev_state();
1252 return ret_val;
1253 }
1254
1255 Template* Template::get_refd_sub_template(Ttcn::FieldOrArrayRefs *subrefs,
1256 bool usedInIsbound,
1257 ReferenceChain *refch)
1258 {
1259 if (!subrefs) return this;
1260 Template *t=this;
1261 for (size_t i=0; i<subrefs->get_nof_refs(); i++) {
1262 if(!t) break;
1263 t=t->get_template_refd_last(refch);
1264 t->set_lowerid_to_ref();
1265 switch(t->templatetype) {
1266 case TEMPLATE_ERROR:
1267 return t;
1268 case TEMPLATE_REFD:
1269 case INDEXED_TEMPLATE_LIST:
1270 // unfoldable stuff
1271 return this;
1272 case SPECIFIC_VALUE:
1273 (void)t->u.specific_value->get_refd_sub_value(
1274 subrefs, i, usedInIsbound, refch); // only to report errors
1275 break;
1276 default:
1277 break;
1278 } // switch
1279 Ttcn::FieldOrArrayRef *ref=subrefs->get_ref(i);
1280 if(ref->get_type() == Ttcn::FieldOrArrayRef::FIELD_REF)
1281 t=t->get_refd_field_template(*ref->get_id(), *ref, usedInIsbound,
1282 refch);
1283 else t=t->get_refd_array_template(ref->get_val(), usedInIsbound, refch);
1284 }
1285 return t;
1286 }
1287
1288 Template* Template::get_template_refd(ReferenceChain *refch)
1289 {
1290 unsigned int const prev_err_count = get_error_count();
1291 if (templatetype != TEMPLATE_REFD)
1292 FATAL_ERROR("Template::get_template_refd()");
1293 // use the cached pointer if it is already set
1294 if (u.ref.refd) return u.ref.refd;
1295 Common::Assignment *ass = u.ref.ref->get_refd_assignment();
1296 if (!ass) FATAL_ERROR("Template::get_template_refd()");
1297 if(ass->get_asstype() == Common::Assignment::A_TEMPLATE) {
1298 FieldOrArrayRefs *subrefs = u.ref.ref->get_subrefs();
1299 Template *asst = ass->get_Template();
1300 Template *t = asst->get_refd_sub_template(
1301 subrefs, u.ref.ref->getUsedInIsbound(), refch);
1302 if (t) {
1303 u.ref.refd = t;
1304 // Why do we not set u.ref.refd_last ?
1305 }
1306 else if (subrefs && subrefs->has_unfoldable_index()) {
1307 // some array indices could not be evaluated
1308 u.ref.refd = this;
1309 u.ref.refd_last = this;
1310 } else if (u.ref.ref->getUsedInIsbound()) {
1311 u.ref.refd = this;
1312 u.ref.refd_last = this;
1313 } else {
1314 // an error was found while resolving sub-references
1315 if (get_error_count() == prev_err_count) {
1316 // it was not reported, report it now
1317 error("Using a template which refers to a non-template is not supported");
1318 asst->note("Workaround: change the right hand side refer to a template");
1319 if (ass->is_local()) {
1320 ass->note("Workaround: change the template definition "
1321 "to a var template");
1322 }
1323 }
1324 set_templatetype(TEMPLATE_ERROR);
1325 return this;
1326 }
1327 } else {
1328 // the reference is unfoldable
1329 u.ref.refd = this;
1330 }
1331 return u.ref.refd;
1332 }
1333
1334 Template* Template::get_refd_field_template(const Identifier& field_id,
1335 const Location& loc, bool usedInIsbound, ReferenceChain *refch)
1336 {
1337 switch (templatetype) {
1338 case OMIT_VALUE:
1339 case ANY_VALUE:
1340 case ANY_OR_OMIT:
1341 case VALUE_LIST:
1342 case COMPLEMENTED_LIST:
1343 // the above template types are valid matching mechanisms,
1344 // but they cannot be sub-referenced
1345 loc.error("Reference to field `%s' of %s `%s'",
1346 field_id.get_dispname().c_str(), get_templatetype_str(),
1347 get_fullname().c_str());
1348 break;
1349 default:
1350 break;
1351 }
1352 if(!my_governor) FATAL_ERROR("Template::get_refd_field_template()");
1353 Type *t = my_governor->get_type_refd_last();
1354 const char *typetype_str="set";
1355 switch(t->get_typetype()) {
1356 case Type::T_ERROR:
1357 // remain silent
1358 return 0;
1359 case Type::T_CHOICE_A:
1360 case Type::T_CHOICE_T:
1361 case Type::T_OPENTYPE:
1362 case Type::T_ANYTYPE:
1363 if (!t->has_comp_withName(field_id)) {
1364 loc.error("Reference to non-existent union field `%s' in type `%s'",
1365 field_id.get_dispname().c_str(), t->get_typename().c_str());
1366 return 0;
1367 } else if (templatetype != NAMED_TEMPLATE_LIST) {
1368 // this is an invalid matching mechanism, the error is already reported
1369//error("invalid matching mechanism (not template list) but %d", templatetype);
1370 return 0;
1371 } else if (u.named_templates->get_nof_nts() != 1) {
1372 // this is an invalid union template (more than one active field)
1373 // the error is already reported
1374//error("invalid union template ");
1375 return 0;
1376 } else {
1377 NamedTemplate *nt = u.named_templates->get_nt_byIndex(0);
1378 if (nt->get_name() != field_id) {
1379 if (!usedInIsbound) {
1380 loc.error("Reference to inactive field `%s' in a template of"
1381 " union type `%s'. The active field is `%s'.",
1382 field_id.get_dispname().c_str(),
1383 t->get_typename().c_str(),
1384 nt->get_name().get_dispname().c_str());
1385 }
1386 return 0;
1387 } else {
1388 // everything is OK
1389 return nt->get_template();
1390 }
1391 }
1392 case Type::T_SEQ_A:
1393 case Type::T_SEQ_T:
1394 typetype_str="record";
1395 // no break
1396 case Type::T_SET_A:
1397 case Type::T_SET_T:
1398 if (!t->has_comp_withName(field_id)) {
1399 loc.error("Reference to non-existent %s field `%s' in type `%s'",
1400 typetype_str, field_id.get_dispname().c_str(),
1401 t->get_typename().c_str());
1402 return 0;
1403 } else if (templatetype != NAMED_TEMPLATE_LIST) {
1404 // this is an invalid matching mechanism
1405 // the error should be already reported
1406 return 0;
1407 } else if (u.named_templates->has_nt_withName(field_id)) {
1408 // the field is found, everything is OK
1409 return u.named_templates->get_nt_byName(field_id)->get_template();
1410 } else if (base_template) {
1411 // take the field from the base template (recursively)
1412 return base_template->get_template_refd_last(refch)
1413 ->get_refd_field_template(field_id, loc, usedInIsbound, refch);
1414 } else {
1415 if (!usedInIsbound) {
1416 // this should not happen unless there is an error
1417 // (e.g. missing field)
1418 loc.error("Reference to an unbound field `%s'",
1419 field_id.get_dispname().c_str());
1420 }
1421 return 0;
1422 }
1423 default:
1424 loc.error("Invalid field reference `%s': type `%s' "
1425 "does not have fields", field_id.get_dispname().c_str(),
1426 t->get_typename().c_str());
1427 return 0;
1428 }
1429 }
1430
1431 Template* Template::get_refd_array_template(Value *array_index,
1432 bool usedInIsbound,
1433 ReferenceChain *refch)
1434 {
1435 switch (templatetype) {
1436 case OMIT_VALUE:
1437 case ANY_VALUE:
1438 case ANY_OR_OMIT:
1439 case VALUE_LIST:
1440 case COMPLEMENTED_LIST:
1441 case SUPERSET_MATCH:
1442 case SUBSET_MATCH:
1443 // the above template types are valid matching mechanisms,
1444 // but they cannot be sub-referenced
1445 array_index->error("Reference with index to an element of %s `%s'",
1446 get_templatetype_str(), get_fullname().c_str());
1447 break;
1448 default:
1449 break;
1450 }
1451 Value *v_index = array_index->get_value_refd_last(refch);
1452 Int index = 0;
1453 bool index_available = false;
1454 if (!v_index->is_unfoldable()) {
1455 if (v_index->get_valuetype() == Value::V_INT) {
1456 index = v_index->get_val_Int()->get_val();
1457 index_available = true;
1458 } else {
1459 array_index->error("An integer value was expected as index");
1460 }
1461 }
1462 if (!my_governor) FATAL_ERROR("Template::get_refd_array_template()");
1463 Type *t = my_governor->get_type_refd_last();
1464 const char *typetype_str="set";
1465 switch(t->get_typetype()) {
1466 case Type::T_ERROR:
1467 // remain silent
1468 return 0;
1469 case Type::T_SEQOF:
1470 typetype_str="record";
1471 // no break
1472 case Type::T_SETOF:
1473 if (index_available) {
1474 if(index < 0) {
1475 array_index->error("A non-negative integer value was expected "
1476 "instead of %s for indexing a template of `%s of' type `%s'",
1477 Int2string(index).c_str(), typetype_str,
1478 t->get_typename().c_str());
1479 return 0;
1480 } else if (templatetype != TEMPLATE_LIST) {
1481 // remain silent the error has been already reported
1482 return 0;
1483 } else {
1484 size_t nof_elements = get_nof_listitems();
1485 if (index >= static_cast<Int>(nof_elements)) {
1486 array_index->error("Index overflow in a template of `%s of' type "
1487 "`%s': the index is %s, but the template has only %lu elements",
1488 typetype_str, t->get_typename().c_str(),
1489 Int2string(index).c_str(), (unsigned long) nof_elements);
1490 return 0;
1491 }
1492 }
1493 } else {
1494 // the index is not available or the error has been reported above
1495 return 0;
1496 }
1497 break;
1498 case Type::T_ARRAY:
1499 if (index_available) {
1500 ArrayDimension *dim = t->get_dimension();
1501 dim->chk_index(v_index, Type::EXPECTED_DYNAMIC_VALUE);
1502 if (templatetype == TEMPLATE_LIST && !dim->get_has_error()) {
1503 // perform the index transformation
1504 index -= dim->get_offset();
1505 // check for index underflow/overflow or too few elements in template
1506 if (index < 0 || index >= static_cast<Int>(get_nof_listitems()))
1507 return 0;
1508 } else {
1509 // remain silent, the error has been already reported
1510 return 0;
1511 }
1512 } else {
1513 // the index is not available or the error has been reported above
1514 return 0;
1515 }
1516 break;
1517 default:
1518 array_index->error("Invalid array element reference: type `%s' cannot "
1519 "be indexed", t->get_typename().c_str());
1520 return 0;
1521 }
1522 Template *ret_val = get_listitem_byIndex(index);
1523 if (ret_val->templatetype == TEMPLATE_NOTUSED) {
1524 if (base_template) {
1525 // take the referred element from the base template
1526 return base_template->get_template_refd_last(refch)
1527 ->get_refd_array_template(v_index, usedInIsbound, refch);
1528 } else {
1529 if(ret_val->get_templatetype() == TEMPLATE_NOTUSED)
1530 error("Not used symbol is not allowed in this context");
1531 return 0;
1532 }
1533 } else return ret_val;
1534 }
1535
1536 bool Template::temps_contains_anyornone_symbol() const
1537 {
1538 switch (templatetype) {
1539 case TEMPLATE_LIST:
1540 case SUPERSET_MATCH:
1541 case SUBSET_MATCH:
1542 case PERMUTATION_MATCH:
1543 break;
1544 default:
1545 FATAL_ERROR("Template::temps_contains_anyornone_symbol()");
1546 }
1547 size_t nof_comps = u.templates->get_nof_ts();
1548 for (size_t i = 0; i < nof_comps; i++) {
1549 Template *t = u.templates->get_t_byIndex(i);
1550 switch (t->templatetype) {
1551 case ANY_OR_OMIT:
3abe9331 1552 case ALL_FROM:
1553 // 'all from' clauses not known at compile time are also considered
1554 // as 'AnyOrNone'
970ed795
EL
1555 return true;
1556 case PERMUTATION_MATCH:
1557 // walk recursively
1558 if (t->temps_contains_anyornone_symbol()) return true;
1559 break;
1560 default:
1561 break;
1562 }
1563 }
1564 return false;
1565 }
1566
1567 size_t Template::get_nof_comps_not_anyornone() const
1568 {
1569 switch (templatetype) {
1570 case TEMPLATE_LIST:
1571 case SUPERSET_MATCH:
1572 case SUBSET_MATCH:
1573 case PERMUTATION_MATCH:
1574 break;
1575 default:
1576 FATAL_ERROR("Template::get_nof_comps_not_anyornone()");
1577 }
1578 size_t ret_val = 0;
1579 size_t nof_comps = u.templates->get_nof_ts();
1580 for (size_t i = 0; i < nof_comps; i++) {
1581 Template *t = u.templates->get_t_byIndex(i);
1582 switch (t->templatetype) {
1583 case ANY_OR_OMIT:
3abe9331 1584 case ALL_FROM:
970ed795
EL
1585 // do not count it
1586 break;
1587 case PERMUTATION_MATCH:
1588 // walk recursively
1589 ret_val += t->get_nof_comps_not_anyornone();
1590 break;
3abe9331 1591 default:
970ed795
EL
1592 // other types are counted as 1
1593 ret_val++;
1594 break;
1595 }
1596 }
1597 return ret_val;
1598 }
1599
1600 bool Template::pattern_contains_anyornone_symbol() const
1601 {
1602 switch (templatetype) {
1603 case BSTR_PATTERN:
1604 case HSTR_PATTERN:
1605 case OSTR_PATTERN:
1606 return u.pattern->find('*') < u.pattern->size();
1607 case CSTR_PATTERN:
1608 case USTR_PATTERN:
1609 return true;
1610 default:
1611 FATAL_ERROR("Template::pattern_contains_anyornone_symbol()");
1612 return false;
1613 }
1614 }
1615
1616 size_t Template::get_min_length_of_pattern() const
1617 {
1618 size_t ret_val = 0;
1619 switch (templatetype) {
1620 case BSTR_PATTERN:
1621 case HSTR_PATTERN: {
1622 size_t pattern_len = u.pattern->size();
1623 const char *pattern_ptr = u.pattern->c_str();
1624 for (size_t i = 0; i < pattern_len; i++)
1625 if (pattern_ptr[i] != '*') ret_val++;
1626 break; }
1627 case OSTR_PATTERN: {
1628 size_t pattern_len = u.pattern->size();
1629 const char *pattern_ptr = u.pattern->c_str();
1630 for (size_t i = 0; i < pattern_len; i++) {
1631 switch (pattern_ptr[i]) {
1632 case '*':
1633 // do not count
1634 break;
1635 case '?':
1636 // count as 1
1637 ret_val++;
1638 break;
1639 default:
1640 // count as 1 and skip over the next hex digit
1641 ret_val++;
1642 i++;
1643 }
1644 }
1645 break; }
1646 case CSTR_PATTERN:
1647 case USTR_PATTERN:
1648 break;
1649 default:
1650 FATAL_ERROR("Template::get_min_length_of_pattern()");
1651 }
1652 return ret_val;
1653 }
1654
1655 bool Template::is_Value() const
1656 {
1657 if (length_restriction || is_ifpresent) return false;
1658 switch (templatetype) {
1659 case TEMPLATE_ERROR:
1660 case TEMPLATE_NOTUSED:
1661 case OMIT_VALUE:
1662 return true;
1663 case SPECIFIC_VALUE:
1664 if(u.specific_value->get_valuetype() == Value::V_INVOKE) {
1665 Type *t = u.specific_value
1666 ->get_invoked_type(Type::EXPECTED_DYNAMIC_VALUE);
1667 if(t && t->get_type_refd_last()->get_typetype() == Type::T_FUNCTION &&
1668 t->get_type_refd_last()->get_returns_template()) return false;
1669 }
1670 return true;
1671 case TEMPLATE_LIST: {
1672 Templates *ts = u.templates;
1673 for (size_t i = 0; i < ts->get_nof_ts(); i++)
1674 if (!ts->get_t_byIndex(i)->is_Value()) return false;
1675 return true;
1676 }
1677 case NAMED_TEMPLATE_LIST: {
1678 NamedTemplates *ts = u.named_templates;
1679 for (size_t i = 0;i < ts->get_nof_nts(); i++)
1680 if (!ts->get_nt_byIndex(i)->get_template()->is_Value()) return false;
1681 return true;
1682 }
1683 case INDEXED_TEMPLATE_LIST: {
1684 IndexedTemplates *ts = u.indexed_templates;
1685 for (size_t i = 0; i < ts->get_nof_its(); i++)
1686 if (!ts->get_it_byIndex(i)->get_template()->is_Value()) return false;
1687 return true;
1688 }
1689 case TEMPLATE_REFD: {
1690 Common::Assignment *ass = u.ref.ref->get_refd_assignment();
1691 switch (ass->get_asstype()) {
1692 case Common::Assignment::A_EXT_CONST:
1693 case Common::Assignment::A_PAR_VAL:
1694 case Common::Assignment::A_PAR_VAL_IN:
1695 case Common::Assignment::A_PAR_VAL_OUT:
1696 case Common::Assignment::A_PAR_VAL_INOUT:
1697 case Common::Assignment::A_VAR:
1698 return true;
1699 default:
1700 return false;
1701 }
1702 }
1703 default:
1704 return false;
1705 }
1706 }
1707
1708 Value *Template::get_Value()
1709 {
1710 Value *ret_val;
1711 switch(templatetype) {
1712 case TEMPLATE_ERROR:
1713 ret_val = new Value(Value::V_ERROR);
1714 break;
1715 case TEMPLATE_NOTUSED:
1716 ret_val = new Value(Value::V_NOTUSED);
1717 break;
1718 case OMIT_VALUE:
1719 ret_val = new Value(Value::V_OMIT);
1720 break;
1721 case SPECIFIC_VALUE:
1722 ret_val = u.specific_value;
1723 u.specific_value = 0;
1724 set_templatetype(TEMPLATE_ERROR);
1725 return ret_val;
1726 case TEMPLATE_LIST: {
1727 Values *vs = new Values;
1728 size_t nof_ts = u.templates->get_nof_ts();
1729 Type* gov = 0;
1730 for (size_t i = 0; i < nof_ts; i++) {
1731 Value* v = u.templates->get_t_byIndex(i)->get_Value();
1732 if (!gov) gov = v->get_my_governor();
1733 vs->add_v(v);
1734 }
1735 ret_val = new Value(Value::V_SEQOF, vs);
af710487 1736 if (gov) gov = gov->get_parent_type();
1737 if (gov) ret_val->set_my_governor(gov);
970ed795
EL
1738 break; }
1739 case NAMED_TEMPLATE_LIST: {
1740 NamedValues *nvs = new NamedValues;
1741 size_t nof_nts = u.named_templates->get_nof_nts();
1742 Type* gov = 0;
1743 for (size_t i = 0; i < nof_nts; i++) {
1744 NamedTemplate *nt = u.named_templates->get_nt_byIndex(i);
1745 Value* v = nt->get_template()->get_Value();
1746 if (!gov) gov = v->get_my_governor();
1747 NamedValue *nv = new NamedValue(nt->get_name().clone(), v);
1748 nv->set_location(*nt);
1749 nvs->add_nv(nv);
1750 }
1751 ret_val = new Value(Value::V_SEQ, nvs);
af710487 1752 if (gov) gov = gov->get_parent_type();
1753 if (gov) ret_val->set_my_governor(gov);
970ed795
EL
1754 break; }
1755 case INDEXED_TEMPLATE_LIST: {
1756 Values *ivs = new Values(true);
1757 size_t nof_its = u.indexed_templates->get_nof_its();
1758 Type* gov = 0;
1759 for (size_t i = 0; i < nof_its; i++) {
1760 IndexedTemplate *it = u.indexed_templates->get_it_byIndex(i);
1761 Value* v = it->get_template()->get_Value();
1762 if (!gov) gov = v->get_my_governor();
1763 IndexedValue *iv = new IndexedValue(it->get_index().clone(), v);
1764 iv->set_location(*it);
1765 ivs->add_iv(iv);
1766 }
1767 ret_val = new Value(Value::V_SEQOF, ivs);
af710487 1768 if (gov) gov = gov->get_parent_type();
1769 if (gov) ret_val->set_my_governor(gov);
970ed795
EL
1770 break; }
1771 default:
1772 FATAL_ERROR("Template::get_Value()");
1773 ret_val = 0;
1774 break;
1775 }
1776 ret_val->set_location(*this);
1777 ret_val->set_my_scope(get_my_scope());
1778 ret_val->set_fullname(get_fullname());
1779 return ret_val;
1780 }
1781
1782 bool Template::is_Ref() const
1783 {
1784 if (length_restriction || is_ifpresent || templatetype != SPECIFIC_VALUE)
1785 return false;
1786 Value *v = u.specific_value;
1787 switch (v->get_valuetype()) {
1788 case Value::V_UNDEF_LOWERID:
1789 return true;
1790 case Value::V_REFD:
1791 if (dynamic_cast<Ref_base*>(v->get_reference())) return true;
1792 else return false;
1793 default:
1794 return false;
1795 }
1796 }
1797
1798 Ref_base *Template::get_Ref()
1799 {
1800 if (templatetype != SPECIFIC_VALUE)
1801 FATAL_ERROR("Template::get_Ref()");
1802 return u.specific_value->steal_ttcn_ref_base();
1803 }
1804
1805 void Template::chk_recursions(ReferenceChain& refch)
1806 {
1807 if (recurs_checked) return;
1808 Template *t = this;
1809 for ( ; ; ) {
1810 if (t->templatetype == SPECIFIC_VALUE) break;
1811 else if (!refch.add(t->get_fullname())) goto end;
1812 else if (t->templatetype != TEMPLATE_REFD) break;
1813 ActualParList *parlist = t->u.ref.ref->get_parlist();
1814 if (parlist) parlist->chk_recursions(refch);
1815 Template *t_refd = t->get_template_refd(&refch);
1816 if (t_refd == t) break;
1817 else t = t_refd;
1818 }
1819 t->set_lowerid_to_ref();
1820 switch (t->templatetype) {
1821 case SPECIFIC_VALUE:
1822 t->u.specific_value->chk_recursions(refch);
1823 break;
1824 case TEMPLATE_LIST:
1825 case VALUE_LIST:
1826 case COMPLEMENTED_LIST:
1827 case SUPERSET_MATCH:
1828 case SUBSET_MATCH:
1829 case PERMUTATION_MATCH:
1830 for (size_t i = 0; i < t->u.templates->get_nof_ts(); i++) {
1831 refch.mark_state();
1832 t->u.templates->get_t_byIndex(i)->chk_recursions(refch);
1833 refch.prev_state();
1834 }
1835 break;
1836 case NAMED_TEMPLATE_LIST:
1837 for (size_t i = 0; i < t->u.named_templates->get_nof_nts(); i++) {
1838 refch.mark_state();
1839 t->u.named_templates->get_nt_byIndex(i)
1840 ->get_template()->chk_recursions(refch);
1841 refch.prev_state();
1842 }
1843 break;
1844 case INDEXED_TEMPLATE_LIST:
1845 for (size_t i = 0; i < t->u.indexed_templates->get_nof_its(); i++) {
1846 refch.mark_state();
1847 t->u.indexed_templates->get_it_byIndex(i)
1848 ->get_template()->chk_recursions(refch);
1849 refch.prev_state();
1850 }
1851 break;
1852 case CSTR_PATTERN:
1853 case USTR_PATTERN:
1854 t->u.pstring->chk_recursions(refch);
1855 break;
1856 default:
1857 break;
1858 }
1859end:
1860 recurs_checked = true;
1861 }
1862
1863 void Template::chk_specific_value(bool allow_omit)
1864 {
1865 Template *t = get_template_refd_last();
1866 if (!allow_omit && t->templatetype==OMIT_VALUE) {
1867 t->error("A specific value was expected instead of omit");
1868 }
1869 chk_specific_value_generic();
1870 }
1871
1872 void Template::chk_specific_value_generic()
1873 {
1874 if (specific_value_checked) return;
1875 Template *t = get_template_refd_last();
1876 if (t->specific_value_checked) return;
1877 switch (t->templatetype) {
1878 case TEMPLATE_ERROR:
1879 case TEMPLATE_NOTUSED:
1880 case TEMPLATE_REFD: // unfoldable reference
1881 break;
1882 case SPECIFIC_VALUE:
1883 if(u.specific_value->get_valuetype() == Value::V_INVOKE) {
1884 Type *t_type = u.specific_value
1885 ->get_invoked_type(Type::EXPECTED_DYNAMIC_VALUE);
1886 if(t_type && t_type->get_type_refd_last()->get_returns_template()) {
1887 set_templatetype(TEMPLATE_INVOKE);
1888 chk_invoke();
1889 }
1890 }
1891 break;
1892 case TEMPLATE_INVOKE:
1893 chk_invoke();
1894 break;
1895 case TEMPLATE_LIST:
1896 for (size_t i = 0; i < t->u.templates->get_nof_ts(); i++)
1897 t->u.templates->get_t_byIndex(i)->chk_specific_value_generic();
1898 break;
1899 case NAMED_TEMPLATE_LIST:
1900 for (size_t i = 0; i < t->u.named_templates->get_nof_nts(); i++)
1901 t->u.named_templates->get_nt_byIndex(i)
1902 ->get_template()->chk_specific_value_generic();
1903 break;
1904 case INDEXED_TEMPLATE_LIST:
1905 for (size_t i = 0; i < t->u.indexed_templates->get_nof_its(); i++)
1906 t->u.indexed_templates->get_it_byIndex(i)
1907 ->get_template()->chk_specific_value_generic();
1908 break;
1909 case OMIT_VALUE:
1910 break;
1911 default:
1912 t->error("A specific value was expected instead of %s",
1913 t->get_templatetype_str());
1914 break;
1915 }
1916 t->specific_value_checked = true;
1917 specific_value_checked = true;
1918 }
1919
1920 void Template::chk_invoke()
1921 {
1922 if(templatetype != TEMPLATE_INVOKE) FATAL_ERROR("Template::chk_invoke()");
1923 if(!u.invoke.t_list) return; //already checked
1924 Error_Context cntxt(this, "In `apply()' operation");
1925 Type *t = u.invoke.v->get_expr_governor_last();
1926 if (t) {
1927 if (t->get_typetype() != Type::T_FUNCTION) {
1928 u.invoke.v->error("A value of type function was expected in the "
1929 "argument instead of `%s'", t->get_typename().c_str());
1930 set_templatetype(TEMPLATE_ERROR);
1931 return;
1932 }
1933 } else {
1934 if (u.invoke.v->get_valuetype() != Value::V_ERROR)
1935 u.invoke.v->error("A value of type function was expected in the "
1936 "argument");
1937 set_templatetype(TEMPLATE_ERROR);
1938 return;
1939 }
1940 my_scope->chk_runs_on_clause(t, *this, "call");
1941 Ttcn::FormalParList *fp_list = t->get_fat_parameters();
1942 Ttcn::ActualParList *parlist = new Ttcn::ActualParList;
1943 bool is_erroneous = fp_list->fold_named_and_chk(u.invoke.t_list,parlist);
1944 delete u.invoke.t_list;
1945 u.invoke.t_list = 0;
1946 if(is_erroneous) {
1947 delete parlist;
1948 u.invoke.ap_list = 0;
1949 } else {
1950 parlist->set_fullname(get_fullname());
1951 parlist->set_my_scope(get_my_scope());
1952 u.invoke.ap_list = parlist;
1953 }
1954 }
1955
1956 Templates *Template::harbinger(Template *t, bool from_permutation, bool killer)
1957 {
1958 Templates *new_templates = new Templates;
1959 switch (t->u.all_from->templatetype) {
1960 case SPECIFIC_VALUE: {
1961 Value *innerv = t->u.all_from->get_specific_value();
1962 //if (v->get_valuetype() == Value::V_UNDEF_LOWERID)
1963 innerv->set_lowerid_to_ref();
1964 // should be a ref now
1965 bool can_flatten = true;
1966 Common::Reference *ref = innerv->get_reference();
1967 if (dynamic_cast<Ttcn::Ref_pard*>(ref)) {
1968 // Cannot flatten at compile time if the template has parameters.
1969 can_flatten = false;
1970 }
a38c6d4c 1971
1972 // check for subreferences in the 'all from' target
1973 FieldOrArrayRefs* subrefs = ref->get_subrefs();
1974 if (NULL != subrefs) {
a38c6d4c 1975 for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
1976 FieldOrArrayRef* subref = subrefs->get_ref(i);
1977 if (FieldOrArrayRef::ARRAY_REF == subref->get_type()) {
1978 // set any array indexes from undefined lowerID to reference
1979 subref->get_val()->set_lowerid_to_ref();
1980 }
1981 }
1982 }
1983
970ed795
EL
1984 Common::Assignment *ass = ref->get_refd_assignment();
1985 if (ass == NULL) { // perhaps erroneous
1986 break;
1987 }
1988
1989 Common::Assignment::asstype_t asst = ass->get_asstype();
1990 switch (asst) {
970ed795
EL
1991 case Common::Assignment::A_TEMPLATE: {
1992 Template *tpl = ass->get_Template();
1993 // tpl is the template whose name appears after the "all from"
3abe9331 1994 Common::Type *type = ass->get_Type()->get_type_refd_last();
1995 if (NULL != subrefs) {
1996 // walk through the subreferences to determine the type and value of the 'all from' target
1997 // Note: the templates referenced by the array indexes and field names
1998 // have not been checked yet
1999 for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
2000 FieldOrArrayRef* subref = subrefs->get_ref(i);
2001 if (FieldOrArrayRef::ARRAY_REF == subref->get_type()) {
2002 // check if the type can be indexed
2003 Common::Type::typetype_t tt = type->get_typetype();
2004 if (Common::Type::T_SEQOF != tt && Common::Type::T_SETOF != tt &&
2005 Common::Type::T_ARRAY != tt) {
2006 subref->error("Cannot apply an array index to type '%s'",
2007 type->get_typename().c_str());
2008 i = subrefs->get_nof_refs(); // quit from the cycle, too
2009 tpl = NULL;
2010 break;
2011 }
2012 if (can_flatten && !subref->get_val()->is_unfoldable()) {
2013 switch(tpl->get_templatetype()) {
2014 case TEMPLATE_LIST:
2015 case VALUE_LIST: {
2016 Int index = subref->get_val()->get_val_Int()->get_val();
2017 // check for index overflow
2018 if (index >= static_cast<Int>(tpl->get_nof_comps())) {
2019 subref->error("Index overflow in a template %s type `%s':"
2020 " the index is %s, but the template has only %lu elements",
2021 Common::Type::T_ARRAY == tt ? "array of" :
2022 (Common::Type::T_SEQOF == tt ? "of 'record of'" : "of 'set of'"),
2023 type->get_typename().c_str(), Int2string(index).c_str(),
2024 (unsigned long)tpl->get_nof_comps());
2025 i = subrefs->get_nof_refs(); // quit from the cycle, too
2026 tpl = NULL;
2027 break;
970ed795 2028 }
3abe9331 2029 tpl = tpl->get_temp_byIndex(index);
2030 // check if the element is initialized
2031 if (TEMPLATE_NOTUSED == tpl->get_templatetype()) {
2032 subref->error("An uninitialized list element can not be used as target of 'all from'");
2033 i = subrefs->get_nof_refs(); // quit from the cycle, too
2034 tpl = NULL;
2035 break;
2036 }
2037 break; }
2038 case INDEXED_TEMPLATE_LIST:
2039 can_flatten = false; // currently not supported
2040 break;
2041 default:
2042 subref->error("Expected a specific value of type '%s' instead of %s",
2043 type->get_typename().c_str(), tpl->get_templatetype_str());
2044 i = subrefs->get_nof_refs(); // quit from the cycle, too
2045 tpl = NULL;
2046 break;
970ed795
EL
2047 }
2048 }
3abe9331 2049 else {
2050 // one of the array indexes is a reference => cannot flatten
2051 can_flatten = false;
970ed795 2052 }
3abe9331 2053 type = type->get_ofType()->get_type_refd_last();
2054 }
2055 else { // FIELD_REF
2056 // check if the type can have fields
2057 Common::Type::typetype_t tt = type->get_typetype();
2058 if (Common::Type::T_SEQ_T != tt && Common::Type::T_SEQ_A != tt &&
2059 Common::Type::T_SET_T != tt && Common::Type::T_SET_A != tt &&
2060 Common::Type::T_CHOICE_T != tt && Common::Type::T_CHOICE_A != tt) {
2061 subref->error("Cannot apply a field name to type '%s'",
2062 type->get_typename().c_str());
2063 tpl = NULL;
2064 break;
2065 }
2066 // check if the field name is valid
2067 if (!type->has_comp_withName(*subref->get_id())) {
2068 subref->error("Type '%s' does not have a field with name '%s'",
2069 type->get_typename().c_str(), subref->get_id()->get_dispname().c_str());
2070 tpl = NULL;
2071 break;
2072 }
2073 if (can_flatten) {
2074 switch(tpl->get_templatetype()) {
2075 case NAMED_TEMPLATE_LIST: {
2076 // check if there is any data in the template for this field
2077 // (no data means it's uninitialized)
2078 if (!tpl->u.named_templates->has_nt_withName(*subref->get_id())) {
2079 subref->error("An uninitialized field can not be used as target of 'all from'");
2080 i = subrefs->get_nof_refs(); // quit from the cycle, too
2081 tpl = NULL;
2082 break;
2083 }
2084 tpl = tpl->u.named_templates->get_nt_byName(*subref->get_id())->get_template();
2085 // check if the field is initialized and present (not omitted)
2086 if (OMIT_VALUE == tpl->get_templatetype() || TEMPLATE_NOTUSED == tpl->get_templatetype()) {
2087 subref->error("An %s field can not be used as target of 'all from'",
2088 OMIT_VALUE == tpl->get_templatetype() ? "omitted" : "uninitialized");
2089 i = subrefs->get_nof_refs(); // quit from the cycle, too
2090 tpl = NULL;
2091 break;
2092 }
2093 break; }
2094 default:
2095 subref->error("Expected a specific value of type '%s' instead of %s",
2096 type->get_typename().c_str(), tpl->get_templatetype_str());
2097 i = subrefs->get_nof_refs(); // quit from the cycle, too
2098 tpl = NULL;
2099 break;
2100 }
2101 }
2102 type = type->get_comp_byName(*subref->get_id())->get_type()->get_type_refd_last();
970ed795
EL
2103 }
2104 }
3abe9331 2105 }
2106 if (NULL != tpl) { // tpl is set to null if an error occurs
970ed795 2107 if (can_flatten) {
3abe9331 2108 Template::templatetype_t tpltt = tpl->get_templatetype();
2109 switch (tpltt) {
2110 case INDEXED_TEMPLATE_LIST: // currently not supported
2111 case TEMPLATE_REFD: {
2112 delete new_templates;
2113 new_templates = 0;
2114 killer = false;
2115 break; }
2116
2117 case TEMPLATE_LIST:
2118 // ALL_FROM ?
2119 case VALUE_LIST: {
2120 size_t nvl = tpl->get_nof_comps();
2121 for (size_t ti = 0; ti < nvl; ++ti) {
970ed795 2122 Template *orig = tpl->get_temp_byIndex(ti);
3abe9331 2123 switch (orig->templatetype) {
2124 case SPECIFIC_VALUE: {
2125 Value *val = orig->get_specific_value();
2126 if (val->get_valuetype() == Value::V_REFD) {
2127 if (dynamic_cast<Ttcn::Ref_pard*>(val->get_reference())) {
2128 // Cannot flatten at compile time if one of the values or templates has parameters.
2129 can_flatten = false;
2130 }
2131 }
2132 break; }
2133 case ANY_OR_OMIT:
2134 if (from_permutation) {
2135 break; // AnyElementOrNone allowed in "all from" now
2136 }
2137 // no break
2138 case PERMUTATION_MATCH:
2139 t->error("'all from' can not refer to permutation or AnyElementsOrNone");
2140 t->set_templatetype(TEMPLATE_ERROR);
2141 default:
2142 break;
2143 }
2144 }
2145 if (can_flatten) {
2146 for (size_t ti = 0; ti < nvl; ++ti) {
2147 Template *orig = tpl->get_temp_byIndex(ti);
2148 Template *copy = orig->clone();
2149 copy->set_my_scope(orig->get_my_scope());
2150 new_templates->add_t(copy);
2151 }
2152 }
2153 else {
2154 // Cannot flatten at compile time
2155 delete new_templates;
2156 new_templates = 0;
2157 killer = false;
2158 }
2159 break; }
970ed795 2160
3abe9331 2161 case NAMED_TEMPLATE_LIST: {
2162 size_t nvl = tpl->get_nof_comps();
2163 for (size_t ti = 0; ti < nvl; ++ti) {
2164 NamedTemplate *orig = tpl->get_namedtemp_byIndex(ti);
2165 switch (orig->get_template()->get_templatetype()) {
2166 case ANY_OR_OMIT:
2167 break;
2168 case PERMUTATION_MATCH:
2169 t->error("'all from' can not refer to permutation or AnyElementsOrNone");
2170 t->set_templatetype(TEMPLATE_ERROR);
2171 default:
2172 break;
2173 }
2174 }
2175 delete new_templates;
2176 new_templates = 0;
2177 killer = false;
2178 break; }
2179
2180 case ANY_VALUE:
2181 case ANY_OR_OMIT:
2182 tpl->error("Matching mechanism can not be used as target of 'all from'");
2183 break;
2184 default:
2185 tpl->error("A template of type '%s' can not be used as target of 'all from'",
2186 type->get_typename().c_str());
2187 break;
970ed795
EL
2188 }
2189 }
3abe9331 2190 else { // cannot flatten
2191 switch (type->get_typetype()) {
2192 case Common::Type::T_SEQOF: case Common::Type::T_SETOF:
2193 case Common::Type::T_ARRAY:
2194 delete new_templates;
2195 new_templates = 0;
2196 killer = false;
2197 break;
2198 default:
2199 type->error("A template of type `%s' can not be used as target of 'all from'",
2200 type->get_typename().c_str());
2201 break;
2202 } // switch(typetype)
2203 }
970ed795
EL
2204 }
2205
2206 if (killer) delete t;
2207 break; }
2208
2209
2210 case Common::Assignment::A_CONST: { // all from a constant definition
2211 Common::Value *val = ass->get_Value();
3abe9331 2212 Common::Type *type = ass->get_Type()->get_type_refd_last();
2213 if (NULL != subrefs) {
2214 // walk through the subreferences to determine the type and value of the 'all from' target
2215 for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
2216 FieldOrArrayRef* subref = subrefs->get_ref(i);
2217 if (FieldOrArrayRef::ARRAY_REF == subref->get_type()) {
2218 // check if the type can be indexed
2219 Common::Type::typetype_t tt = type->get_typetype();
2220 if (Common::Type::T_SEQOF != tt && Common::Type::T_SETOF != tt &&
2221 Common::Type::T_ARRAY != tt) {
2222 subref->error("Cannot apply an array index to type '%s'",
2223 type->get_typename().c_str());
2224 val = NULL;
2225 break;
2226 }
2227 if (can_flatten && !subref->get_val()->is_unfoldable()) {
2228 Int index = subref->get_val()->get_val_Int()->get_val();
2229 // check for index overflow
2230 if (index >= static_cast<Int>(val->get_nof_comps())) {
2231 subref->error("Index overflow in a value %s type `%s':"
2232 " the index is %s, but the template has only %lu elements",
2233 Common::Type::T_ARRAY == tt ? "array of" :
2234 (Common::Type::T_SEQOF == tt ? "of 'record of'" : "of 'set of'"),
2235 type->get_typename().c_str(), Int2string(index).c_str(),
2236 (unsigned long)val->get_nof_comps());
2237 val = NULL;
2238 break;
2239 }
2240 val = val->get_comp_byIndex(index);
2241 // check if the element is initialized
2242 if (Common::Value::V_NOTUSED == val->get_valuetype()) {
2243 subref->error("An unbound list element can not be used as target of 'all from'");
2244 val = NULL;
2245 break;
2246 }
2247 }
2248 else {
2249 // one of the array indexes is a reference => cannot flatten
2250 can_flatten = false;
2251 }
2252 type = type->get_ofType()->get_type_refd_last();
2253 }
2254 else { // FIELD_REF
2255 // check if the type can have fields
2256 Common::Type::typetype_t tt = type->get_typetype();
2257 if (Common::Type::T_SEQ_T != tt && Common::Type::T_SEQ_A != tt &&
2258 Common::Type::T_SET_T != tt && Common::Type::T_SET_A != tt &&
2259 Common::Type::T_CHOICE_T != tt && Common::Type::T_CHOICE_A != tt) {
2260 subref->error("Cannot apply a field name to type '%s'",
2261 type->get_typename().c_str());
2262 val = NULL;
2263 break;
2264 }
2265 // check if the field name is valid
2266 if (!type->has_comp_withName(*subref->get_id())) {
2267 subref->error("Type '%s' does not have a field with name '%s'",
2268 type->get_typename().c_str(), subref->get_id()->get_dispname().c_str());
2269 val = NULL;
2270 break;
2271 }
2272 type = type->get_comp_byName(*subref->get_id())->get_type()->get_type_refd_last();
2273 if (can_flatten) {
2274 // check if the value has any data for this field (no data = unbound)
2275 if (!val->has_comp_withName(*subref->get_id())) {
2276 subref->error("An unbound field can not be used as target of 'all from'");
2277 val = NULL;
2278 break;
2279 }
2280 val = val->get_comp_value_byName(*subref->get_id());
2281 // check if the field is bound and present (not omitted)
2282 if (Common::Value::V_OMIT == val->get_valuetype() ||
2283 Common::Value::V_NOTUSED == val->get_valuetype()) {
2284 subref->error("An %s field can not be used as target of 'all from'",
2285 Common::Value::V_OMIT == val->get_valuetype() ? "omitted" : "unbound");
2286 val = NULL;
2287 break;
2288 }
2289 }
a38c6d4c 2290 }
2291 }
3abe9331 2292 }
2293 if (NULL != val) { // val is set to null if an error occurs
2294 switch (type->get_typetype()) {
2295 case Common::Type::T_SEQOF: case Common::Type::T_SETOF:
2296 case Common::Type::T_ARRAY: {
2297 if (can_flatten) {
2298 const size_t ncomp = val->get_nof_comps();
2299 for (size_t i = 0; i < ncomp; ++i) {
2300 Value *v = val->get_comp_byIndex(i);
2301 Template *newt = new Template(v->clone());
2302 new_templates->add_t(newt);
2303 }
2304 }
2305 else {
2306 delete new_templates;
2307 new_templates = 0;
2308 killer = false;
2309 }
2310 break; }
970ed795 2311
3abe9331 2312 default:
2313 type->error("A constant of type `%s' can not be used as target of 'all from'",
2314 type->get_typename().c_str());
2315 break;
2316 } // switch(typetype)
2317 }
970ed795
EL
2318 if (killer) delete t;
2319 break; }
2320
3abe9331 2321 case Common::Assignment::A_MODULEPAR_TEMP:
2322 case Common::Assignment::A_VAR_TEMPLATE:
2323 case Common::Assignment::A_FUNCTION_RTEMP:
2324 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
970ed795
EL
2325 case Common::Assignment::A_PAR_TEMPL_IN:
2326 case Common::Assignment::A_PAR_TEMPL_INOUT:
3abe9331 2327 case Common::Assignment::A_PAR_TEMPL_OUT:
970ed795
EL
2328//TODO: flatten if the actual par is const template
2329 case Common::Assignment::A_MODULEPAR: // all from a module parameter
2330 case Common::Assignment::A_VAR: // all from a variable
2331 case Common::Assignment::A_PAR_VAL_IN:
3abe9331 2332 case Common::Assignment::A_PAR_VAL_INOUT:
2333 case Common::Assignment::A_PAR_VAL_OUT:
a38c6d4c 2334 case Common::Assignment::A_FUNCTION_RVAL:
2335 case Common::Assignment::A_EXT_FUNCTION_RVAL: {
3abe9331 2336 Common::Type *type = ass->get_Type()->get_type_refd_last();
2337 if (NULL != subrefs) {
2338 // walk through the subreferences to determine the type of the 'all from' target
2339 for (size_t i = 0; i < subrefs->get_nof_refs(); ++i) {
2340 FieldOrArrayRef* subref = subrefs->get_ref(i);
2341 if (FieldOrArrayRef::ARRAY_REF == subref->get_type()) {
2342 // check if the type can be indexed
2343 Common::Type::typetype_t tt = type->get_typetype();
2344 if (Common::Type::T_SEQOF != tt && Common::Type::T_SETOF != tt &&
2345 Common::Type::T_ARRAY != tt) {
2346 subref->error("Cannot apply an array index to type '%s'",
2347 type->get_typename().c_str());
2348 type = NULL;
2349 break;
2350 }
2351 type = type->get_ofType()->get_type_refd_last();
2352 }
2353 else { // FIELD_REF
2354 // check if the type can have fields
2355 Common::Type::typetype_t tt = type->get_typetype();
2356 if (Common::Type::T_SEQ_T != tt && Common::Type::T_SEQ_A != tt &&
2357 Common::Type::T_SET_T != tt && Common::Type::T_SET_A != tt &&
2358 Common::Type::T_CHOICE_T != tt && Common::Type::T_CHOICE_A != tt) {
2359 subref->error("Cannot apply a field name to type '%s'",
2360 type->get_typename().c_str());
2361 type = NULL;
2362 break;
2363 }
2364 // check if the field name is valid
2365 if (!type->has_comp_withName(*subref->get_id())) {
2366 subref->error("Type '%s' does not have a field with name '%s'",
2367 type->get_typename().c_str(), subref->get_id()->get_dispname().c_str());
2368 type = NULL;
2369 break;
2370 }
2371 type = type->get_comp_byName(*subref->get_id())->get_type()->get_type_refd_last();
2372 }
2373 }
2374 }
2375 if (NULL != type) {
2376 switch (type->get_typetype()) {
2377 case Common::Type::T_SEQOF: case Common::Type::T_SETOF:
2378 case Common::Type::T_ARRAY:
2379 delete new_templates; // cannot flatten at compile time
2380 new_templates = 0;
2381 break;
2382 default: {
2383 // not an array type => error
2384 const char* ass_name = ass->get_assname();
2385 string descr;
2386 switch(asst) {
2387 case Common::Assignment::A_MODULEPAR_TEMP:
2388 case Common::Assignment::A_VAR_TEMPLATE:
2389 case Common::Assignment::A_MODULEPAR:
2390 case Common::Assignment::A_VAR:
2391 case Common::Assignment::A_PAR_TEMPL_IN:
2392 case Common::Assignment::A_PAR_VAL_IN:
2393 descr = "A ";
2394 descr += ass_name;
2395 break;
2396 case Common::Assignment::A_PAR_TEMPL_INOUT:
2397 case Common::Assignment::A_PAR_TEMPL_OUT:
2398 case Common::Assignment::A_PAR_VAL_INOUT:
2399 case Common::Assignment::A_PAR_VAL_OUT:
2400 descr = "An ";
2401 descr += ass_name;
2402 break;
2403 // the assignment name string for functions is no good here
2404 case Common::Assignment::A_FUNCTION_RTEMP:
2405 descr = "A function returning a template";
2406 break;
2407 case Common::Assignment::A_FUNCTION_RVAL:
2408 descr = "A function returning a value";
2409 break;
2410 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
2411 descr = "An external function returning a template";
2412 break;
2413 case Common::Assignment::A_EXT_FUNCTION_RVAL:
2414 descr = "An external function returning a value";
2415 break;
2416 default:
2417 break;
2418 }
2419 type->error("%s of type `%s' can not be used as target of 'all from'",
2420 descr.c_str(), type->get_typename().c_str());
2421 break; }
2422 }
2423 } // switch(typetype)
970ed795
EL
2424 break; }
2425
2426 default:
2427 FATAL_ERROR("harbinger asst %d", asst);
2428 break;
2429 }
2430 break; }
2431
2432 case ALL_FROM:
2433 FATAL_ERROR("unexpected all from inside all from");
2434 break;
2435 default:
2436 FATAL_ERROR("tt %d", t->u.all_from->templatetype);
2437 }
2438
2439 return new_templates;
2440 }
2441
2442 bool Template::flatten(bool from_permutation)
2443 {
2444 switch (templatetype) {
2445 case TEMPLATE_LIST:
2446 case VALUE_LIST:
2447 case COMPLEMENTED_LIST:
2448 case SUPERSET_MATCH:
2449 case SUBSET_MATCH:
2450 case PERMUTATION_MATCH: {
2451 size_t num_t = u.templates->get_nof_ts(); // one of these is the "all from"
2452 Templates *new_templates = new Templates;
2453 for (size_t i = 0; i < num_t; ++i) {
2454 Template *& t = u.templates->get_t_byIndex(i);
2455 // the element in the (,,,)
2456 switch (t->templatetype) {
2457 case VALUE_LIST_ALL_FROM: {
2458 // the all from from something like subset(1, (all from...), 99)
2459 // value list: one out of many possible values^^^^^^^^^^^^^
2460 Location tloc(*t); // save the location info
2461 string tname(t->get_fullname());
2462 Templates *ha = harbinger(t, from_permutation, true);
2463 if (ha) {
2464 // Don't touch t from now on, it might have been deleted!
2465 Template *qq = new Template(VALUE_LIST, ha);
2466 qq->set_location(tloc);
2467 qq->set_fullname(tname + ".all_from");
2468 new_templates->add_t(qq);
2469 }
2470 else {
2471 new_templates->add_t(t); // transfer it unchanged
2472 flattened = false;
2473 }
2474 break; }
2475
2476 case ALL_FROM: { // subset(1, all from ..., 99)
2477 // some number of elements--^^^^^^^^^^^^
2478 if (t->checked) FATAL_ERROR("too late");
2479 Templates *af = harbinger(t, from_permutation, true);
2480 if (af) {
2481 for (size_t a = 0, num = af->get_nof_ts(); a < num; ++a) {
2482 Template *& t2 = af->get_t_byIndex(a);
2483 new_templates->add_t(t2);
2484 t2 = 0; // take it away from its current owner
2485 }
2486 delete af;
2487 }
2488 else {
2489 new_templates->add_t(t); // transfer it unchanged
2490 flattened = false;
2491 }
2492 break; } // case ALL_FROM
2493
2494 case PERMUTATION_MATCH: {
2495 // permut inside a value list: { 1, permut(), 2 }
2496 flattened &= t->flatten(true);
2497 new_templates->add_t(t);
2498 break; }
2499 case TEMPLATE_LIST:
2500 // case VALUE_LIST:
2501 // case COMPLEMENTED_LIST:
2502 // case SUPERSET_MATCH:
2503 // case SUBSET_MATCH:
2504 {
2505 flattened &=t->flatten(false);
2506 new_templates->add_t(t);
2507 break; }
2508 default:
2509 new_templates->add_t(t);
2510 }
2511
2512 t = 0; // take it away from the original
2513 }
2514 delete u.templates;
2515 u.templates = new_templates;
2516//printf("!!! flattened from %lu to %lu at line %d\n",
2517// (unsigned long)num_t, (unsigned long)new_templates->get_nof_ts(),
2518// get_first_line());
2519
2520 break; }
2521
2522 case VALUE_LIST_ALL_FROM: {
2523 Templates *new_templates = harbinger(this, from_permutation, false);
2524 if (new_templates) {
2525 delete u.all_from;
2526 // now we can change the type
2527 templatetype = VALUE_LIST;
2528 u.templates = new_templates;
2529 }
2530 break; }
2531
2532 case TEMPLATE_ERROR: case TEMPLATE_NOTUSED:
2533 case OMIT_VALUE: case ANY_VALUE: case ANY_OR_OMIT:
2534 case SPECIFIC_VALUE:
2535 case TEMPLATE_REFD: case TEMPLATE_INVOKE:
2536 case NAMED_TEMPLATE_LIST: case INDEXED_TEMPLATE_LIST:
2537 case VALUE_RANGE:
2538 case ALL_FROM:
2539 case BSTR_PATTERN: case HSTR_PATTERN: case OSTR_PATTERN:
2540 case CSTR_PATTERN: case USTR_PATTERN:
2541 break; // NOP
2542 }
2543
2544 set_fullname(get_fullname()); // recompute fullname (esp. for components)
2545 set_my_scope(get_my_scope());
2546
2547 return flattened;
2548 }
2549
2550 const char* Template::get_restriction_name(template_restriction_t tr)
2551 {
2552 switch (tr) {
2553 case TR_NONE:
2554 break;
2555 case TR_OMIT:
2556 return "omit";
2557 case TR_VALUE:
2558 return "value";
2559 case TR_PRESENT:
2560 return "present";
2561 default:
2562 FATAL_ERROR("Template::get_restriction_name()");
2563 }
2564 return "";
2565 }
2566
2567 template_restriction_t Template::get_sub_restriction(
2568 template_restriction_t tr, Ref_base* ref)
2569 {
2570 if (!ref) FATAL_ERROR("Template::get_sub_restriction()");
2571 if (!ref->get_subrefs()) return tr;
2572 bool is_optional = true; // the referenced field is on an optional path
2573 Common::Assignment* ass = ref->get_refd_assignment();
2574 if (ass) {
2575 Type* t = ass->get_Type();
2576 if (t) {
2577 ReferenceChain refch(ref, "While checking template restriction");
2578 t = t->get_field_type(ref->get_subrefs(), Type::EXPECTED_TEMPLATE,
2579 &refch, true);
2580 if (t) is_optional = false;
2581 }
2582 }
2583 switch (tr) {
2584 case TR_NONE:
2585 return TR_NONE;
2586 case TR_OMIT:
2587 return TR_OMIT;
2588 case TR_VALUE:
2589 return is_optional ? TR_OMIT : TR_VALUE;
2590 case TR_PRESENT:
2591 return is_optional ? TR_NONE : TR_PRESENT;
2592 default:
2593 FATAL_ERROR("Template::get_sub_restriction()");
2594 }
2595 return tr;
2596 }
2597
2598 bool Template::is_less_restrictive(template_restriction_t needed_tr,
2599 template_restriction_t refd_tr)
2600 {
2601 switch (needed_tr) {
2602 case TR_NONE:
2603 return false;
2604 case TR_VALUE:
2605 return refd_tr!=TR_VALUE;
2606 case TR_OMIT:
2607 return refd_tr!=TR_VALUE && refd_tr!=TR_OMIT;
2608 case TR_PRESENT:
2609 return refd_tr!=TR_VALUE && refd_tr!=TR_PRESENT;
2610 default:
2611 FATAL_ERROR("Template::is_less_restrictive()");
2612 }
2613 return true;
2614 }
2615
2616 char* Template::generate_restriction_check_code(char* str, const char* name,
2617 template_restriction_t tr)
2618 {
2619 const char* tr_name;
2620 switch (tr) {
2621 case TR_NONE:
2622 return str;
2623 case TR_OMIT:
2624 tr_name = "TR_OMIT";
2625 break;
2626 case TR_VALUE:
2627 tr_name = "TR_VALUE";
2628 break;
2629 case TR_PRESENT:
2630 tr_name = "TR_PRESENT";
2631 break;
2632 default:
2633 FATAL_ERROR("Template::generate_restriction_check_code()");
2634 }
3abe9331 2635 return mputprintf(str, "%s.check_restriction(%s%s);\n", name, tr_name,
2636 (omit_in_value_list ? ", NULL, TRUE" : ""));
970ed795
EL
2637 }
2638
2639 // embedded templates -> check needed only for case of TR_OMIT
2640 bool Template::chk_restriction_named_list(const char* definition_name,
3abe9331 2641 map<string, void>& checked_map, size_t needed_checked_cnt,
2642 const Location* usage_loc)
970ed795
EL
2643 {
2644 bool needs_runtime_check = false;
2645 if (checked_map.size()>=needed_checked_cnt) return needs_runtime_check;
2646 switch (templatetype) {
2647 case NAMED_TEMPLATE_LIST:
2648 for (size_t i = 0;i < u.named_templates->get_nof_nts(); i++) {
2649 Template* tmpl = u.named_templates->get_nt_byIndex(i)->get_template();
2650 const string& name =
2651 u.named_templates->get_nt_byIndex(i)->get_name().get_name();
2652 if (!checked_map.has_key(name)) {
3abe9331 2653 bool nrc = tmpl->chk_restriction(definition_name, TR_OMIT, usage_loc);
970ed795
EL
2654 needs_runtime_check = needs_runtime_check || nrc;
2655 checked_map.add(name, 0);
2656 }
2657 }
2658 if (base_template) {
2659 bool nrc = base_template->chk_restriction_named_list(definition_name,
3abe9331 2660 checked_map, needed_checked_cnt, usage_loc);
970ed795
EL
2661 needs_runtime_check = needs_runtime_check || nrc;
2662 }
2663 break;
2664 case ANY_VALUE:
2665 case ANY_OR_OMIT:
2666 error("Restriction on %s does not allow usage of %s",
2667 definition_name, get_templatetype_str());
2668 break;
2669 default:
2670 // others will be converted to specific value
2671 break;
2672 }
2673 return needs_runtime_check;
2674 }
2675
2676 bool Template::chk_restriction_refd(const char* definition_name,
3abe9331 2677 template_restriction_t template_restriction, const Location* usage_loc)
970ed795
EL
2678 {
2679 bool needs_runtime_check = false;
2680 Common::Assignment* ass = u.ref.ref->get_refd_assignment();
2681 if (!ass) FATAL_ERROR("Template::chk_restriction_refd()");
2682 // get the restriction on the referenced template
2683 template_restriction_t refd_tr = TR_NONE;
2684 bool is_var_template = false;
2685 switch (ass->get_asstype()) {
2686 case Common::Assignment::A_TEMPLATE: {
2687 Template* t_last = get_template_refd_last();
2688 if (t_last!=this) {
2689 bool nrc = t_last->chk_restriction(definition_name,
3abe9331 2690 template_restriction, usage_loc);
970ed795
EL
2691 needs_runtime_check = needs_runtime_check || nrc;
2692 }
2693 break; }
2694 case Common::Assignment::A_MODULEPAR_TEMP:
2695 is_var_template = true;
2696 refd_tr = TR_NONE; // can't place restriction on this thing
2697 break;
2698 case Common::Assignment::A_VAR_TEMPLATE: {
2699 Def_Var_Template* dvt = dynamic_cast<Def_Var_Template*>(ass);
2700 if (!dvt) FATAL_ERROR("Template::chk_restriction_refd()");
2701 is_var_template = true;
2702 refd_tr = dvt->get_template_restriction();
2703 break; }
2704 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
2705 // we do not trust external functions because there is no generated
2706 // restriction check on their return value
2707 if (template_restriction!=TR_NONE) needs_runtime_check = true;
2708 // no break
2709 case Common::Assignment::A_FUNCTION_RTEMP: {
2710 Def_Function_Base* dfb = dynamic_cast<Def_Function_Base*>(ass);
2711 if (!dfb) FATAL_ERROR("Template::chk_restriction_refd()");
2712 is_var_template = true;
2713 refd_tr = dfb->get_template_restriction();
2714 break; }
2715 case Common::Assignment::A_PAR_TEMPL_IN:
2716 case Common::Assignment::A_PAR_TEMPL_OUT:
2717 case Common::Assignment::A_PAR_TEMPL_INOUT: {
2718 FormalPar* fp = dynamic_cast<FormalPar*>(ass);
2719 if (!fp) FATAL_ERROR("Template::chk_restriction_refd()");
2720 is_var_template = true;
2721 refd_tr = fp->get_template_restriction();
2722 break; }
2723 default:
2724 break;
2725 }
2726 if (is_var_template) {
2727 // check the restriction
2728 refd_tr = get_sub_restriction(refd_tr, u.ref.ref);
2729 // if restriction not satisfied issue warning
2730 if (is_less_restrictive(template_restriction, refd_tr)) {
2731 needs_runtime_check = true;
2732 warning("Inadequate restriction on the referenced %s `%s', this may "
2733 "cause a dynamic test case error at runtime", ass->get_assname(),
2734 u.ref.ref->get_dispname().c_str());
2735 ass->note("Referenced %s is here", ass->get_assname());
2736 }
2737 }
2738 return needs_runtime_check;
2739 }
2740
2741 bool Template::chk_restriction(const char* definition_name,
3abe9331 2742 template_restriction_t template_restriction,
2743 const Location* usage_loc)
970ed795
EL
2744 {
2745 bool needs_runtime_check = false;
3abe9331 2746 bool erroneous = false;
970ed795
EL
2747 switch (template_restriction) {
2748 case TR_NONE:
2749 break;
2750 case TR_OMIT:
2751 case TR_VALUE:
3abe9331 2752 if (length_restriction) {
2753 usage_loc->error("Restriction on %s does not allow usage of length "
2754 "restriction", definition_name);
2755 erroneous = true;
2756 }
2757 if (is_ifpresent) {
2758 usage_loc->error("Restriction on %s does not allow usage of `ifpresent'",
2759 definition_name);
2760 erroneous = true;
2761 }
970ed795
EL
2762 switch(templatetype) {
2763 case TEMPLATE_ERROR:
2764 break;
2765 case TEMPLATE_NOTUSED:
2766 if (base_template) {
2767 bool nrc = base_template->chk_restriction(definition_name,
3abe9331 2768 template_restriction, usage_loc);
970ed795
EL
2769 needs_runtime_check = needs_runtime_check || nrc;
2770 }
2771 else needs_runtime_check = true;
2772 break;
2773 case SPECIFIC_VALUE:
2774 case TEMPLATE_INVOKE:
2775 break;
2776 case TEMPLATE_REFD: {
3abe9331 2777 bool nrc = chk_restriction_refd(definition_name, template_restriction,
2778 usage_loc);
970ed795
EL
2779 needs_runtime_check = needs_runtime_check || nrc;
2780 } break;
2781 case TEMPLATE_LIST:
2782 for (size_t i = 0; i < u.templates->get_nof_ts(); i++) {
2783 bool nrc = u.templates->get_t_byIndex(i)->
3abe9331 2784 chk_restriction(definition_name, TR_OMIT, usage_loc);
970ed795
EL
2785 needs_runtime_check = needs_runtime_check || nrc;
2786 }
2787 break;
2788 case NAMED_TEMPLATE_LIST: {
2789 map<string, void> checked_map;
2790 size_t needed_checked_cnt = 0;
2791 if (base_template && my_governor) {
2792 switch (my_governor->get_typetype()) {
2793 case Type::T_SEQ_A:
2794 case Type::T_SEQ_T:
2795 case Type::T_SET_A:
2796 case Type::T_SET_T:
2797 case Type::T_SIGNATURE:
2798 needed_checked_cnt = my_governor->get_nof_comps();
2799 break;
2800 default:
2801 break;
2802 }
2803 }
2804 for (size_t i = 0;i < u.named_templates->get_nof_nts(); i++) {
2805 bool nrc = u.named_templates->get_nt_byIndex(i)->get_template()->
3abe9331 2806 chk_restriction(definition_name, TR_OMIT, usage_loc);
970ed795
EL
2807 needs_runtime_check = needs_runtime_check || nrc;
2808 if (needed_checked_cnt)
2809 checked_map.add(
2810 u.named_templates->get_nt_byIndex(i)->get_name().get_name(), 0);
2811 }
2812 if (needed_checked_cnt) {
2813 bool nrc = base_template->chk_restriction_named_list(definition_name,
3abe9331 2814 checked_map, needed_checked_cnt, usage_loc);
970ed795
EL
2815 needs_runtime_check = needs_runtime_check || nrc;
2816 checked_map.clear();
2817 }
2818 } break;
2819 case INDEXED_TEMPLATE_LIST:
2820 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++) {
2821 bool nrc = u.indexed_templates->get_it_byIndex(i)->get_template()->
3abe9331 2822 chk_restriction(definition_name, TR_OMIT, usage_loc);
970ed795
EL
2823 needs_runtime_check = needs_runtime_check || nrc;
2824 }
2825 needs_runtime_check = true; // only basic check, needs runtime check
2826 break;
2827 case OMIT_VALUE:
2828 if (template_restriction==TR_OMIT) break;
2829 // Else restriction is TR_VALUE, but template type is OMIT:
2830 // fall through to error.
2831 default:
3abe9331 2832 usage_loc->error("Restriction on %s does not allow usage of %s",
2833 definition_name, get_templatetype_str());
2834 erroneous = true;
970ed795
EL
2835 break;
2836 }
2837 break;
2838 case TR_PRESENT:
3abe9331 2839 if (is_ifpresent) {
2840 usage_loc->error("Restriction on %s does not allow usage of `ifpresent'",
2841 definition_name);
2842 erroneous = true;
2843 }
970ed795
EL
2844 switch(templatetype) {
2845 case TEMPLATE_REFD: {
3abe9331 2846 bool nrc = chk_restriction_refd(definition_name, template_restriction,
2847 usage_loc);
970ed795
EL
2848 needs_runtime_check = needs_runtime_check || nrc;
2849 } break;
2850 case VALUE_LIST:
2851 for (size_t i = 0; i < u.templates->get_nof_ts(); i++) {
2852 bool nrc = u.templates->get_t_byIndex(i)->
3abe9331 2853 chk_restriction(definition_name, template_restriction, usage_loc);
970ed795
EL
2854 needs_runtime_check = needs_runtime_check || nrc;
2855 }
2856 break;
3abe9331 2857 case COMPLEMENTED_LIST:
970ed795
EL
2858 // some basic check, always needs runtime check
2859 needs_runtime_check = true;
3abe9331 2860 if (omit_in_value_list) {
2861 bool has_any_or_omit = false;
2862 for (size_t i = 0; i < u.templates->get_nof_ts(); i++) {
2863 templatetype_t item_templatetype =
2864 u.templates->get_t_byIndex(i)->templatetype;
2865 if (item_templatetype==OMIT_VALUE || item_templatetype==ANY_OR_OMIT) {
2866 has_any_or_omit = true;
2867 break;
2868 }
2869 }
2870 if (!has_any_or_omit) {
2871 usage_loc->error("Restriction on %s does not allow usage of %s without "
2872 "omit or AnyValueOrNone in the list", definition_name,
2873 get_templatetype_str());
2874 erroneous = true;
970ed795
EL
2875 }
2876 }
3abe9331 2877 break;
970ed795
EL
2878 case OMIT_VALUE:
2879 case ANY_OR_OMIT:
3abe9331 2880 usage_loc->error("Restriction on %s does not allow usage of %s",
2881 definition_name, get_templatetype_str());
2882 erroneous = true;
970ed795
EL
2883 break;
2884 default:
2885 break; // all others are ok
2886 }
2887 break;
2888 default:
2889 FATAL_ERROR("Template::chk_restriction()");
2890 }
3abe9331 2891 if (erroneous && usage_loc != this) {
2892 // display the template's location, too
2893 note("Referenced template is here");
2894 }
970ed795
EL
2895 return needs_runtime_check;
2896 }
2897
2898 void Template::generate_code_expr(expression_struct *expr,
2899 template_restriction_t template_restriction)
2900 {
2901 // Only templates without extra matching attributes can be directly
2902 // represented in a C++ expression.
2903 if (!length_restriction && !is_ifpresent
2904 && template_restriction == TR_NONE) {
2905 // The single expression must be tried first because this rule might
2906 // cover some referenced templates.
2907 if (has_single_expr()) {
2908 expr->expr = mputstr(expr->expr, get_single_expr(true).c_str());
2909 return;
2910 }
2911 switch (templatetype) {
2912 case SPECIFIC_VALUE:
2913 // A simple specific value: use explicit cast.
2914 expr->expr = mputprintf(expr->expr, "%s(",
2915 my_governor->get_genname_template(my_scope).c_str());
2916 u.specific_value->generate_code_expr(expr);
2917 expr->expr = mputc(expr->expr, ')');
2918 return;
2919 case TEMPLATE_REFD:
2920 // A simple unfoldable referenced template.
2921 if (!get_needs_conversion()) {
2922 u.ref.ref->generate_code(expr);
2923 } else {
2924 Type *my_gov = get_expr_governor(Type::EXPECTED_TEMPLATE)
2925 ->get_type_refd_last();
2926 Type *refd_gov = u.ref.ref->get_refd_assignment()->get_Type()
2927 ->get_field_type(u.ref.ref->get_subrefs(),
2928 Type::EXPECTED_TEMPLATE)->get_type_refd_last();
2929 if (!my_gov || !refd_gov || my_gov == refd_gov)
2930 FATAL_ERROR("Template::generate_code_expr()");
2931 expression_struct expr_tmp;
2932 Code::init_expr(&expr_tmp);
2933 const string& tmp_id1 = get_temporary_id();
2934 const char *tmp_id_str1 = tmp_id1.c_str();
2935 const string& tmp_id2 = get_temporary_id();
2936 const char *tmp_id_str2 = tmp_id2.c_str();
2937 expr->preamble = mputprintf(expr->preamble,
2938 "%s %s;\n", refd_gov->get_genname_template(my_scope).c_str(),
2939 tmp_id_str1);
2940 expr_tmp.expr = mputprintf(expr_tmp.expr, "%s = ", tmp_id_str1);
2941 u.ref.ref->generate_code(&expr_tmp);
2942 expr->preamble = Code::merge_free_expr(expr->preamble, &expr_tmp);
2943 expr->preamble = mputprintf(expr->preamble,
2944 "%s %s;\n"
2945 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
2946 "and `%s' are not compatible at run-time\");\n",
2947 my_gov->get_genname_template(my_scope).c_str(), tmp_id_str2,
2948 TypeConv::get_conv_func(refd_gov, my_gov, get_my_scope()
2949 ->get_scope_mod()).c_str(), tmp_id_str2, tmp_id_str1, my_gov
2950 ->get_typename().c_str(), refd_gov->get_typename().c_str());
2951 expr->expr = mputprintf(expr->expr, "%s", tmp_id_str2);
2952 }
2953 return;
2954 case TEMPLATE_INVOKE:
2955 generate_code_expr_invoke(expr);
2956 return;
2957 default:
2958 break;
2959 }
2960 }
2961 // if none of the above methods are applicable use the most generic and
2962 // least efficient solution
2963 // create a temporary object, initialize it and use it in the expression
2964 const string& tmp_id = get_temporary_id();
2965 const char *tmp_id_str = tmp_id.c_str();
2966
2967 expr->preamble = mputprintf(expr->preamble, "%s %s;\n",
2968 my_governor->get_genname_template(my_scope).c_str(), tmp_id_str);
2969 set_genname_recursive(tmp_id);
2970 expr->preamble = generate_code_init(expr->preamble, tmp_id_str);
2971 if (template_restriction != TR_NONE)
2972 expr->preamble = Template::generate_restriction_check_code(expr->preamble,
2973 tmp_id_str, template_restriction);
2974 expr->expr = mputstr(expr->expr, tmp_id_str);
2975 }
2976
2977 char *Template::generate_code_init(char *str, const char *name)
2978 {
2979 if (get_code_generated()) return str;
2980 set_code_generated();
2981 if (err_descr) {
2982 str = err_descr->generate_code_init_str(str, string(name)+"_err_descr");
2983 }
2984 switch (templatetype) {
2985 case OMIT_VALUE:
2986 case ANY_VALUE:
2987 case ANY_OR_OMIT:
2988 case BSTR_PATTERN:
2989 case HSTR_PATTERN:
2990 case OSTR_PATTERN:
2991 case CSTR_PATTERN:
2992 case USTR_PATTERN:
2993 str = mputprintf(str, "%s = %s;\n", name, get_single_expr(false).c_str());
2994 break;
2995 case SPECIFIC_VALUE:
2996 if (get_code_section() == CS_POST_INIT)
2997 str = u.specific_value->rearrange_init_code(str);
2998 str = u.specific_value->generate_code_init(str, name);
2999 break;
3000 case TEMPLATE_REFD:
3001 str = generate_code_init_refd(str, name);
3002 break;
3003 case TEMPLATE_INVOKE:
3004 if (get_code_section() == CS_POST_INIT)
51fa56b9 3005 str = rearrange_init_code_invoke(str, my_scope->get_scope_mod_gen());
970ed795
EL
3006 str = generate_code_init_invoke(str, name);
3007 break;
3008 case TEMPLATE_LIST:
3009 case INDEXED_TEMPLATE_LIST:
3010 str = generate_code_init_seof(str, name);
3011 break;
3012 case NAMED_TEMPLATE_LIST:
3013 str = generate_code_init_se(str, name);
3014 break;
3015 case VALUE_LIST_ALL_FROM:
3016 str = generate_code_init_all_from_list(str, name);
3017 break;
3018 case ALL_FROM:
3019 str = generate_code_init_all_from(str, name);
3020 break;
3021 case VALUE_LIST:
3022 str = generate_code_init_list(str, name, false);
3023 break;
3024 case COMPLEMENTED_LIST:
3025 str = generate_code_init_list(str, name, true);
3026 break;
3027 case VALUE_RANGE:
3028 if (get_code_section() == CS_POST_INIT)
3029 str = u.value_range->rearrange_init_code(str);
3030 str = u.value_range->generate_code_init(str, name);
3031 break;
3032 case SUPERSET_MATCH:
3033 str = generate_code_init_set(str, name, true);
3034 break;
3035 case SUBSET_MATCH:
3036 str = generate_code_init_set(str, name, false);
3037 break;
3038 case PERMUTATION_MATCH:
3039 warning("Don't know how to init PERMUT");
3040 str = mputprintf(str, "/* FIXME: PERMUT goes here, name=%s*/\n", name);
3041 break;
3042 case TEMPLATE_ERROR:
3043 case TEMPLATE_NOTUSED:
3044 // "default"
3045 FATAL_ERROR("Template::generate_code_init()");
3046 }
3047 if (length_restriction) {
3048 if (get_code_section() == CS_POST_INIT)
3049 str = length_restriction->rearrange_init_code(str);
3050 str = length_restriction->generate_code_init(str, name);
3051 }
3052 if (is_ifpresent) str = mputprintf(str, "%s.set_ifpresent();\n", name);
3053 if (err_descr) {
3054 str = mputprintf(str, "%s.set_err_descr(&%s_err_descr);\n", name, name);
3055 }
3056 return str;
3057 }
3058
51fa56b9 3059 char *Template::rearrange_init_code(char *str, Common::Module* usage_mod)
970ed795
EL
3060 {
3061 switch (templatetype) {
3062 case SPECIFIC_VALUE:
3063 str = u.specific_value->rearrange_init_code(str);
3064 break;
3065 case TEMPLATE_REFD:
51fa56b9 3066 str = rearrange_init_code_refd(str, usage_mod);
970ed795
EL
3067 break;
3068 case TEMPLATE_INVOKE:
51fa56b9 3069 str = rearrange_init_code_invoke(str, usage_mod);
970ed795
EL
3070 break;
3071 case TEMPLATE_LIST:
3072 case VALUE_LIST:
3073 case COMPLEMENTED_LIST:
3074 case SUPERSET_MATCH:
3075 case SUBSET_MATCH:
3076 case PERMUTATION_MATCH:
3077 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
51fa56b9 3078 str = u.templates->get_t_byIndex(i)->rearrange_init_code(str, usage_mod);
970ed795
EL
3079 break;
3080 case NAMED_TEMPLATE_LIST:
3081 for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++)
3082 str = u.named_templates->get_nt_byIndex(i)->get_template()
51fa56b9 3083 ->rearrange_init_code(str, usage_mod);
970ed795
EL
3084 break;
3085 case INDEXED_TEMPLATE_LIST:
3086 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++)
3087 str = u.indexed_templates->get_it_byIndex(i)->get_template()
51fa56b9 3088 ->rearrange_init_code(str, usage_mod);
970ed795
EL
3089 break;
3090 case VALUE_RANGE:
3091 str = u.value_range->rearrange_init_code(str);
3092 break;
3093 default:
3094 break;
3095 }
3096 if (length_restriction) str = length_restriction->rearrange_init_code(str);
3097 return str;
3098 }
3099
3100 bool Template::use_single_expr_for_init()
3101 {
3102 Template *t_last = get_template_refd_last();
3103 // return false in case of unfoldable references
3104 if (t_last->templatetype == TEMPLATE_REFD) return false;
3105 // return false if t_last is in a different module
3106 if (t_last->my_scope->get_scope_mod_gen() != my_scope->get_scope_mod_gen())
3107 return false;
3108 // return false if t_last cannot be represented by a single expression
3109 if (!t_last->has_single_expr()) return false;
3110 // return true if t_last is a generic wildcard, string pattern, etc.
3111 if (t_last->templatetype != SPECIFIC_VALUE) return true;
3112 // examine the specific value
3113 Value *v_last = t_last->u.specific_value->get_value_refd_last();
3114 switch (v_last->get_valuetype()) {
3115 case Value::V_EXPR:
3116 // do not calculate expressions again
3117 return false;
3118 case Value::V_REFD: {
3119 // v_last is an unfoldable value reference
3120 // the scope of the definition that v_last refers to
3121 Scope *v_scope =
3122 v_last->get_reference()->get_refd_assignment()->get_my_scope();
3123 for (Scope *t_scope = my_scope; t_scope;
3124 t_scope = t_scope->get_parent_scope()) {
3125 // return true if the referred definition is in the same scope
3126 // as this or in one of the parent scopes of this
3127 if (t_scope == v_scope) return true;
3128 }
3129 // otherwise return false
3130 return false; }
3131 default:
3132 // return true only if v_last is defined in the same module as this
3133 return v_last->get_my_scope()->get_scope_mod_gen() ==
3134 my_scope->get_scope_mod_gen();
3135 }
3136 }
3137
3138 char *Template::generate_code_init_refd(char *str, const char *name)
3139 {
3140 if (use_single_expr_for_init() && has_single_expr()) {
3141 str = mputprintf(str, "%s = %s;\n", name,
3142 get_single_expr(false).c_str());
3143 } else {
3144 expression_struct expr;
3145 Code::init_expr(&expr);
3146 bool use_ref_for_codegen = true;
3147 if (get_code_section() == CS_POST_INIT) {
3148 // the referencing template is a part of a non-parameterized template
3149 Common::Assignment *ass = u.ref.ref->get_refd_assignment();
51fa56b9 3150 if (ass->get_asstype() == Common::Assignment::A_TEMPLATE) {
970ed795 3151 // the reference points to (a field of) a template
970ed795
EL
3152 if (ass->get_FormalParList()) {
3153 // the referred template is parameterized
3154 // generate the initialization sequence first for all dependent
3155 // non-parameterized templates
51fa56b9 3156 str = rearrange_init_code_refd(str, my_scope->get_scope_mod_gen());
3157 } else if (ass->get_my_scope()->get_scope_mod_gen() ==
3158 my_scope->get_scope_mod_gen()) {
970ed795
EL
3159 // the referred template is non-parameterized
3160 // use a different algorithm for code generation
3161 str = generate_rearrange_init_code_refd(str, &expr);
3162 use_ref_for_codegen = false;
3163 }
3164 }
3165 }
3166 if (use_ref_for_codegen) u.ref.ref->generate_code_const_ref(&expr);
3167 if (expr.preamble || expr.postamble) {
3168 // the expressions within reference need temporary objects
3169 str = mputstr(str, "{\n");
3170 str = mputstr(str, expr.preamble);
3171 if (use_runtime_2 && get_needs_conversion()) {
3172 const string& tmp_id = get_temporary_id();
3173 const char *tmp_id_str = tmp_id.c_str();
3174 Type *my_gov = my_governor->get_type_refd_last();
3175 Type *refd_gov = u.ref.ref->get_refd_assignment()->get_Type()
3176 ->get_type_refd_last();
3177 if (!my_gov || !refd_gov)
3178 FATAL_ERROR("Template::generate_code_init_refd()");
3179 str = mputprintf(str,
3180 "%s %s;\n"
3181 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
3182 "and `%s' are not compatible at run-time\");\n",
3183 my_gov->get_genname_template(my_scope).c_str(), tmp_id_str,
3184 TypeConv::get_conv_func(refd_gov, my_gov, get_my_scope()
3185 ->get_scope_mod()).c_str(), tmp_id_str, expr.expr, my_gov
3186 ->get_typename().c_str(), refd_gov->get_typename().c_str());
3187 str = mputprintf(str, "%s = %s;\n", name, tmp_id_str);
3188 } else {
3189 str = mputprintf(str, "%s = %s;\n", name, expr.expr);
3190 }
3191 str = mputstr(str, expr.postamble);
3192 str = mputstr(str, "}\n");
3193 } else {
3194 // the reference does not need temporary objects
3195 if (use_runtime_2 && get_needs_conversion()) {
3196 const string& tmp_id = get_temporary_id();
3197 const char *tmp_id_str = tmp_id.c_str();
3198 Type *my_gov = my_governor->get_type_refd_last();
3199 Type *refd_gov = u.ref.ref->get_refd_assignment()->get_Type()
3200 ->get_type_refd_last();
3201 if (!my_gov || !refd_gov)
3202 FATAL_ERROR("Template::generate_code_init_refd()");
3203 str = mputprintf(str,
3204 "%s %s;\n"
3205 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
3206 "and `%s' are not compatible at run-time\");\n",
3207 my_gov->get_genname_template(my_scope).c_str(), tmp_id_str,
3208 TypeConv::get_conv_func(refd_gov, my_gov, get_my_scope()
3209 ->get_scope_mod()).c_str(), tmp_id_str, expr.expr, my_gov
3210 ->get_typename().c_str(), refd_gov->get_typename().c_str());
3211 str = mputprintf(str, "%s = %s;\n", name, tmp_id_str);
3212 } else {
3213 str = mputprintf(str, "%s = %s;\n", name, expr.expr);
3214 }
3215 }
3216 Code::free_expr(&expr);
3217 }
3218 return str;
3219 }
3220
3221 char *Template::generate_code_init_invoke(char *str, const char *name)
3222 {
3223 expression_struct expr;
3224 Code::init_expr(&expr);
3225 expr.expr = mputprintf(expr.expr, "%s = ", name);
3226 generate_code_expr_invoke(&expr);
3227 return Code::merge_free_expr(str, &expr);
3228 }
3229
3230 char *Template::generate_rearrange_init_code_refd(char *str,
3231 expression_struct *expr)
3232 {
3233 /** Initially we can assume that:
3234 * - this is a referenced template and a part of a non-parameterized
3235 * template
3236 * - u.ref.ref points to (a field of) a non-parameterized template within
3237 * the same module as \a this.
3238 * - this ensures that the do-while loop will run at least twice (i.e. the
3239 * first continue statement will be reached in the first iteration) */
3240 stack<FieldOrArrayRef> refstack;
3241 Template *t = this;
3242 // first try to find the smallest dependent template
3243 for ( ; ; ) {
3244 if (t->templatetype == TEMPLATE_REFD) {
3245 Common::Assignment *ass = t->u.ref.ref->get_refd_assignment();
3246 /** Don't follow the reference if:
3247 * - the referenced definition is not a template
3248 * - the referenced template is parameterized or
3249 * - the referenced template is in different module */
3250 if (ass->get_asstype() == Common::Assignment::A_TEMPLATE &&
3251 ass->get_FormalParList() == 0 &&
3252 ass->get_my_scope()->get_scope_mod_gen() ==
3253 my_scope->get_scope_mod_gen()) {
3254 // accumulate the sub-references of the referred reference
3255 FieldOrArrayRefs *subrefs = t->u.ref.ref->get_subrefs();
3256 if (subrefs) {
3257 for (size_t i = subrefs->get_nof_refs(); i > 0; i--)
3258 refstack.push(subrefs->get_ref(i - 1));
3259 }
3260 // jump to the referred top-level template
3261 t = ass->get_Template();
3262 // start the iteration from the beginning
3263 continue;
3264 // stop otherwise: the reference cannot be followed
3265 } else break;
3266 }
3267 // stop if there are no sub-references
3268 if (refstack.empty()) break;
3269 // take the topmost sub-reference
3270 FieldOrArrayRef *subref = refstack.top();
3271 if (subref->get_type() == FieldOrArrayRef::FIELD_REF) {
3272 if (t->templatetype != NAMED_TEMPLATE_LIST) break;
3273 // the field reference can be followed
3274 t = t->u.named_templates->get_nt_byName(*subref->get_id())
3275 ->get_template();
3276 } else {
3277 // trying to follow an array reference
3278 if (t->templatetype != TEMPLATE_LIST) break;
3279 Value *array_index = subref->get_val()->get_value_refd_last();
3280 if (array_index->get_valuetype() != Value::V_INT) break;
3281 // the index is available at compilation time
3282 Int index = array_index->get_val_Int()->get_val();
3283 // index transformation in case of arrays
3284 if (t->my_governor->get_typetype() == Type::T_ARRAY)
3285 index -= t->my_governor->get_dimension()->get_offset();
3286 t = t->get_listitem_byIndex(index);
3287 }
3288 // the topmost sub-reference was processed
3289 // it can be erased from the stack
3290 refstack.pop();
3291 }
3292 // the smallest dependent template is now in t
3293 // generate the initializer sequence for t
3294 str = t->generate_code_init(str, t->get_lhs_name().c_str());
3295 // the equivalent C++ code of the referenced template is composed of the
3296 // genname of t and the remained sub-references in refstack
3297 expr->expr = mputstr(expr->expr, t->get_genname_own(my_scope).c_str());
3298 while (!refstack.empty()) {
3299 FieldOrArrayRef *subref = refstack.pop();
3300 if (subref->get_type() == FieldOrArrayRef::FIELD_REF) {
3301 expr->expr = mputprintf(expr->expr, ".%s()",
3302 subref->get_id()->get_name().c_str());
3303 } else {
3304 expr->expr = mputc(expr->expr, '[');
3305 subref->get_val()->generate_code_expr(expr);
3306 expr->expr = mputc(expr->expr, ']');
3307 }
3308 }
3309 return str;
3310 }
3311
3312 bool Template::compile_time() const
3313 {
3314 switch (templatetype) {
3315 case ALL_FROM:
3316 case VALUE_LIST_ALL_FROM:
3317 return false;
3318 case TEMPLATE_ERROR: /**< erroneous template */
3319 case TEMPLATE_NOTUSED: /**< not used symbol (-) */
3320 case OMIT_VALUE: /**< omit */
3321 case ANY_VALUE: /**< any value (?) */
3322 case ANY_OR_OMIT: /**< any or omit (*) */
3323 case SPECIFIC_VALUE: /**< specific value */
3324 case TEMPLATE_REFD: /**< reference to another template */
3325 case VALUE_RANGE: /**< value range match */
3326 case BSTR_PATTERN: /**< bitstring pattern */
3327 case HSTR_PATTERN: /**< hexstring pattern */
3328 case OSTR_PATTERN: /**< octetstring pattern */
3329 case CSTR_PATTERN: /**< character string pattern */
3330 case USTR_PATTERN: /**< universal charstring pattern */
3331 case TEMPLATE_INVOKE:
3332 // Simple templates can be computed at compile time
3333 return true;
3334
3335 // "Complex" templates need to look at all elements
3336 case TEMPLATE_LIST:
3337 case VALUE_LIST:
3338 case COMPLEMENTED_LIST:
3339 case SUPERSET_MATCH:
3340 case SUBSET_MATCH:
3341 case PERMUTATION_MATCH:
3342 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
3343 if (u.templates->get_t_byIndex(i)->compile_time()) continue;
3344 else return false;
3345 return true;
3346 case NAMED_TEMPLATE_LIST:
3347 for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++)
3348 if (!u.named_templates->get_nt_byIndex(i)->get_template()->compile_time())
3349 return false;
3350 return true;
3351 case INDEXED_TEMPLATE_LIST:
3352 for (size_t i = 0; i <u.indexed_templates->get_nof_its(); i++)
3353 if (!u.indexed_templates->get_it_byIndex(i)->get_template()->compile_time())
3354 return false;
3355 return true;
3356 }
3357
3358 return true; // not reached
3359 }
3360
3361 char *Template::generate_code_init_seof(char *str, const char *name)
3362 {
3363 switch (templatetype) {
3364 case TEMPLATE_LIST: {
3365 size_t nof_ts = u.templates->get_nof_ts();
3366 if (nof_ts == 0) {
3367 str = mputprintf(str, "%s = NULL_VALUE;\n", name);
3368 break;
3369 }
3370
3371 // nof_ts > 0
3372 Type *t_last = my_governor->get_type_refd_last();
3373 Int index_offset;
3374 if (t_last->get_typetype() == Type::T_ARRAY) {
3375 // take the start index from the array dimension
3376 index_offset = t_last->get_dimension()->get_offset();
3377 } else {
3378 // indexing always starts from zero
3379 index_offset = 0;
3380 }
3381
3382 const string& oftype_name =
3383 t_last->get_ofType()->get_genname_template(my_scope);
3384 const char *oftype_name_str = oftype_name.c_str();
3385
3386 ReferenceChain refch (this, "While searching template");
3387 if (!flattened || my_scope->get_statementblock_scope()) { // this "if" may be redundant if all non-var templates are flattened
3388 str = mputstr(str, "// this is a var template\n");
3389
3390 if (compile_time()) goto compile_time;
3391 // run-time, variable sized init
3392
3393 // This is a record-of var template, like this:
3394 // var template rec_of_int vt_r := {
3395 // 1, 2, 3, permutation(10, all from x, 20), 4, 5 }
3396 // ^^^^^^^--- these ------------------------^^^^^
3397 // are known at compile time, but the length of the "all from"
3398 // is only known at run time.
3399 // Collect the indices where there is an "all from".
3400 dynamic_array<int> variables;
3401 size_t fixed_part = 0;
3402 if (has_permutation) {
3403 for (size_t i = 0; i < nof_ts; i++) {
3404 Template *t = u.templates->get_t_byIndex(i);
3405 if (t->templatetype == PERMUTATION_MATCH) {
3406 size_t num_p = t->u.templates->get_nof_ts();
3407 // t->u.templates is 2: "hello" and all from ...
3408 for (size_t j = 0; j < num_p; ++j) {
3409 Template *subt = t->u.templates->get_t_byIndex(j);
3410 if (subt->templatetype == ALL_FROM) {
3411 variables.add(j);
3412 }
3413 else fixed_part++;
3414 }
3415 }
3416 else fixed_part++;
3417 }
3418
3419 char* str_preamble = 0;
3420 char* str_set_size = mputprintf(0, "%s.set_size(%lu", name,
3421 (unsigned long)fixed_part);
3422
3423 // variable part
3424 for (size_t i = 0; i < nof_ts; i++) {
3425 Template *t = u.templates->get_t_byIndex(i);
3426 for (size_t k = 0, v = variables.size(); k < v; ++k) {
3427 if (t->templatetype != PERMUTATION_MATCH) continue; // ?? really nothing to do ??
3428 Template *subt = t->u.templates->get_t_byIndex(variables[k]);
3429 if (subt->templatetype == ALL_FROM) {
3430 Value *refv = subt->u.all_from->u.specific_value;
3431 // don't call get_Value(), it rips out the value from the template
3432
3433 if (refv->get_valuetype()!=Value::V_REFD) FATAL_ERROR("%s", __FUNCTION__);
3434 Common::Reference *ref = refv->get_reference();
3435 FieldOrArrayRefs *subrefs = ref->get_subrefs();
3436 Common::Assignment *ass = ref->get_refd_assignment();
3437
3438 str_set_size = mputstrn(str_set_size, " + ", 3);
3439
3440 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3441 if (ref_pard) {
3442 // in case of parametrised references:
3443 // - temporary parameters need to be declared (stored in str_preamble)
3444 // - the same temporary needs to be used at each call (generate_code_cached call)
3445 expression_struct expr;
3446 Code::init_expr(&expr);
3447
3448 ref_pard->generate_code_cached(&expr);
3449 str_set_size = mputprintf(str_set_size, "%s", expr.expr);
3450 if (expr.preamble)
3451 str_preamble = mputstr(str_preamble, expr.preamble);
3452
3453 Code::free_expr(&expr);
3454 }
3455 else {
3456 str_set_size = mputstr (str_set_size, ass->get_id().get_name().c_str());
3457 if (subrefs) {
3458 expression_struct expr;
3459 Code::init_expr(&expr);
3460
3461 subrefs->generate_code(&expr, ass);
3462 str_set_size = mputprintf(str_set_size, "%s", expr.expr);
3463
3464 Code::free_expr(&expr);
3465 }
3466 }
3abe9331 3467
3468 switch(ass->get_asstype()) {
3469 case Common::Assignment::A_CONST:
3470 case Common::Assignment::A_EXT_CONST:
3471 case Common::Assignment::A_MODULEPAR:
3472 case Common::Assignment::A_VAR:
3473 case Common::Assignment::A_PAR_VAL_IN:
3474 case Common::Assignment::A_PAR_VAL_OUT:
3475 case Common::Assignment::A_PAR_VAL_INOUT:
3476 case Common::Assignment::A_FUNCTION_RVAL:
3477 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3478 if (ass->get_Type()->field_is_optional(subrefs)) {
3479 str_set_size = mputstrn(str_set_size, "()", 2);
3480 }
3481 break;
3482 default:
3483 break;
3484 }
3485
970ed795
EL
3486 str_set_size = mputstr(str_set_size, ".n_elem()");
3487 }
3488 }
3489 }
3490
3491 str = mputstr(str, str_preamble);
3492 str = mputstr(str, str_set_size);
3493
3494 Free(str_preamble);
3495 Free(str_set_size);
3496
3497 str = mputstrn(str, ");\n", 3); // finally done set_size
3abe9331 3498
970ed795
EL
3499 size_t index = 0;
3500 string skipper, hopper;
3501 for (size_t i = 0; i < nof_ts; i++) {
3502 Template *t = u.templates->get_t_byIndex(i);
3503 switch (t->templatetype) {
3504 case ALL_FROM: {
3505 break; }
3506 case PERMUTATION_MATCH: {
3507 size_t nof_perm_ts = t->u.templates->get_nof_ts();
3508 for (size_t j = 0; j < nof_perm_ts; j++) {
3509 Int ix(index_offset + index + j);
3510 Template *permut_elem = t->u.templates->get_t_byIndex(j);
3511 if (permut_elem->templatetype == ALL_FROM) {
3512 expression_struct expr;
3513 Code::init_expr(&expr);
3514 switch (permut_elem->u.all_from->templatetype) {
3515 case SPECIFIC_VALUE: {
3516 Value *spec = permut_elem->u.all_from->u.specific_value;
3517 switch (spec->get_valuetype()) {
3518 case Common::Value::V_REFD: {
3519 Common::Reference *ref = spec->get_reference();
3520
3521 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3522 if (ref_pard)
3523 ref_pard->generate_code_cached(&expr);
3524 else
3525 ref->generate_code(&expr);
3abe9331 3526
3527 Common::Assignment* ass = ref->get_refd_assignment();
3528 switch(ass->get_asstype()) {
3529 case Common::Assignment::A_CONST:
3530 case Common::Assignment::A_EXT_CONST:
3531 case Common::Assignment::A_MODULEPAR:
3532 case Common::Assignment::A_VAR:
3533 case Common::Assignment::A_PAR_VAL_IN:
3534 case Common::Assignment::A_PAR_VAL_OUT:
3535 case Common::Assignment::A_PAR_VAL_INOUT:
3536 case Common::Assignment::A_FUNCTION_RVAL:
3537 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3538 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
3539 expr.expr = mputstrn(expr.expr, "()", 2);
3540 }
3541 break;
3542 default:
3543 break;
3544 }
970ed795
EL
3545
3546 break; }
3547 default:
3548 FATAL_ERROR("vtype %d", spec->get_valuetype());
3549 break;
3550 }
3551 break; }
3552
3553
3554 default:
3555 FATAL_ERROR("ttype %d", permut_elem->u.all_from->templatetype);
3556 break;
3557 }
3558 str = mputprintf(str,
3559 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3560 expr.expr);
3561
3562 str = permut_elem->generate_code_init_seof_element(str, name,
3563 (Int2string(ix) + skipper + " + i_i").c_str(),
3564 oftype_name_str);
3565
3566 str = mputstrn(str, "}\n", 2);
3567 skipper += "-1+";
3568 skipper += expr.expr;
3569 skipper += ".n_elem() /* 3005 */ ";
3570 Code::free_expr(&expr);
3571 }
3572 else {
3573 str = permut_elem->generate_code_init_seof_element(str, name,
3574 (Int2string(ix) + skipper).c_str(), oftype_name_str);
3575 }
3576 }
3577 // do not consider index_offset in case of permutation indicators
3578 str = mputprintf(str, "%s.add_permutation(%lu%s, %lu%s);\n", name,
3579 (unsigned long)index, hopper.c_str(),
3580 (unsigned long)(index + nof_perm_ts - 1), skipper.c_str());
3581 hopper = skipper;
3582 t->set_code_generated();
3583 index += nof_perm_ts;
3584 break; }
3585
3586 default:
3587 str = t->generate_code_init_seof_element(str, name,
3588 (Int2string(index_offset + index) + skipper).c_str(), oftype_name_str);
3589 // no break
3590 case TEMPLATE_NOTUSED:
3591 index++;
3592 break;
3593 }
3594 }
3595
3596 break;
3597
3598 }
3599
3600
3601 if (!has_permutation && has_allfrom()) {
3602 for (size_t i = 0; i < nof_ts; i++) {
3603 Template *t = u.templates->get_t_byIndex(i);
3604 if (t->templatetype == ALL_FROM) {
3605 variables.add(i);
3606 }
3607 else {
3608 fixed_part++;
3609 }
3610 }
3611 char* str_preamble = 0;
3612 char* str_set_size = mputprintf(0, "%s.set_size(%lu", name,
3613 (unsigned long)fixed_part);
3614
3f84031e 3615 // variable part
3616 for (size_t i = 0, v = variables.size(); i < v; ++i) {
3617 Template *t = u.templates->get_t_byIndex(variables[i]);
970ed795
EL
3618 if (t->templatetype == ALL_FROM) {
3619 Value *refv = t->u.all_from->u.specific_value;
3620 // don't call get_Value(), it rips out the value from the template
3621 if (refv->get_valuetype()!=Value::V_REFD) FATAL_ERROR("%s", __FUNCTION__);
3622 Common::Reference *ref = refv->get_reference();
3623 FieldOrArrayRefs *subrefs = ref->get_subrefs();
3624 Common::Assignment *ass = ref->get_refd_assignment();
3625 str_set_size = mputstrn(str_set_size, " + ", 3);
3626 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3627 if (ref_pard) {
3628 // in case of parametrised references:
3629 // - temporary parameters need to be declared (stored in str_preamble)
3630 // - the same temporary needs to be used at each call (generate_code_cached call)
3631 expression_struct expr;
3632 Code::init_expr(&expr);
3633
3634 ref_pard->generate_code_cached(&expr);
3635 str_set_size = mputprintf(str_set_size, "%s", expr.expr);
3636 if (expr.preamble)
3637 str_preamble = mputstr(str_preamble, expr.preamble);
3638 Code::free_expr(&expr);
3639 }
3640 else {
3641 str_set_size = mputstr (str_set_size, ass->get_id().get_name().c_str());
3642 if (subrefs) {
3643 expression_struct expr;
3644 Code::init_expr(&expr);
3645 subrefs->generate_code(&expr, ass);
3646 str_set_size = mputprintf(str_set_size, "%s", expr.expr);
3647 Code::free_expr(&expr);
3648 }
3649 }
3abe9331 3650
3651 switch(ass->get_asstype()) {
3652 case Common::Assignment::A_CONST:
3653 case Common::Assignment::A_EXT_CONST:
3654 case Common::Assignment::A_MODULEPAR:
3655 case Common::Assignment::A_VAR:
3656 case Common::Assignment::A_PAR_VAL_IN:
3657 case Common::Assignment::A_PAR_VAL_OUT:
3658 case Common::Assignment::A_PAR_VAL_INOUT:
3659 case Common::Assignment::A_FUNCTION_RVAL:
3660 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3661 if (ass->get_Type()->field_is_optional(subrefs)) {
3662 str_set_size = mputstrn(str_set_size, "()", 2);
3663 }
3664 break;
3665 default:
3666 break;
3667 }
3668
970ed795
EL
3669 str_set_size = mputstr(str_set_size, ".n_elem()");
3670 }
3671 }
3f84031e 3672 str = mputstr(str, str_preamble);
3673 str = mputstr(str, str_set_size);
3674 Free(str_preamble);
3675 Free(str_set_size);
3676 str = mputstrn(str, ");\n", 3); // finally done set_size
3677
3678 size_t index = 0;
3679 string skipper;
3680 for (size_t i = 0; i < nof_ts; i++) {
3681 Template *t = u.templates->get_t_byIndex(i);
3682 Int ix(index_offset + i);
3683 switch (t->templatetype) {
3684 case ALL_FROM: {
970ed795
EL
3685 expression_struct expr;
3686 Code::init_expr(&expr);
3687 switch (t->u.all_from->templatetype) {
3688 case SPECIFIC_VALUE: {
3689 Value *spec = t->u.all_from->u.specific_value;
3690 switch (spec->get_valuetype()) {
3691 case Common::Value::V_REFD: {
3692 Common::Reference *ref = spec->get_reference();
3693 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3694 if (ref_pard)
3695 ref_pard->generate_code_cached(&expr);
3696 else
3697 ref->generate_code(&expr);
3abe9331 3698
3699 Common::Assignment* ass = ref->get_refd_assignment();
3700 switch(ass->get_asstype()) {
3701 case Common::Assignment::A_CONST:
3702 case Common::Assignment::A_EXT_CONST:
3703 case Common::Assignment::A_MODULEPAR:
3704 case Common::Assignment::A_VAR:
3705 case Common::Assignment::A_PAR_VAL_IN:
3706 case Common::Assignment::A_PAR_VAL_OUT:
3707 case Common::Assignment::A_PAR_VAL_INOUT:
3708 case Common::Assignment::A_FUNCTION_RVAL:
3709 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3710 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
3711 expr.expr = mputstrn(expr.expr, "()", 2);
3712 }
3713 break;
3714 default:
3715 break;
3716 }
3717
970ed795
EL
3718 break; }
3719 default:
3720 FATAL_ERROR("vtype %d", spec->get_valuetype());
3721 break;
3722 }
3723 break; }
3724 default: {
3725 FATAL_ERROR("ttype %d", t->u.all_from->templatetype);
3726 break; }
3727 }
3728 str = mputprintf(str,
3729 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3730 expr.expr);
3731 str = t->generate_code_init_seof_element(str, name,
3732 (Int2string(ix) + skipper + " + i_i").c_str(),
3733 oftype_name_str);
3734 str = mputstrn(str, "}\n", 2);
3735 skipper += "-1+";
3736 skipper += expr.expr;
3737 skipper += ".n_elem() ";
3738 Code::free_expr(&expr);
3739 t->set_code_generated();
3740 ++index;
3741 break; }
3742 default: {
970ed795
EL
3743 str = t->generate_code_init_seof_element(str, name,
3744 (Int2string(index_offset + index) + skipper).c_str(), oftype_name_str);
3745 // no break
3746 case TEMPLATE_NOTUSED:
3747 ++index;
3748 break; }
3749 }
3750 }
3f84031e 3751 break;
970ed795
EL
3752 }
3753
3754 // else carry on
3755 }
3756compile_time:
3757 // setting the size first
3758 if (!has_allfrom())
3759 str = mputprintf(str, "%s.set_size(%lu);\n", name, (unsigned long) get_nof_listitems());
3760 // determining the index offset based on the governor
3761
3762 size_t index = 0;
3763 for (size_t i = 0; i < nof_ts; i++) {
3764 Template *t = u.templates->get_t_byIndex(i);
3765 switch (t->templatetype) {
3766 case PERMUTATION_MATCH: {
3767 size_t nof_perm_ts = t->u.templates->get_nof_ts();
3768 for (size_t j = 0; j < nof_perm_ts; j++) {
3769 Int ix(index_offset + index + j);
3770 str = t->u.templates->get_t_byIndex(j)
3771 ->generate_code_init_seof_element(str, name,
3772 Int2string(ix).c_str(), oftype_name_str);
3773 }
3774 // do not consider index_offset in case of permutation indicators
3775 str = mputprintf(str, "%s.add_permutation(%lu, %lu);\n", name,
3776 (unsigned long)index, (unsigned long) (index + nof_perm_ts - 1));
3777 t->set_code_generated();
3778 index += nof_perm_ts;
3779 break; }
3780
3781 default:
3782 str = t->generate_code_init_seof_element(str, name,
3783 Int2string(index_offset + index).c_str(), oftype_name_str);
3784 // no break
3785 case ALL_FROM:
3786 case TEMPLATE_NOTUSED:
3787 index++;
3788 }
3789 }
3790 break; }
3791 case INDEXED_TEMPLATE_LIST: {
3792 size_t nof_its = u.indexed_templates->get_nof_its();
3793 if (nof_its > 0) {
3794 Type *t_last = my_governor->get_type_refd_last();
3795 const string& oftype_name =
3796 t_last->get_ofType()->get_genname_template(my_scope);
3797 const char *oftype_name_str = oftype_name.c_str();
3798 // There's no need to generate a set_size call here. To do that, we
3799 // should know the size of the base template, which is not available
3800 // from here.
3801 for (size_t i = 0; i < nof_its; i++) {
3802 IndexedTemplate *it = u.indexed_templates->get_it_byIndex(i);
3803 const string& tmp_id_1 = get_temporary_id();
3804 str = mputstr(str, "{\n");
3805 Value *index = (it->get_index()).get_val();
3806 if (index->get_valuetype() != Value::V_INT) {
3807 const string& tmp_id_2 = get_temporary_id();
3808 str = mputprintf(str, "int %s;\n", tmp_id_2.c_str());
3809 str = index->generate_code_init(str, tmp_id_2.c_str());
3810 str = mputprintf(str, "%s& %s = %s[%s];\n", oftype_name_str,
3811 tmp_id_1.c_str(), name, tmp_id_2.c_str());
3812 } else {
3813 str = mputprintf(str, "%s& %s = %s[%s];\n", oftype_name_str,
3814 tmp_id_1.c_str(), name,
3815 Int2string(index->get_val_Int()->get_val()).c_str());
3816 }
3817 str = it->get_template()->generate_code_init(str, tmp_id_1.c_str());
3818 str = mputstr(str, "}\n");
3819 }
3820 } else {
3821 // It seems to be impossible in this case.
3822 str = mputprintf(str, "%s = NULL_VALUE;\n", name);
3823 }
3824 break; }
3825 default:
3826 FATAL_ERROR("Template::generate_code_init_seof()");
3827 return NULL;
3828 }
3829 return str;
3830 }
3831
3832 char *Template::generate_code_init_seof_element(char *str, const char *name,
3833 const char* index, const char *element_type_genname)
3834 {
3835 if (needs_temp_ref()) {
3836 const string& tmp_id = get_temporary_id();
3837 str = mputprintf(str, "{\n"
3838 "%s& %s = %s[%s];\n",
3839 element_type_genname, tmp_id.c_str(), name, index);
3840 str = generate_code_init(str, tmp_id.c_str());
3841 str = mputstr(str, "}\n");
3842 } else {
3843 char *embedded_name = mprintf("%s[%s]", name, index);
3844 str = generate_code_init(str, embedded_name);
3845 Free(embedded_name);
3846 }
3847 return str;
3848 }
3849
3850 char *Template::generate_code_init_all_from(char *str, const char *name)
3851 {
3852 // we are ALL_FROM, hence u.all_from
3853 switch (u.all_from->templatetype) {
3854 case SPECIFIC_VALUE: {
3855 Value *spec = u.all_from->u.specific_value;
3856 switch (spec->get_valuetype()) {
3857 case Common::Value::V_REFD: {
3858 Common::Reference *ref = spec->get_reference();
3859 expression_struct expr;
3860 Code::init_expr(&expr);
3861 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3862 if (ref_pard)
3863 ref_pard->generate_code_cached(&expr);
3864 else
3865 ref->generate_code(&expr);
3abe9331 3866
3867 Common::Assignment* ass = ref->get_refd_assignment();
3868 switch(ass->get_asstype()) {
3869 case Common::Assignment::A_CONST:
3870 case Common::Assignment::A_EXT_CONST:
3871 case Common::Assignment::A_MODULEPAR:
3872 case Common::Assignment::A_VAR:
3873 case Common::Assignment::A_PAR_VAL_IN:
3874 case Common::Assignment::A_PAR_VAL_OUT:
3875 case Common::Assignment::A_PAR_VAL_INOUT:
3876 case Common::Assignment::A_FUNCTION_RVAL:
3877 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3878 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
3879 expr.expr = mputstrn(expr.expr, "()", 2);
3880 }
3881 break;
3882 default:
3883 break;
3884 }
3885
970ed795
EL
3886 str = mputprintf(str, "%s = %s[i_i];\n", name, expr.expr);
3887 // The caller will have to provide the for cycle with this variable
3888 Code::free_expr(&expr);
3889 break; }
3890 default:
3891 break;
3892 }
3893 break; }
3894 default:
3895 break;
3896 }
3897 return str;
3898 }
3899
3900 char *Template::generate_code_init_all_from_list(char *str, const char *name)
3901 {
3902 // FIXME: this is the third instance
3903 expression_struct expr;
3904 Code::init_expr(&expr);
3905 switch (u.all_from->templatetype) {
3906 case SPECIFIC_VALUE: {
3907 Value *spec = u.all_from->u.specific_value;
3908 switch (spec->get_valuetype()) {
3909 case Common::Value::V_REFD: {
3910 Common::Reference *ref = spec->get_reference();
3911 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3912 if (ref_pard)
3913 ref_pard->generate_code_cached(&expr);
3914 else
3915 ref->generate_code(&expr);
3916 break; }
3917 default:
3918 FATAL_ERROR("vtype %d", spec->get_valuetype());
3919 break;
3920 }
3921 break; }
3922
3923 default:
3924 FATAL_ERROR("ttype %d", u.all_from->templatetype);
3925 break;
3926 }
3927
3928 if (expr.preamble)
3929 str = mputstr(str, expr.preamble);
3930
3931 str = mputprintf(str,
3932 "%s.set_type(VALUE_LIST, %s.n_elem());\n"
3933 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3934 name,
3935 expr.expr,
3936 expr.expr);
3937 string embedded_name(name);
3938 embedded_name += ".list_item(i_i)";
3939 str = generate_code_init_all_from(str, embedded_name.c_str());
3940 str = mputstrn(str, "}\n", 2);
3941
3942 Code::free_expr(&expr);
3943 return str;
3944 }
3945
3946 char *Template::generate_code_init_se(char *str, const char *name)
3947 { // named template list
3948 size_t nof_nts = u.named_templates->get_nof_nts();
3949 Type *type = my_governor->get_type_refd_last();
3950 if (type->get_nof_comps() > 0) {
3951 for (size_t i = 0; i < nof_nts; i++) {
3952 NamedTemplate *nt = u.named_templates->get_nt_byIndex(i);
3953 const Identifier& fieldname = nt->get_name();
3954 const char *fieldname_str = 0;
3955 string at("AT_");
3956 if (type->get_typetype()==Type::T_ANYTYPE) {
3957 at += fieldname.get_name();
3958 fieldname_str = at.c_str();
3959 }
3960 else {
3961 fieldname_str = fieldname.get_name().c_str();
3962 }
3963 Template *t = nt->get_template();
3964 if (t->needs_temp_ref()) {
3965 Type *field_type;
3966 if (type->get_typetype() == Type::T_SIGNATURE) {
3967 field_type = type->get_signature_parameters()
3968 ->get_param_byName(fieldname)->get_type();
3969 } else {
3970 field_type = type->get_comp_byName(fieldname)->get_type();
3971 }
3972 const string& tmp_id = get_temporary_id();
3973 const char *tmp_id_str = tmp_id.c_str();
3974 str = mputprintf(str, "{\n"
3975 "%s& %s = %s.%s();\n",
3976 field_type->get_genname_template(my_scope).c_str(), tmp_id_str,
3977 name, fieldname_str);
3978 str = t->generate_code_init(str, tmp_id_str);
3979 str = mputstr(str, "}\n");
3980 } else {
3981 char *embedded_name = mprintf("%s.%s()", name, fieldname_str);
3982 str = t->generate_code_init(str, embedded_name);
3983 Free(embedded_name);
3984 }
3985 }
3986 } else {
3987 str = mputprintf(str, "%s = NULL_VALUE;\n", name);
3988 }
3989 return str;
3990 }
3991
3992 char *Template::generate_code_init_list(char *str, const char *name,
3993 bool is_complemented) // VALUE_LIST or COMPLEMENTED_LIST
3994 {
3995 size_t nof_ts = u.templates->get_nof_ts();
3996 const string& type_name = my_governor->get_genname_template(my_scope);
3997 const char *type_name_str = type_name.c_str();
3998
3999 dynamic_array<int> variables;
4000 size_t fixed_part = 0;
4001 for (size_t i = 0; i < nof_ts; ++i) {
4002 Template *t = u.templates->get_t_byIndex(i);
4003 if (t->templatetype == ALL_FROM) {
4004 variables.add(i);
4005 }
4006 else ++fixed_part;
4007 }
4008
4009 if (variables.size() > 0) {
4010 char* str_preamble = 0;
3abe9331 4011 char* str_set_type = mprintf("%s.set_type(%s, %lu", name,
970ed795
EL
4012 (is_complemented ? "COMPLEMENTED_LIST" : "VALUE_LIST"),
4013 (unsigned long)fixed_part);
4014 // The code to compute the number of elements at run time (the variable part).
4015 // This is the sum of sizes of "all from"s.
4016 for (size_t v = 0, vs = variables.size(); v < vs; ++v) {
4017 Template *vt = u.templates->get_t_byIndex(variables[v]);
4018 if (vt->templatetype != ALL_FROM) FATAL_ERROR("must be ALL_FROM");
4019 if (vt->u.all_from->templatetype != SPECIFIC_VALUE) FATAL_ERROR("not value");
4020 Value *val = vt->u.all_from->u.specific_value;
4021 if (val->get_valuetype() != Value::V_REFD) FATAL_ERROR("ref expected from val");
4022 Common::Reference *ref = val->get_reference();
4023 FieldOrArrayRefs *subrefs = ref->get_subrefs();
4024 Common::Assignment *ass = ref->get_refd_assignment();
4025 if (!ass) FATAL_ERROR("Could not grab ass!");
4026
4027 str_set_type = mputstrn(str_set_type, " + ", 3);
4028
4029 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
4030 if (ref_pard) {
4031 // in case of parametrised references:
4032 // - temporary parameters need to be declared (stored in str_preamble)
4033 // - the same temporary needs to be used at each call (generate_code_cached call)
4034 expression_struct expr;
4035 Code::init_expr(&expr);
4036
4037 ref_pard->generate_code_cached(&expr);
4038 str_set_type = mputprintf(str_set_type, "%s", expr.expr);
4039 if (expr.preamble)
4040 str_preamble = mputstr(str_preamble, expr.preamble);
4041
4042 Code::free_expr(&expr);
4043 }
4044 else {
4045 str_set_type = mputstr (str_set_type, ass->get_id().get_name().c_str());
4046 if (subrefs) {
4047 expression_struct expr;
4048 Code::init_expr(&expr);
4049
4050 subrefs->generate_code(&expr, ass);
3abe9331 4051 str_set_type = mputprintf(str_set_type, "%s", expr.expr);
970ed795
EL
4052
4053 Code::free_expr(&expr);
4054 }
4055 }
3abe9331 4056
4057 switch(ass->get_asstype()) {
4058 case Common::Assignment::A_CONST:
4059 case Common::Assignment::A_EXT_CONST:
4060 case Common::Assignment::A_MODULEPAR:
4061 case Common::Assignment::A_VAR:
4062 case Common::Assignment::A_PAR_VAL_IN:
4063 case Common::Assignment::A_PAR_VAL_OUT:
4064 case Common::Assignment::A_PAR_VAL_INOUT:
4065 case Common::Assignment::A_FUNCTION_RVAL:
4066 case Common::Assignment::A_EXT_FUNCTION_RVAL:
4067 if (ass->get_Type()->field_is_optional(subrefs)) {
4068 str_set_type = mputstrn(str_set_type, "()", 2);
4069 }
4070 break;
4071 default:
4072 break;
4073 }
4074
970ed795
EL
4075 str_set_type = mputstr(str_set_type, ".n_elem()");
4076 }
4077
4078 str = mputstr(str, str_preamble);
4079 str = mputstr(str, str_set_type);
4080
4081 Free(str_preamble);
4082 Free(str_set_type);
4083
4084 str = mputstrn(str, ");\n", 3);
3abe9331 4085
970ed795
EL
4086 string shifty; // contains the expression used to calculate
4087 // the size increase due to the runtime expansion of "all from".
4088 // In nof_ts, each "all from" appears as 1, but actually contributes
4089 // more. So the increase (by which all elements after the "all from"
4090 // are shifted) is:  target_of_all_from.n_elem()-1
4091 // This needs to be accumulated for each "all from".
4092 for (size_t vi = 0; vi < nof_ts; ++vi) {
4093 Template *t = u.templates->get_t_byIndex(vi);
4094 switch (t->templatetype) {
4095 case VALUE_LIST_ALL_FROM:
4096 FATAL_ERROR("VALUE_LIST_ALL_FROM not handled");
4097 case ALL_FROM: {
4098 expression_struct expr;
4099 Code::init_expr(&expr);
4100 // variable one
4101 switch (t->u.all_from->templatetype) {
4102 case SPECIFIC_VALUE: {
4103 Value *sv = t->u.all_from->u.specific_value;
4104 switch (sv->get_valuetype()) {
4105 case Value::V_REFD: {
4106 Common::Reference *ref = sv->get_reference();
4107 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
4108 if (ref_pard)
4109 ref_pard->generate_code_cached(&expr);
4110 else
3abe9331 4111 ref->generate_code(&expr);
4112
4113 Common::Assignment* ass = ref->get_refd_assignment();
4114 switch(ass->get_asstype()) {
4115 case Common::Assignment::A_CONST:
4116 case Common::Assignment::A_EXT_CONST:
4117 case Common::Assignment::A_MODULEPAR:
4118 case Common::Assignment::A_VAR:
4119 case Common::Assignment::A_PAR_VAL_IN:
4120 case Common::Assignment::A_PAR_VAL_OUT:
4121 case Common::Assignment::A_PAR_VAL_INOUT:
4122 case Common::Assignment::A_FUNCTION_RVAL:
4123 case Common::Assignment::A_EXT_FUNCTION_RVAL:
4124 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
4125 expr.expr = mputstrn(expr.expr, "()", 2);
4126 }
4127 break;
4128 default:
4129 break;
4130 }
4131
970ed795
EL
4132 break; }
4133
4134 default:
4135 FATAL_ERROR("VT NOT HANDLED");
4136 } // switch valuetype
4137 break; }
4138
4139 default:
4140 FATAL_ERROR("ttype not handled");
4141 break;
4142 }
4143
4144 // All local variables should contain a single underscore,
4145 // to avoid potential clashes with field names.
4146 str = mputprintf(str, "for (int i_i= 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
4147 expr.expr);
4148
4149 if (t->needs_temp_ref()) {
4150 // Not possible, because t->templatetype is ALL_FROM
4151 FATAL_ERROR("temp ref not handled");
4152 }
4153 char *embedded_name = mprintf("%s.list_item(%lu + i_i%s)", name,
4154 (unsigned long) vi, shifty.c_str());
4155 str = t->generate_code_init(str, embedded_name);
4156 Free(embedded_name);
4157
4158 str = mputstrn(str, "}\n", 2);
4159
4160 shifty += "-1+";
4161 shifty += expr.expr;
4162 shifty += ".n_elem() /* 3303 */ ";
4163
4164 Code::free_expr(&expr);
4165 break; }
4166
4167 default: // "fixed one"
4168 if (t->needs_temp_ref()) { // FIXME: this is copypasta from below / but may need to be changed
4169 const string& tmp_id = get_temporary_id();
4170 const char *tmp_id_str = tmp_id.c_str();
4171 str = mputprintf(str, "{\n"
4172 "%s& %s = %s.list_item(%lu);\n",
4173 type_name_str, tmp_id_str, name, (unsigned long) vi);
4174 str = t->generate_code_init(str, tmp_id_str);
4175 str = mputstr(str, "}\n");
4176 } else {
4177 char *embedded_name = mprintf("%s.list_item(%lu%s)", name,
4178 (unsigned long) vi, shifty.c_str());
4179 str = t->generate_code_init(str, embedded_name);
4180 Free(embedded_name);
4181 }
4182 break;
4183 } // switch t->templatetype
4184 }
4185 }
4186 else {
4187 str = mputprintf(str, "%s.set_type(%s, %lu);\n", name,
4188 is_complemented ? "COMPLEMENTED_LIST" : "VALUE_LIST",
4189 (unsigned long) nof_ts);
4190 for (size_t i = 0; i < nof_ts; i++) {
4191 Template *t = u.templates->get_t_byIndex(i);
4192 if (t->needs_temp_ref()) {
4193 const string& tmp_id = get_temporary_id();
4194 const char *tmp_id_str = tmp_id.c_str();
4195 str = mputprintf(str, "{\n"
4196 "%s& %s = %s.list_item(%lu);\n",
4197 type_name_str, tmp_id_str, name, (unsigned long) i);
4198 str = t->generate_code_init(str, tmp_id_str);
4199 str = mputstr(str, "}\n");
4200 } else {
4201 char *embedded_name = mprintf("%s.list_item(%lu)", name,
4202 (unsigned long) i);
4203 str = t->generate_code_init(str, embedded_name);
4204 Free(embedded_name);
4205 }
4206 }
4207 }
4208 return str;
4209 }
4210
4211 char *Template::generate_code_init_set(char *str, const char *name,
4212 bool is_superset) // SUPERSET_MATCH and SUBSET_MATCH
4213 {
4214 size_t nof_ts = u.templates->get_nof_ts();
4215 const string& oftype_name =
4216 my_governor->get_ofType()->get_genname_template(my_scope);
4217 const char *oftype_name_str = oftype_name.c_str();
4218
4219 dynamic_array<int> variables;
4220 size_t fixed_part = 0;
4221 for (size_t i = 0; i < nof_ts; ++i) {
4222 Template *t = u.templates->get_t_byIndex(i);
4223 if (t->templatetype == ALL_FROM) {
4224 variables.add(i);
4225 }
4226 else ++fixed_part;
4227 }
4228
4229 //warning("There are %lu set elements", nof_ts);
4230 if (variables.size() > 0) {
4231 char* str_preamble = 0;
4232 char* str_set_type = mputprintf(0, "%s.set_type(%s, %lu", name,
4233 is_superset ? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) fixed_part);
4234
4235 for (size_t v = 0, vs = variables.size(); v < vs; ++v) {
4236 Template *vt = u.templates->get_t_byIndex(variables[v]);
4237 if (vt->templatetype != ALL_FROM) FATAL_ERROR("must be ALL_FROM");
4238 if (vt->u.all_from->templatetype != SPECIFIC_VALUE) FATAL_ERROR("not value");
4239 Value *val = vt->u.all_from->u.specific_value;
4240 if (val->get_valuetype() != Value::V_REFD) FATAL_ERROR("ref expected from val");
4241 Common::Reference *ref = val->get_reference();
4242 FieldOrArrayRefs *subrefs = ref->get_subrefs();
4243 Common::Assignment *ass = ref->get_refd_assignment();
4244 if (!ass) FATAL_ERROR("Could not grab ass!");
4245
4246 str_set_type = mputstrn(str_set_type, " + ", 3);
4247
4248 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
4249 if (ref_pard) {
4250 // in case of parametrised references:
4251 // - temporary parameters need to be declared (stored in str_preamble)
4252 // - the same temporary needs to be used at each call (generate_code_cached call)
4253 expression_struct expr;
4254 Code::init_expr(&expr);
4255
4256 ref_pard->generate_code_cached(&expr);
4257 str_set_type = mputprintf(str_set_type, "%s", expr.expr);
4258 if (expr.preamble)
4259 str_preamble = mputstr(str_preamble, expr.preamble);
4260
4261 Code::free_expr(&expr);
4262 }
4263 else {
4264 str_set_type = mputstr (str_set_type, ass->get_id().get_name().c_str());
4265 if (subrefs) {
4266 expression_struct expr;
4267 Code::init_expr(&expr);
4268
4269 subrefs->generate_code(&expr, ass);
4270 str_set_type = mputprintf(str_set_type, "%s", expr.expr);
4271
4272 Code::free_expr(&expr);
4273 }
4274 }
3abe9331 4275
4276 switch(ass->get_asstype()) {
4277 case Common::Assignment::A_CONST:
4278 case Common::Assignment::A_EXT_CONST:
4279 case Common::Assignment::A_MODULEPAR:
4280 case Common::Assignment::A_VAR:
4281 case Common::Assignment::A_PAR_VAL_IN:
4282 case Common::Assignment::A_PAR_VAL_OUT:
4283 case Common::Assignment::A_PAR_VAL_INOUT:
4284 case Common::Assignment::A_FUNCTION_RVAL:
4285 case Common::Assignment::A_EXT_FUNCTION_RVAL:
4286 if (ass->get_Type()->field_is_optional(subrefs)) {
4287 str_set_type = mputstrn(str_set_type, "()", 2);
4288 }
4289 break;
4290 default:
4291 break;
4292 }
4293
970ed795
EL
4294 str_set_type = mputstr(str_set_type, ".n_elem()");
4295 }
4296
4297 str = mputstr(str, str_preamble);
4298 str = mputstr(str, str_set_type);
4299
4300 Free(str_preamble);
4301 Free(str_set_type);
4302
4303 str = mputstrn(str, ");\n", 3);
4304
4305 string shifty;
4306 for (size_t i = 0; i < nof_ts; i++) {
4307 Template *t = u.templates->get_t_byIndex(i);
4308 switch (t->templatetype) {
4309 case ALL_FROM: {
4310 expression_struct expr; // FIXME copypasta from init_list above !
4311 Code::init_expr(&expr);
4312 // variable one
4313 switch (t->u.all_from->templatetype) {
4314 case SPECIFIC_VALUE: {
4315 Value *sv = t->u.all_from->u.specific_value;
4316 switch (sv->get_valuetype()) {
4317 case Value::V_REFD: {
4318 Common::Reference *ref = sv->get_reference();
4319 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
4320 if (ref_pard)
4321 ref_pard->generate_code_cached(&expr);
4322 else
4323 ref->generate_code(&expr);
3abe9331 4324
4325 Common::Assignment* ass = ref->get_refd_assignment();
4326 switch(ass->get_asstype()) {
4327 case Common::Assignment::A_CONST:
4328 case Common::Assignment::A_EXT_CONST:
4329 case Common::Assignment::A_MODULEPAR:
4330 case Common::Assignment::A_VAR:
4331 case Common::Assignment::A_PAR_VAL_IN:
4332 case Common::Assignment::A_PAR_VAL_OUT:
4333 case Common::Assignment::A_PAR_VAL_INOUT:
4334 case Common::Assignment::A_FUNCTION_RVAL:
4335 case Common::Assignment::A_EXT_FUNCTION_RVAL:
4336 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
4337 expr.expr = mputstrn(expr.expr, "()", 2);
4338 }
4339 break;
4340 default:
4341 break;
4342 }
4343
970ed795
EL
4344 break; }
4345
4346 default:
4347 FATAL_ERROR("VT NOT HANDLED");
4348 } // switch valuetype
4349 break; }
4350
4351 default:
4352 FATAL_ERROR("ttype not handled");
4353 break;
4354 }
4355
4356 str = mputprintf(str,
4357 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
4358 expr.expr);
4359
4360 // Name for the LHS
4361 char *embedded_name = mprintf("%s.set_item(%lu%s + i_i)", name,
4362 (unsigned long) i, shifty.c_str());
4363 str = t->generate_code_init_all_from(str, embedded_name);
4364 Free(embedded_name);
4365
4366 str = mputstrn(str, "}\n", 2);
4367
4368 shifty += "-1+";
4369 shifty += expr.expr;
4370 shifty += ".n_elem() /* 3442 */";
4371 Code::free_expr(&expr);
4372 break; }
4373 case VALUE_LIST_ALL_FROM:
4374 FATAL_ERROR("Not possible");
4375 break; // not reached
4376
4377 default:
4378 if (t->needs_temp_ref()) {
4379 const string& tmp_id = get_temporary_id();
4380 const char *tmp_id_str = tmp_id.c_str();
4381 str = mputprintf(str, "{\n"
4382 "%s& %s = %s.set_item(%lu%s);\n",
4383 oftype_name_str, tmp_id_str, name, (unsigned long) i, shifty.c_str());
4384 str = t->generate_code_init(str, tmp_id_str);
4385 str = mputstr(str, "}\n");
4386 } else {
4387 char *embedded_name = mprintf("%s.set_item(%lu%s)", name,
4388 (unsigned long) i, shifty.c_str());
4389 str = t->generate_code_init(str, embedded_name);
4390 Free(embedded_name);
4391 }
4392 break;
4393 } // switch t->templatetype
4394 }
4395
4396 }
4397 else {
4398 str = mputprintf(str, "%s.set_type(%s, %lu);\n", name,
4399 is_superset ? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) nof_ts);
4400 for (size_t i = 0; i < nof_ts; i++) {
4401 Template *t = u.templates->get_t_byIndex(i);
4402 if (t->needs_temp_ref()) {
4403 const string& tmp_id = get_temporary_id();
4404 const char *tmp_id_str = tmp_id.c_str();
4405 str = mputprintf(str, "{\n"
4406 "%s& %s = %s.set_item(%lu);\n",
4407 oftype_name_str, tmp_id_str, name, (unsigned long) i);
4408 str = t->generate_code_init(str, tmp_id_str);
4409 str = mputstr(str, "}\n");
4410 } else {
4411 char *embedded_name = mprintf("%s.set_item(%lu)", name,
4412 (unsigned long) i);
4413 str = t->generate_code_init(str, embedded_name);
4414 Free(embedded_name);
4415 }
4416 }
4417 }
4418 return str;
4419 }
4420
4421 void Template::generate_code_expr_invoke(expression_struct *expr)
4422 {
4423 Value *last_v = u.invoke.v->get_value_refd_last();
4424 if (last_v->get_valuetype() == Value::V_FUNCTION) {
4425 Common::Assignment *function = last_v->get_refd_fat();
4426 expr->expr = mputprintf(expr->expr, "%s(",
4427 function->get_genname_from_scope(my_scope).c_str());
4428 u.invoke.ap_list->generate_code_alias(expr,
4429 function->get_FormalParList(), function->get_RunsOnType(), false);
4430 } else {
4431 u.invoke.v->generate_code_expr_mandatory(expr);
4432 expr->expr = mputstr(expr->expr, ".invoke(");
4433 Type* gov_last = u.invoke.v->get_expr_governor_last();
4434 u.invoke.ap_list->generate_code_alias(expr, 0,
4435 gov_last->get_fat_runs_on_type(), gov_last->get_fat_runs_on_self());
4436 }
4437 expr->expr = mputc(expr->expr, ')');
4438 }
4439
51fa56b9 4440 char *Template::rearrange_init_code_refd(char *str, Common::Module* usage_mod)
970ed795
EL
4441 {
4442 if (templatetype != TEMPLATE_REFD)
4443 FATAL_ERROR("Template::rearrange_init_code_refd()");
51fa56b9 4444 ActualParList *actual_parlist = u.ref.ref->get_parlist();
970ed795
EL
4445 // generate code for the templates that are used in the actual parameter
4446 // list of the reference
4447 Common::Assignment *ass = u.ref.ref->get_refd_assignment();
51fa56b9 4448 if (actual_parlist) str = actual_parlist->rearrange_init_code(str, usage_mod);
970ed795
EL
4449 // do nothing if the reference does not point to a template definition
4450 if (ass->get_asstype() != Common::Assignment::A_TEMPLATE) return str;
970ed795 4451 Template *t = ass->get_Template();
51fa56b9 4452 FormalParList *formal_parlist = ass->get_FormalParList();
4453 if (formal_parlist) {
970ed795
EL
4454 // the reference points to a parameterized template
4455 // we must perform the rearrangement for all non-parameterized templates
51fa56b9 4456 // that are referred by the parameterized template regardless of the
970ed795 4457 // sub-references of u.ref.ref
51fa56b9 4458 str = t->rearrange_init_code(str, usage_mod);
4459 // the parameterized template's default values must also be generated
4460 // (this only generates their value assignments, their declarations will
4461 // be generated when the template's definition is reached)
4462 if (ass->get_my_scope()->get_scope_mod_gen() == usage_mod) {
4463 str = formal_parlist->generate_code_defval(str);
4464 }
970ed795
EL
4465 } else {
4466 // the reference points to a non-parameterized template
4467 FieldOrArrayRefs *subrefs = u.ref.ref->get_subrefs();
4468 if (subrefs) {
4469 // we should follow the sub-references as much as we can
4470 // and perform the rearrangement for the referred field only
4471 for (size_t i = 0; i < subrefs->get_nof_refs(); i++) {
4472 FieldOrArrayRef *ref = subrefs->get_ref(i);
4473 if (ref->get_type() == FieldOrArrayRef::FIELD_REF) {
4474 // stop if the body does not have fields
4475 if (t->templatetype != NAMED_TEMPLATE_LIST) break;
4476 // get the sub-template of the referred field
4477 t = t->u.named_templates->get_nt_byName(*ref->get_id())
4478 ->get_template();
4479 } else {
4480 // stop if the body is not a list
4481 if (t->templatetype != TEMPLATE_LIST) break;
4482 Value *array_index = ref->get_val()->get_value_refd_last();
4483 // stop if the index cannot be evaluated at compile time
4484 if (array_index->get_valuetype() != Value::V_INT) break;
4485 Int index = array_index->get_val_Int()->get_val();
4486 // index transformation in case of arrays
4487 if (t->my_governor->get_typetype() == Type::T_ARRAY)
4488 index -= t->my_governor->get_dimension()->get_offset();
4489 // get the template with the given index
4490 t = t->get_listitem_byIndex(index);
4491 }
4492 }
4493 }
4494 // otherwise if the reference points to a top-level template
4495 // we should initialize its entire body
51fa56b9 4496 if (ass->get_my_scope()->get_scope_mod_gen() == usage_mod) {
4497 str = t->generate_code_init(str, t->get_lhs_name().c_str());
4498 }
970ed795
EL
4499 }
4500 return str;
4501 }
4502
51fa56b9 4503 char *Template::rearrange_init_code_invoke(char *str, Common::Module* usage_mod)
970ed795
EL
4504 {
4505 str = u.invoke.v->rearrange_init_code(str);
51fa56b9 4506 str = u.invoke.ap_list->rearrange_init_code(str, usage_mod);
970ed795
EL
4507 return str;
4508 }
4509
4510 bool Template::needs_temp_ref()
4511 {
4512 if (length_restriction || is_ifpresent) return true;
4513 switch (templatetype) {
4514 case OMIT_VALUE:
4515 case ANY_VALUE:
4516 case ANY_OR_OMIT:
4517 case SPECIFIC_VALUE:
4518 case TEMPLATE_REFD:
4519 case TEMPLATE_INVOKE:
4520 case BSTR_PATTERN:
4521 case HSTR_PATTERN:
4522 case OSTR_PATTERN:
4523 case CSTR_PATTERN:
4524 case USTR_PATTERN:
4525 return false;
4526 case TEMPLATE_LIST:
4527 // temporary reference is needed if the template has at least one
4528 // element (excluding not used symbols)
4529 for (size_t i = 0; i < u.templates->get_nof_ts(); i++) {
4530 if (u.templates->get_t_byIndex(i)->templatetype != TEMPLATE_NOTUSED)
4531 return true;
4532 }
4533 return false;
4534 case INDEXED_TEMPLATE_LIST:
4535 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++) {
4536 if (u.indexed_templates->get_it_byIndex(i)->get_template()
4537 ->templatetype != TEMPLATE_NOTUSED)
4538 return true;
4539 }
4540 return false;
4541 case NAMED_TEMPLATE_LIST:
4542 return u.named_templates->get_nof_nts() > 1;
4543 case ALL_FROM:
4544 case VALUE_LIST_ALL_FROM:
4545 return false;
4546 case VALUE_LIST:
4547 case COMPLEMENTED_LIST:
4548 case VALUE_RANGE:
4549 case SUPERSET_MATCH:
4550 case SUBSET_MATCH:
4551 return true;
4552 case TEMPLATE_ERROR:
4553 case TEMPLATE_NOTUSED:
4554 FATAL_ERROR("Template::needs_temp_ref()");
4555 case PERMUTATION_MATCH:
4556 // FIXME
4557 return false;
4558 }
4559 return false;
4560 }
4561
4562 bool Template::has_single_expr()
4563 {
4564 if (length_restriction || is_ifpresent || get_needs_conversion())
4565 return false;
4566 switch (templatetype) {
4567 case OMIT_VALUE:
4568 case ANY_VALUE:
4569 case ANY_OR_OMIT:
4570 case BSTR_PATTERN:
4571 case HSTR_PATTERN:
4572 case OSTR_PATTERN:
4573 case CSTR_PATTERN:
4574 case USTR_PATTERN:
4575 return true;
4576 case SPECIFIC_VALUE:
4577 return u.specific_value->has_single_expr();
4578 case TEMPLATE_REFD: {
4579 Template *t_last = get_template_refd_last();
4580 if (t_last != this && t_last->has_single_expr()) {
4581 for (Scope *t_scope = my_scope; t_scope;
4582 t_scope = t_scope->get_parent_scope()) {
4583 // return true if t_last is visible from my scope
4584 if (t_scope == t_last->my_scope) return true;
4585 }
4586 }
4587 // otherwise consider the reference itself
4588 return u.ref.ref->has_single_expr(); }
4589 case TEMPLATE_INVOKE:
4590 if (!u.invoke.v->has_single_expr()) return false;
4591 for (size_t i = 0; i < u.invoke.ap_list->get_nof_pars(); i++)
4592 if (!u.invoke.ap_list->get_par(i)->has_single_expr()) return false;
4593 return true;
4594 case TEMPLATE_LIST:
4595 return u.templates->get_nof_ts() == 0;
4596 case NAMED_TEMPLATE_LIST: {
4597 if (!my_governor) FATAL_ERROR("Template::has_single_expr()");
4598 Type *type = my_governor->get_type_refd_last();
4599 return type->get_nof_comps() == 0; }
4600 case INDEXED_TEMPLATE_LIST:
4601 return u.indexed_templates->get_nof_its() == 0;
4602 case VALUE_LIST:
4603 case COMPLEMENTED_LIST:
4604 case VALUE_RANGE:
4605 case SUPERSET_MATCH:
4606 case SUBSET_MATCH:
4607 case PERMUTATION_MATCH:
4608 return false;
4609 case ALL_FROM:
4610 case VALUE_LIST_ALL_FROM:
4611 return false;
4612 default:
4613 FATAL_ERROR("Template::has_single_expr()");
4614 return false;
4615 }
4616 }
4617
4618 string Template::get_single_expr(bool cast_needed)
4619 {
4620 if (cast_needed && (length_restriction || is_ifpresent))
4621 FATAL_ERROR("Template::get_single_expr()");
4622 string ret_val;
4623 switch (templatetype) {
4624 case OMIT_VALUE:
4625 ret_val = "OMIT_VALUE";
4626 break;
4627 case ANY_VALUE:
4628 ret_val = "ANY_VALUE";
4629 break;
4630 case ANY_OR_OMIT:
4631 ret_val = "ANY_OR_OMIT";
4632 break;
4633 case SPECIFIC_VALUE:
4634 ret_val = u.specific_value->get_single_expr();
4635 break;
4636 case TEMPLATE_REFD: {
4637 // convert the reference to a single expression
4638 expression_struct expr;
4639 Code::init_expr(&expr);
4640 u.ref.ref->generate_code(&expr);
4641 if (expr.preamble || expr.postamble)
4642 FATAL_ERROR("Template::get_single_expr()");
4643 ret_val = expr.expr;
4644 Code::free_expr(&expr);
4645 return ret_val;
4646 }
4647 case TEMPLATE_INVOKE: {
4648 expression_struct expr;
4649 Code::init_expr(&expr);
4650 generate_code_expr_invoke(&expr);
4651 if (expr.preamble || expr.postamble)
4652 FATAL_ERROR("Template::get_single_expr()");
4653 ret_val = expr.expr;
4654 Code::free_expr(&expr);
4655 return ret_val; }
4656 case TEMPLATE_LIST:
4657 if (u.templates->get_nof_ts() != 0)
4658 FATAL_ERROR("Template::get_single_expr()");
4659 ret_val = "NULL_VALUE";
4660 break;
4661 case NAMED_TEMPLATE_LIST:
4662 if (u.named_templates->get_nof_nts() != 0)
4663 FATAL_ERROR("Template::get_single_expr()");
4664 ret_val = "NULL_VALUE";
4665 break;
4666 case INDEXED_TEMPLATE_LIST:
4667 if (u.indexed_templates->get_nof_its() != 0)
4668 FATAL_ERROR("Template::get_single_expr()");
4669 ret_val = "NULL_VALUE";
4670 break;
4671 case BSTR_PATTERN:
4672 return get_my_scope()->get_scope_mod_gen()
4673 ->add_bitstring_pattern(*u.pattern);
4674 case HSTR_PATTERN:
4675 return get_my_scope()->get_scope_mod_gen()
4676 ->add_hexstring_pattern(*u.pattern);
4677 case OSTR_PATTERN:
4678 return get_my_scope()->get_scope_mod_gen()
4679 ->add_octetstring_pattern(*u.pattern);
4680 case CSTR_PATTERN:
4681 case USTR_PATTERN:
4682 return u.pstring
4683 ->create_charstring_literals(get_my_scope()->get_scope_mod_gen());
4684 default:
4685 FATAL_ERROR("Template::get_single_expr()");
4686 }
4687 if (cast_needed) ret_val = my_governor->get_genname_template(my_scope) +
4688 "(" + ret_val + ")";
4689 return ret_val;
4690 }
4691
4692 void Template::dump(unsigned level) const
4693 {
4694 DEBUG(level, "%s", get_templatetype_str());
4695 switch (templatetype) {
4696 case TEMPLATE_ERROR:
4697 case OMIT_VALUE:
4698 case ANY_VALUE:
4699 case ANY_OR_OMIT:
4700 break;
4701 case SPECIFIC_VALUE:
4702 u.specific_value->dump(level+1);
4703 break;
4704 case TEMPLATE_REFD:
4705 u.ref.ref->dump(level+1);
4706 break;
4707 case TEMPLATE_INVOKE:
4708 u.invoke.v->dump(level+1);
4709 if (u.invoke.ap_list) u.invoke.ap_list->dump(level + 1);
4710 else if (u.invoke.t_list) u.invoke.t_list->dump(level + 1);
4711 break;
4712 case TEMPLATE_LIST:
4713 case VALUE_LIST:
4714 case COMPLEMENTED_LIST:
4715 case SUPERSET_MATCH:
4716 case SUBSET_MATCH:
4717 case PERMUTATION_MATCH:
4718 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
4719 u.templates->get_t_byIndex(i)->dump(level+1);
4720 break;
4721 case NAMED_TEMPLATE_LIST:
4722 for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++)
4723 u.named_templates->get_nt_byIndex(i)->dump(level+1);
4724 break;
4725 case INDEXED_TEMPLATE_LIST:
4726 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++)
4727 u.indexed_templates->get_it_byIndex(i)->dump(level+1);
4728 break;
4729 case VALUE_RANGE:
4730 u.value_range->dump(level);
4731 break;
4732 case BSTR_PATTERN:
4733 case HSTR_PATTERN:
4734 case OSTR_PATTERN:
4735 DEBUG(level+1, "%s", u.pattern->c_str());
4736 break;
4737 case CSTR_PATTERN:
4738 case USTR_PATTERN:
4739 u.pstring->dump(level+1);
4740 break;
4741 case ALL_FROM:
4742 case VALUE_LIST_ALL_FROM:
4743 u.all_from->dump(level+1);
4744 break;
4745 default:
4746 break;
4747 }
4748 if (length_restriction) length_restriction->dump(level + 1);
4749 }
4750
4751 bool Template::has_allfrom() const
4752 { // the code generation of all from is not fully implemented. This helps avoid of using it.
4753 if (templatetype != TEMPLATE_LIST) FATAL_ERROR("has_allfrom(): Templatetype shall be TEMPLATE_LIST");
4754 size_t nof_ts = u.templates->get_nof_ts();
4755 for (size_t i = 0; i < nof_ts; i++) {
4756 if (u.templates->get_t_byIndex(i)->templatetype == ALL_FROM) {
4757 return true;
4758 }
4759 }
4760 return false;
4761 }
4762
4763 // =================================
4764 // ===== TemplateInstance
4765 // =================================
4766
4767 TemplateInstance::TemplateInstance(const TemplateInstance& p)
4768 : Node(p), Location(p)
4769 {
4770 type = p.type ? p.type->clone() : 0;
4771 derived_reference = p.derived_reference ? p.derived_reference->clone() : 0;
4772 template_body = p.template_body->clone();
4773 }
4774
4775 TemplateInstance::TemplateInstance(Type *p_type, Ref_base *p_ref,
4776 Template *p_body) : Node(), Location(), type(p_type),
4777 derived_reference(p_ref), template_body(p_body)
4778 {
4779 if (!p_body) FATAL_ERROR("TemplateInstance::TemplateInstance()");
4780 if (type) type->set_ownertype(Type::OT_TEMPLATE_INST, this);
4781 }
4782
4783 TemplateInstance::~TemplateInstance()
4784 {
4785 delete type;
4786 delete derived_reference;
4787 delete template_body;
4788 }
4789
4790 void TemplateInstance::release()
4791 {
4792 type = 0;
4793 derived_reference = 0;
4794 template_body = 0;
4795 }
4796
4797 TemplateInstance *TemplateInstance::clone() const
4798 {
4799 return new TemplateInstance(*this);
4800 }
4801
4802 void TemplateInstance::set_fullname(const string& p_fullname)
4803 {
4804 Node::set_fullname(p_fullname);
4805 if (type) type->set_fullname(p_fullname + ".<type>");
4806 if (derived_reference)
4807 derived_reference->set_fullname(p_fullname + ".<derived_reference>");
4808 template_body->set_fullname(p_fullname);
4809 }
4810
4811 void TemplateInstance::set_my_scope(Scope *p_scope)
4812 {
4813 if (type) type->set_my_scope(p_scope);
4814 if (derived_reference) derived_reference->set_my_scope(p_scope);
4815 template_body->set_my_scope(p_scope);
4816 }
4817
4818 Type::typetype_t TemplateInstance::get_expr_returntype
4819 (Type::expected_value_t exp_val)
4820 {
4821 Type *t = get_expr_governor(exp_val);
4822 if (t) return t->get_type_refd_last()->get_typetype_ttcn3();
4823 else return template_body->get_expr_returntype(exp_val);
4824 }
4825
4826 Type *TemplateInstance::get_expr_governor(Type::expected_value_t exp_val)
4827 {
4828 if (type) return type;
4829 if (derived_reference) {
4830 Type *ret_val = chk_DerivedRef(0);
4831 if (ret_val) return ret_val;
4832 }
4833 return template_body->get_expr_governor(exp_val);
4834 }
4835
4836 void TemplateInstance::chk(Type *governor)
4837 {
4838 if (!governor) FATAL_ERROR("TemplateInstance::chk()");
4839 governor = chk_Type(governor);
4840 governor = chk_DerivedRef(governor);
4841 template_body->set_my_governor(governor);
4842 governor->chk_this_template_ref(template_body);
4843 governor->chk_this_template_generic(template_body,
4844 (derived_reference != 0 ? INCOMPLETE_ALLOWED : INCOMPLETE_NOT_ALLOWED),
4845 OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, NOT_IMPLICIT_OMIT, 0);
4846 }
4847
4848 Type *TemplateInstance::chk_Type(Type *governor)
4849 {
4850 if (!type) return governor;
4851 {
4852 Error_Context cntxt(type, "In explicit type specification");
4853 type->chk();
4854 }
4855 TypeCompatInfo info(template_body->get_template_refd_last()
4856 ->get_my_scope()->get_scope_mod(), governor, type,
4857 true, false);
4858 TypeChain l_chain;
4859 TypeChain r_chain;
4860 if (!governor) return type;
3f84031e 4861 else if (governor->is_compatible(type, &info, &l_chain, &r_chain, true)) {
970ed795
EL
4862 return governor;
4863 } else {
4864 if (info.is_subtype_error()) {
4865 type->error("%s", info.get_subtype_error().c_str());
4866 } else
4867 if (!info.is_erroneous()) {
4868 type->error("Incompatible explicit type specification: `%s' was "
4869 "expected instead of `%s'",
4870 governor->get_typename().c_str(),
4871 type->get_typename().c_str());
4872 } else {
4873 type->error("%s", info.get_error_str_str().c_str());
4874 }
4875 return type;
4876 }
4877 }
4878
4879 Type *TemplateInstance::chk_DerivedRef(Type *governor)
4880 {
4881 if (!derived_reference) return governor;
4882 Error_Context cntxt(derived_reference, "In derived reference");
4883 Common::Assignment *ass = derived_reference->get_refd_assignment();
4884 // the base template reference must not have sub-references
4885 if (derived_reference->get_subrefs())
4886 FATAL_ERROR("TemplateInstance::chk_DerivedRef()");
4887 bool set_bt = false;
4888 if (!ass) goto error;
4889 switch (ass->get_asstype()) {
4890 case Common::Assignment::A_TEMPLATE:
4891 set_bt = true;
4892 // no break
4893 case Common::Assignment::A_MODULEPAR_TEMP:
4894 case Common::Assignment::A_VAR_TEMPLATE:
4895 case Common::Assignment::A_PAR_TEMPL_IN:
4896 case Common::Assignment::A_PAR_TEMPL_OUT:
4897 case Common::Assignment::A_PAR_TEMPL_INOUT:
4898 case Common::Assignment::A_FUNCTION_RTEMP:
4899 case Common::Assignment::A_EXT_FUNCTION_RTEMP: {
4900 if (!governor) governor = type;
4901 Type *base_template_type = ass->get_Type();
4902 if (governor) {
4903 TypeCompatInfo info(template_body->get_template_refd_last()
4904 ->get_my_scope()->get_scope_mod(), governor, type,
4905 true, false);
4906 TypeChain l_chain;
4907 TypeChain r_chain;
4908 if (!governor->is_compatible(base_template_type, &info, &l_chain,
4909 &r_chain)) {
4910 if (info.is_subtype_error()) {
4911 derived_reference->error("%s", info.get_subtype_error().c_str());
4912 } else
4913 if (!info.is_erroneous()) {
4914 derived_reference->error("Base template `%s' has incompatible "
4915 "type: `%s' was expected instead of `%s'",
4916 ass->get_fullname().c_str(),
4917 governor->get_typename().c_str(),
4918 base_template_type->get_typename().c_str());
4919 } else {
4920 derived_reference->error("%s", info.get_error_str_str().c_str());
4921 }
4922 // if explicit type specification is omitted
4923 // check the template body against the type of the base template
4924 if (!type) governor = base_template_type;
4925 set_bt = false;
4926 } else {
4927 if (info.needs_conversion())
4928 template_body->set_needs_conversion();
4929 }
4930 } else governor = base_template_type;
4931 break; }
4932 default:
4933 derived_reference->error("Reference to a template was expected instead "
4934 "of %s", ass->get_description().c_str());
4935 goto error;
4936 }
4937 if (set_bt) template_body->set_base_template(ass->get_Template());
4938 return governor;
4939 error:
4940 // drop the erroneous derived_reference to avoid further errors
4941 delete derived_reference;
4942 derived_reference = 0;
4943 return governor;
4944 }
4945
4946 void TemplateInstance::chk_recursions(ReferenceChain& refch)
4947 {
4948 template_body->chk_recursions(refch);
4949 }
4950
4951 bool TemplateInstance::is_string_type(Type::expected_value_t exp_val)
4952 {
4953 switch (get_expr_returntype(exp_val)) {
4954 case Type::T_CSTR:
4955 case Type::T_USTR:
4956 case Type::T_BSTR:
4957 case Type::T_HSTR:
4958 case Type::T_OSTR:
4959 return true;
4960 default:
4961 return false;
4962 }
4963 }
4964
4965 bool TemplateInstance::chk_restriction(const char* definition_name,
3abe9331 4966 template_restriction_t template_restriction, const Location* usage_loc)
970ed795
EL
4967 {
4968 bool needs_runtime_check = false;
4969 if (derived_reference) // if modified
4970 {
4971 Common::Assignment *ass = derived_reference->get_refd_assignment();
4972 switch (ass->get_asstype()) {
4973 case Common::Assignment::A_TEMPLATE:
4974 // already added to template_body as base template by chk_DerivedRef()
4975 needs_runtime_check = template_body->chk_restriction(
3abe9331 4976 definition_name, template_restriction, usage_loc);
970ed795
EL
4977 break;
4978 case Common::Assignment::A_MODULEPAR_TEMP:
4979 case Common::Assignment::A_VAR_TEMPLATE:
4980 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
4981 case Common::Assignment::A_FUNCTION_RTEMP:
4982 case Common::Assignment::A_PAR_TEMPL_IN:
4983 case Common::Assignment::A_PAR_TEMPL_OUT:
4984 case Common::Assignment::A_PAR_TEMPL_INOUT: {
4985 // create a temporary Template to be added as the base template and
4986 // check, remove and delete after checked
4987 if (template_body->get_base_template())
4988 FATAL_ERROR("TemplateInstance::chk_restriction()");
4989 template_body->set_base_template(new Template(derived_reference));
4990 needs_runtime_check = template_body->chk_restriction(
3abe9331 4991 definition_name, template_restriction, usage_loc);
970ed795
EL
4992 delete template_body->get_base_template();
4993 template_body->set_base_template(0);
4994 } break;
4995 default:
4996 break;
4997 }
4998 } else { // simple
4999 needs_runtime_check = template_body->chk_restriction(definition_name,
3abe9331 5000 template_restriction, usage_loc);
970ed795
EL
5001 }
5002 return needs_runtime_check;
5003 }
5004
5005 bool TemplateInstance::has_single_expr()
5006 {
5007 if (derived_reference) return false;
5008 else if (type) return false;
5009 else return template_body->has_single_expr();
5010 }
5011
5012 void TemplateInstance::set_code_section(
5013 GovernedSimple::code_section_t p_code_section)
5014 {
5015 if (derived_reference) derived_reference->set_code_section(p_code_section);
5016 template_body->set_code_section(p_code_section);
5017 }
5018
5019 bool TemplateInstance::needs_temp_ref()
5020 {
5021 if (template_body->get_templatetype() != Template::SPECIFIC_VALUE)
5022 return false;
5023 Value *val = template_body->get_specific_value();
5024 if (val->get_valuetype() == Value::V_REFD) {
5025 FieldOrArrayRefs *refs = val->get_reference()->get_subrefs();
5026 if (!refs) return false;
5027 // We need at least a 2-long reference chain. E.g. "a[0].b". 3.0.4
5028 // can't handle a normal reference following an indexed reference. The
5029 // indexed reference must be on the first place. Code like: "a.b[0].c"
5030 // compiles fine.
5031 if (refs->get_nof_refs() < 2
5032 || refs->get_ref(0)->get_type() != FieldOrArrayRef::ARRAY_REF)
5033 return false;
5034 } else {
5035 return false;
5036 }
5037 return true;
5038 }
5039
5040 void TemplateInstance::generate_code(expression_struct *expr,
5041 template_restriction_t template_restriction)
5042 {
5043 if (derived_reference) {
5044 // preserve the target expression
5045 char *expr_backup = expr->expr;
5046 // reset the space for the target expression
5047 expr->expr = NULL;
5048 derived_reference->generate_code(expr);
5049 // now the C++ equivalent of the base template reference is in expr->expr
5050 const string& tmp_id = template_body->get_temporary_id();
5051 const char *tmp_id_str = tmp_id.c_str();
5052 // create a temporary variable and copy the contents of base template
5053 // into it
5054 expr->preamble = mputprintf(expr->preamble, "%s %s(%s);\n",
5055 template_body->get_my_governor()->get_genname_template(
5056 template_body->get_my_scope()).c_str(), tmp_id_str, expr->expr);
5057 // perform the modifications on the temporary variable
5058 expr->preamble = template_body->generate_code_init(expr->preamble,
5059 tmp_id_str);
5060 // runtime template restriction check
5061 if (template_restriction!=TR_NONE)
5062 expr->preamble = Template::generate_restriction_check_code(
5063 expr->preamble, tmp_id_str, template_restriction);
5064 // the base template reference is no longer needed
5065 Free(expr->expr);
5066 // restore the target expression append the name of the temporary
5067 // variable to it
5068 expr->expr = mputstr(expr_backup, tmp_id_str);
5069 } else template_body->generate_code_expr(expr, template_restriction);
5070 }
5071
51fa56b9 5072 char *TemplateInstance::rearrange_init_code(char *str, Common::Module* usage_mod)
970ed795
EL
5073 {
5074 if (derived_reference) {
51fa56b9 5075 ActualParList *actual_parlist = derived_reference->get_parlist();
970ed795
EL
5076 Common::Assignment *ass = derived_reference->get_refd_assignment();
5077 if (!ass) FATAL_ERROR("TemplateInstance::rearrange_init_code()");
51fa56b9 5078 if (actual_parlist) str = actual_parlist->rearrange_init_code(str, usage_mod);
5079 if (ass->get_asstype() == Common::Assignment::A_TEMPLATE) {
970ed795 5080 Template *t = ass->get_Template();
51fa56b9 5081 FormalParList *formal_parlist = ass->get_FormalParList();
5082 if (formal_parlist) {
970ed795
EL
5083 // the referred template is parameterized
5084 // the embedded referenced templates shall be visited
51fa56b9 5085 str = t->rearrange_init_code(str, usage_mod);
5086 // the constants used for default values have to be initialized now
5087 if (ass->get_my_scope()->get_scope_mod_gen() == usage_mod) {
5088 str = formal_parlist->generate_code_defval(str);
5089 }
970ed795
EL
5090 } else {
5091 // the referred template is not parameterized
5092 // its entire body has to be initialized now
51fa56b9 5093 if (ass->get_my_scope()->get_scope_mod_gen() == usage_mod) {
5094 str = t->generate_code_init(str, t->get_lhs_name().c_str());
5095 }
970ed795
EL
5096 }
5097 }
5098 }
51fa56b9 5099 str = template_body->rearrange_init_code(str, usage_mod);
970ed795
EL
5100 return str;
5101 }
5102
5103 void TemplateInstance::append_stringRepr(string& str) const
5104 {
5105 if (type) {
5106 str += type->get_typename();
5107 str += " : ";
5108 }
5109 if (derived_reference) {
5110 str += "modifies ";
5111 str += derived_reference->get_dispname();
5112 str += " := ";
5113 }
5114 str += template_body->get_stringRepr();
5115 }
5116
5117 void TemplateInstance::dump(unsigned level) const
5118 {
5119 if (type) {
5120 DEBUG(level, "type:");
5121 type->dump(level + 1);
5122 }
5123 if (derived_reference) {
5124 DEBUG(level, "modifies:");
5125 derived_reference->dump(level + 1);
5126 }
5127 template_body->dump(level);
5128 }
5129
5130 Value* TemplateInstance::get_specific_value() const
5131 {
5132 if (type) return NULL;
5133 if (derived_reference) return NULL;
5134 if (template_body->is_length_restricted() || template_body->get_ifpresent())
5135 return NULL;
5136 if (template_body->get_templatetype()!=Template::SPECIFIC_VALUE) return NULL;
5137 return template_body->get_specific_value();
5138 }
5139
5140 Def_Template* TemplateInstance::get_Referenced_Base_Template()
5141 { // it may return 0
5142 if (!get_Template()) return NULL;
5143 Ttcn::Template::templatetype_t tpt = get_Template()->get_templatetype();
5144 if (Ttcn::Template::TEMPLATE_REFD != tpt) return NULL;
5145 Ttcn::Ref_base* refbase = get_Template()->get_reference();
5146 Ttcn::Reference * ref = dynamic_cast<Ttcn::Reference*>(refbase);
5147 if (!ref) return NULL;
5148 Common::Assignment* ass = ref->get_refd_assignment();
5149 Ttcn::Definition* def = dynamic_cast<Ttcn::Definition*>(ass);
5150 if (!def) return NULL;
5151 Ttcn::Def_Template* deftemp = dynamic_cast<Ttcn::Def_Template*>(def);
5152 if (!deftemp) return NULL;
5153
5154 return deftemp;
5155 }
5156
5157}
5158
This page took 0.216102 seconds and 5 git commands to generate.