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