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