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