Merge pull request #47 from BenceJanosSzabo/master
[deliverable/titan.core.git] / compiler2 / ttcn3 / TtcnTemplate.cc
CommitLineData
d44e3c4f 1/******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Baranyi, Botond
12 * Delic, Adam
13 * Kovacs, Ferenc
14 * Raduly, Csaba
15 * Szabados, Kristof
16 * Zalanyi, Balazs Andor
17 * Pandi, Krisztian
18 *
19 ******************************************************************************/
970ed795
EL
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
34namespace 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:
3f84031e 78 u.named_templates = p.u.named_templates->clone();
970ed795
EL
79 break;
80 case INDEXED_TEMPLATE_LIST:
3f84031e 81 u.indexed_templates = p.u.indexed_templates->clone();
970ed795
EL
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:
feade998 746 case Type::T_SEQ_A: case Type::T_SET_A:
970ed795
EL
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:
3abe9331 1565 case ALL_FROM:
1566 // 'all from' clauses not known at compile time are also considered
1567 // as 'AnyOrNone'
970ed795
EL
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:
3abe9331 1597 case ALL_FROM:
970ed795
EL
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;
3abe9331 1604 default:
970ed795
EL
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);
af710487 1749 if (gov) gov = gov->get_parent_type();
1750 if (gov) ret_val->set_my_governor(gov);
970ed795
EL
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);
af710487 1765 if (gov) gov = gov->get_parent_type();
1766 if (gov) ret_val->set_my_governor(gov);
970ed795
EL
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);
af710487 1781 if (gov) gov = gov->get_parent_type();
1782 if (gov) ret_val->set_my_governor(gov);
970ed795
EL
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;
feade998 1826 t->u.ref.ref->get_refd_assignment(true); // make sure the parameter list is checked
970ed795
EL
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 }
1873end:
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 }
a38c6d4c 1985
1986 // check for subreferences in the 'all from' target
1987 FieldOrArrayRefs* subrefs = ref->get_subrefs();
1988 if (NULL != subrefs) {
a38c6d4c 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
970ed795
EL
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) {
970ed795
EL
2005 case Common::Assignment::A_TEMPLATE: {
2006 Template *tpl = ass->get_Template();
2007 // tpl is the template whose name appears after the "all from"
3abe9331 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;
970ed795 2042 }
3abe9331 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;
970ed795
EL
2061 }
2062 }
3abe9331 2063 else {
2064 // one of the array indexes is a reference => cannot flatten
2065 can_flatten = false;
970ed795 2066 }
3abe9331 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();
970ed795
EL
2117 }
2118 }
3abe9331 2119 }
2120 if (NULL != tpl) { // tpl is set to null if an error occurs
970ed795 2121 if (can_flatten) {
3abe9331 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) {
970ed795 2136 Template *orig = tpl->get_temp_byIndex(ti);
3abe9331 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; }
970ed795 2174
3abe9331 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;
970ed795
EL
2202 }
2203 }
3abe9331 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 }
970ed795
EL
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();
3abe9331 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 }
a38c6d4c 2304 }
2305 }
3abe9331 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; }
970ed795 2325
3abe9331 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 }
970ed795
EL
2332 if (killer) delete t;
2333 break; }
2334
3abe9331 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:
970ed795
EL
2339 case Common::Assignment::A_PAR_TEMPL_IN:
2340 case Common::Assignment::A_PAR_TEMPL_INOUT:
3abe9331 2341 case Common::Assignment::A_PAR_TEMPL_OUT:
970ed795
EL
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:
3abe9331 2346 case Common::Assignment::A_PAR_VAL_INOUT:
2347 case Common::Assignment::A_PAR_VAL_OUT:
a38c6d4c 2348 case Common::Assignment::A_FUNCTION_RVAL:
2349 case Common::Assignment::A_EXT_FUNCTION_RVAL: {
3abe9331 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)
970ed795
EL
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 }
3abe9331 2649 return mputprintf(str, "%s.check_restriction(%s%s);\n", name, tr_name,
2650 (omit_in_value_list ? ", NULL, TRUE" : ""));
970ed795
EL
2651 }
2652
2653 // embedded templates -> check needed only for case of TR_OMIT
2654 bool Template::chk_restriction_named_list(const char* definition_name,
3abe9331 2655 map<string, void>& checked_map, size_t needed_checked_cnt,
2656 const Location* usage_loc)
970ed795
EL
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)) {
3abe9331 2667 bool nrc = tmpl->chk_restriction(definition_name, TR_OMIT, usage_loc);
970ed795
EL
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,
3abe9331 2674 checked_map, needed_checked_cnt, usage_loc);
970ed795
EL
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,
3abe9331 2691 template_restriction_t template_restriction, const Location* usage_loc)
970ed795
EL
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,
3abe9331 2704 template_restriction, usage_loc);
970ed795
EL
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,
3abe9331 2756 template_restriction_t template_restriction,
2757 const Location* usage_loc)
970ed795
EL
2758 {
2759 bool needs_runtime_check = false;
3abe9331 2760 bool erroneous = false;
970ed795
EL
2761 switch (template_restriction) {
2762 case TR_NONE:
2763 break;
2764 case TR_OMIT:
2765 case TR_VALUE:
3abe9331 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 }
970ed795
EL
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,
3abe9331 2782 template_restriction, usage_loc);
970ed795
EL
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: {
3abe9331 2791 bool nrc = chk_restriction_refd(definition_name, template_restriction,
2792 usage_loc);
970ed795
EL
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)->
3abe9331 2798 chk_restriction(definition_name, TR_OMIT, usage_loc);
970ed795
EL
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()->
3abe9331 2820 chk_restriction(definition_name, TR_OMIT, usage_loc);
970ed795
EL
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,
3abe9331 2828 checked_map, needed_checked_cnt, usage_loc);
970ed795
EL
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()->
3abe9331 2836 chk_restriction(definition_name, TR_OMIT, usage_loc);
970ed795
EL
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:
3abe9331 2846 usage_loc->error("Restriction on %s does not allow usage of %s",
2847 definition_name, get_templatetype_str());
2848 erroneous = true;
970ed795
EL
2849 break;
2850 }
2851 break;
2852 case TR_PRESENT:
3abe9331 2853 if (is_ifpresent) {
2854 usage_loc->error("Restriction on %s does not allow usage of `ifpresent'",
2855 definition_name);
2856 erroneous = true;
2857 }
970ed795
EL
2858 switch(templatetype) {
2859 case TEMPLATE_REFD: {
3abe9331 2860 bool nrc = chk_restriction_refd(definition_name, template_restriction,
2861 usage_loc);
970ed795
EL
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)->
3abe9331 2867 chk_restriction(definition_name, template_restriction, usage_loc);
970ed795
EL
2868 needs_runtime_check = needs_runtime_check || nrc;
2869 }
2870 break;
3abe9331 2871 case COMPLEMENTED_LIST:
970ed795
EL
2872 // some basic check, always needs runtime check
2873 needs_runtime_check = true;
3abe9331 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;
970ed795
EL
2889 }
2890 }
3abe9331 2891 break;
970ed795
EL
2892 case OMIT_VALUE:
2893 case ANY_OR_OMIT:
3abe9331 2894 usage_loc->error("Restriction on %s does not allow usage of %s",
2895 definition_name, get_templatetype_str());
2896 erroneous = true;
970ed795
EL
2897 break;
2898 default:
2899 break; // all others are ok
2900 }
2901 break;
2902 default:
2903 FATAL_ERROR("Template::chk_restriction()");
2904 }
3abe9331 2905 if (erroneous && usage_loc != this) {
2906 // display the template's location, too
2907 note("Referenced template is here");
2908 }
970ed795
EL
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)
2861f5cd 3011 str = u.specific_value->rearrange_init_code(str, my_scope->get_scope_mod_gen());
970ed795
EL
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)
51fa56b9 3019 str = rearrange_init_code_invoke(str, my_scope->get_scope_mod_gen());
970ed795
EL
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)
2861f5cd 3043 str = u.value_range->rearrange_init_code(str, my_scope->get_scope_mod_gen());
970ed795
EL
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_ERROR:
3057 case TEMPLATE_NOTUSED:
3058 // "default"
3059 FATAL_ERROR("Template::generate_code_init()");
3060 }
3061 if (length_restriction) {
3062 if (get_code_section() == CS_POST_INIT)
2861f5cd 3063 str = length_restriction->rearrange_init_code(str, my_scope->get_scope_mod_gen());
970ed795
EL
3064 str = length_restriction->generate_code_init(str, name);
3065 }
3066 if (is_ifpresent) str = mputprintf(str, "%s.set_ifpresent();\n", name);
3067 if (err_descr) {
3068 str = mputprintf(str, "%s.set_err_descr(&%s_err_descr);\n", name, name);
3069 }
3070 return str;
3071 }
3072
51fa56b9 3073 char *Template::rearrange_init_code(char *str, Common::Module* usage_mod)
970ed795
EL
3074 {
3075 switch (templatetype) {
3076 case SPECIFIC_VALUE:
2861f5cd 3077 str = u.specific_value->rearrange_init_code(str, usage_mod);
970ed795
EL
3078 break;
3079 case TEMPLATE_REFD:
51fa56b9 3080 str = rearrange_init_code_refd(str, usage_mod);
970ed795
EL
3081 break;
3082 case TEMPLATE_INVOKE:
51fa56b9 3083 str = rearrange_init_code_invoke(str, usage_mod);
970ed795
EL
3084 break;
3085 case TEMPLATE_LIST:
3086 case VALUE_LIST:
3087 case COMPLEMENTED_LIST:
3088 case SUPERSET_MATCH:
3089 case SUBSET_MATCH:
3090 case PERMUTATION_MATCH:
3091 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
51fa56b9 3092 str = u.templates->get_t_byIndex(i)->rearrange_init_code(str, usage_mod);
970ed795
EL
3093 break;
3094 case NAMED_TEMPLATE_LIST:
3095 for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++)
3096 str = u.named_templates->get_nt_byIndex(i)->get_template()
51fa56b9 3097 ->rearrange_init_code(str, usage_mod);
970ed795
EL
3098 break;
3099 case INDEXED_TEMPLATE_LIST:
3100 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++)
3101 str = u.indexed_templates->get_it_byIndex(i)->get_template()
51fa56b9 3102 ->rearrange_init_code(str, usage_mod);
970ed795
EL
3103 break;
3104 case VALUE_RANGE:
2861f5cd 3105 str = u.value_range->rearrange_init_code(str, usage_mod);
970ed795
EL
3106 break;
3107 default:
3108 break;
3109 }
2861f5cd 3110 if (length_restriction) str = length_restriction->rearrange_init_code(str, usage_mod);
970ed795
EL
3111 return str;
3112 }
3113
3114 bool Template::use_single_expr_for_init()
3115 {
3116 Template *t_last = get_template_refd_last();
3117 // return false in case of unfoldable references
3118 if (t_last->templatetype == TEMPLATE_REFD) return false;
3119 // return false if t_last is in a different module
3120 if (t_last->my_scope->get_scope_mod_gen() != my_scope->get_scope_mod_gen())
3121 return false;
3122 // return false if t_last cannot be represented by a single expression
3123 if (!t_last->has_single_expr()) return false;
3124 // return true if t_last is a generic wildcard, string pattern, etc.
3125 if (t_last->templatetype != SPECIFIC_VALUE) return true;
3126 // examine the specific value
3127 Value *v_last = t_last->u.specific_value->get_value_refd_last();
3128 switch (v_last->get_valuetype()) {
3129 case Value::V_EXPR:
3130 // do not calculate expressions again
3131 return false;
3132 case Value::V_REFD: {
3133 // v_last is an unfoldable value reference
3134 // the scope of the definition that v_last refers to
3135 Scope *v_scope =
3136 v_last->get_reference()->get_refd_assignment()->get_my_scope();
3137 for (Scope *t_scope = my_scope; t_scope;
3138 t_scope = t_scope->get_parent_scope()) {
3139 // return true if the referred definition is in the same scope
3140 // as this or in one of the parent scopes of this
3141 if (t_scope == v_scope) return true;
3142 }
3143 // otherwise return false
3144 return false; }
3145 default:
3146 // return true only if v_last is defined in the same module as this
3147 return v_last->get_my_scope()->get_scope_mod_gen() ==
3148 my_scope->get_scope_mod_gen();
3149 }
3150 }
3151
3152 char *Template::generate_code_init_refd(char *str, const char *name)
3153 {
3154 if (use_single_expr_for_init() && has_single_expr()) {
3155 str = mputprintf(str, "%s = %s;\n", name,
3156 get_single_expr(false).c_str());
3157 } else {
3158 expression_struct expr;
3159 Code::init_expr(&expr);
3160 bool use_ref_for_codegen = true;
3161 if (get_code_section() == CS_POST_INIT) {
3162 // the referencing template is a part of a non-parameterized template
3163 Common::Assignment *ass = u.ref.ref->get_refd_assignment();
51fa56b9 3164 if (ass->get_asstype() == Common::Assignment::A_TEMPLATE) {
970ed795 3165 // the reference points to (a field of) a template
970ed795
EL
3166 if (ass->get_FormalParList()) {
3167 // the referred template is parameterized
3168 // generate the initialization sequence first for all dependent
3169 // non-parameterized templates
51fa56b9 3170 str = rearrange_init_code_refd(str, my_scope->get_scope_mod_gen());
3171 } else if (ass->get_my_scope()->get_scope_mod_gen() ==
3172 my_scope->get_scope_mod_gen()) {
970ed795
EL
3173 // the referred template is non-parameterized
3174 // use a different algorithm for code generation
3175 str = generate_rearrange_init_code_refd(str, &expr);
3176 use_ref_for_codegen = false;
3177 }
3178 }
3179 }
3180 if (use_ref_for_codegen) u.ref.ref->generate_code_const_ref(&expr);
3181 if (expr.preamble || expr.postamble) {
3182 // the expressions within reference need temporary objects
3183 str = mputstr(str, "{\n");
3184 str = mputstr(str, expr.preamble);
3185 if (use_runtime_2 && get_needs_conversion()) {
3186 const string& tmp_id = get_temporary_id();
3187 const char *tmp_id_str = tmp_id.c_str();
3188 Type *my_gov = my_governor->get_type_refd_last();
3189 Type *refd_gov = u.ref.ref->get_refd_assignment()->get_Type()
3190 ->get_type_refd_last();
3191 if (!my_gov || !refd_gov)
3192 FATAL_ERROR("Template::generate_code_init_refd()");
3193 str = mputprintf(str,
3194 "%s %s;\n"
3195 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
3196 "and `%s' are not compatible at run-time\");\n",
3197 my_gov->get_genname_template(my_scope).c_str(), tmp_id_str,
3198 TypeConv::get_conv_func(refd_gov, my_gov, get_my_scope()
3199 ->get_scope_mod()).c_str(), tmp_id_str, expr.expr, my_gov
3200 ->get_typename().c_str(), refd_gov->get_typename().c_str());
3201 str = mputprintf(str, "%s = %s;\n", name, tmp_id_str);
3202 } else {
3203 str = mputprintf(str, "%s = %s;\n", name, expr.expr);
3204 }
3205 str = mputstr(str, expr.postamble);
3206 str = mputstr(str, "}\n");
3207 } else {
3208 // the reference does not need temporary objects
3209 if (use_runtime_2 && get_needs_conversion()) {
3210 const string& tmp_id = get_temporary_id();
3211 const char *tmp_id_str = tmp_id.c_str();
3212 Type *my_gov = my_governor->get_type_refd_last();
3213 Type *refd_gov = u.ref.ref->get_refd_assignment()->get_Type()
3214 ->get_type_refd_last();
3215 if (!my_gov || !refd_gov)
3216 FATAL_ERROR("Template::generate_code_init_refd()");
3217 str = mputprintf(str,
3218 "%s %s;\n"
3219 "if (!%s(%s, %s)) TTCN_error(\"Values or templates of types `%s' "
3220 "and `%s' are not compatible at run-time\");\n",
3221 my_gov->get_genname_template(my_scope).c_str(), tmp_id_str,
3222 TypeConv::get_conv_func(refd_gov, my_gov, get_my_scope()
3223 ->get_scope_mod()).c_str(), tmp_id_str, expr.expr, my_gov
3224 ->get_typename().c_str(), refd_gov->get_typename().c_str());
3225 str = mputprintf(str, "%s = %s;\n", name, tmp_id_str);
3226 } else {
3227 str = mputprintf(str, "%s = %s;\n", name, expr.expr);
3228 }
3229 }
3230 Code::free_expr(&expr);
3231 }
3232 return str;
3233 }
3234
3235 char *Template::generate_code_init_invoke(char *str, const char *name)
3236 {
3237 expression_struct expr;
3238 Code::init_expr(&expr);
3239 expr.expr = mputprintf(expr.expr, "%s = ", name);
3240 generate_code_expr_invoke(&expr);
3241 return Code::merge_free_expr(str, &expr);
3242 }
3243
3244 char *Template::generate_rearrange_init_code_refd(char *str,
3245 expression_struct *expr)
3246 {
3247 /** Initially we can assume that:
3248 * - this is a referenced template and a part of a non-parameterized
3249 * template
3250 * - u.ref.ref points to (a field of) a non-parameterized template within
3251 * the same module as \a this.
3252 * - this ensures that the do-while loop will run at least twice (i.e. the
3253 * first continue statement will be reached in the first iteration) */
3254 stack<FieldOrArrayRef> refstack;
3255 Template *t = this;
3256 // first try to find the smallest dependent template
3257 for ( ; ; ) {
3258 if (t->templatetype == TEMPLATE_REFD) {
3259 Common::Assignment *ass = t->u.ref.ref->get_refd_assignment();
3260 /** Don't follow the reference if:
3261 * - the referenced definition is not a template
3262 * - the referenced template is parameterized or
3263 * - the referenced template is in different module */
3264 if (ass->get_asstype() == Common::Assignment::A_TEMPLATE &&
3265 ass->get_FormalParList() == 0 &&
3266 ass->get_my_scope()->get_scope_mod_gen() ==
3267 my_scope->get_scope_mod_gen()) {
3268 // accumulate the sub-references of the referred reference
3269 FieldOrArrayRefs *subrefs = t->u.ref.ref->get_subrefs();
3270 if (subrefs) {
3271 for (size_t i = subrefs->get_nof_refs(); i > 0; i--)
3272 refstack.push(subrefs->get_ref(i - 1));
3273 }
3274 // jump to the referred top-level template
3275 t = ass->get_Template();
3276 // start the iteration from the beginning
3277 continue;
3278 // stop otherwise: the reference cannot be followed
3279 } else break;
3280 }
3281 // stop if there are no sub-references
3282 if (refstack.empty()) break;
3283 // take the topmost sub-reference
3284 FieldOrArrayRef *subref = refstack.top();
3285 if (subref->get_type() == FieldOrArrayRef::FIELD_REF) {
3286 if (t->templatetype != NAMED_TEMPLATE_LIST) break;
3287 // the field reference can be followed
3288 t = t->u.named_templates->get_nt_byName(*subref->get_id())
3289 ->get_template();
3290 } else {
3291 // trying to follow an array reference
3292 if (t->templatetype != TEMPLATE_LIST) break;
3293 Value *array_index = subref->get_val()->get_value_refd_last();
3294 if (array_index->get_valuetype() != Value::V_INT) break;
3295 // the index is available at compilation time
3296 Int index = array_index->get_val_Int()->get_val();
3297 // index transformation in case of arrays
3298 if (t->my_governor->get_typetype() == Type::T_ARRAY)
3299 index -= t->my_governor->get_dimension()->get_offset();
3300 t = t->get_listitem_byIndex(index);
3301 }
3302 // the topmost sub-reference was processed
3303 // it can be erased from the stack
3304 refstack.pop();
3305 }
3306 // the smallest dependent template is now in t
3307 // generate the initializer sequence for t
3308 str = t->generate_code_init(str, t->get_lhs_name().c_str());
3309 // the equivalent C++ code of the referenced template is composed of the
3310 // genname of t and the remained sub-references in refstack
3311 expr->expr = mputstr(expr->expr, t->get_genname_own(my_scope).c_str());
3312 while (!refstack.empty()) {
3313 FieldOrArrayRef *subref = refstack.pop();
3314 if (subref->get_type() == FieldOrArrayRef::FIELD_REF) {
3315 expr->expr = mputprintf(expr->expr, ".%s()",
3316 subref->get_id()->get_name().c_str());
3317 } else {
3318 expr->expr = mputc(expr->expr, '[');
3319 subref->get_val()->generate_code_expr(expr);
3320 expr->expr = mputc(expr->expr, ']');
3321 }
3322 }
3323 return str;
3324 }
3325
3326 bool Template::compile_time() const
3327 {
3328 switch (templatetype) {
3329 case ALL_FROM:
3330 case VALUE_LIST_ALL_FROM:
3331 return false;
3332 case TEMPLATE_ERROR: /**< erroneous template */
3333 case TEMPLATE_NOTUSED: /**< not used symbol (-) */
3334 case OMIT_VALUE: /**< omit */
3335 case ANY_VALUE: /**< any value (?) */
3336 case ANY_OR_OMIT: /**< any or omit (*) */
3337 case SPECIFIC_VALUE: /**< specific value */
3338 case TEMPLATE_REFD: /**< reference to another template */
3339 case VALUE_RANGE: /**< value range match */
3340 case BSTR_PATTERN: /**< bitstring pattern */
3341 case HSTR_PATTERN: /**< hexstring pattern */
3342 case OSTR_PATTERN: /**< octetstring pattern */
3343 case CSTR_PATTERN: /**< character string pattern */
3344 case USTR_PATTERN: /**< universal charstring pattern */
3345 case TEMPLATE_INVOKE:
3346 // Simple templates can be computed at compile time
3347 return true;
3348
3349 // "Complex" templates need to look at all elements
3350 case TEMPLATE_LIST:
3351 case VALUE_LIST:
3352 case COMPLEMENTED_LIST:
3353 case SUPERSET_MATCH:
3354 case SUBSET_MATCH:
3355 case PERMUTATION_MATCH:
3356 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
3357 if (u.templates->get_t_byIndex(i)->compile_time()) continue;
3358 else return false;
3359 return true;
3360 case NAMED_TEMPLATE_LIST:
3361 for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++)
3362 if (!u.named_templates->get_nt_byIndex(i)->get_template()->compile_time())
3363 return false;
3364 return true;
3365 case INDEXED_TEMPLATE_LIST:
3366 for (size_t i = 0; i <u.indexed_templates->get_nof_its(); i++)
3367 if (!u.indexed_templates->get_it_byIndex(i)->get_template()->compile_time())
3368 return false;
3369 return true;
3370 }
3371
3372 return true; // not reached
3373 }
3374
3375 char *Template::generate_code_init_seof(char *str, const char *name)
3376 {
3377 switch (templatetype) {
3378 case TEMPLATE_LIST: {
3379 size_t nof_ts = u.templates->get_nof_ts();
3380 if (nof_ts == 0) {
3381 str = mputprintf(str, "%s = NULL_VALUE;\n", name);
3382 break;
3383 }
3384
3385 // nof_ts > 0
3386 Type *t_last = my_governor->get_type_refd_last();
3387 Int index_offset;
3388 if (t_last->get_typetype() == Type::T_ARRAY) {
3389 // take the start index from the array dimension
3390 index_offset = t_last->get_dimension()->get_offset();
3391 } else {
3392 // indexing always starts from zero
3393 index_offset = 0;
3394 }
3395
3396 const string& oftype_name =
3397 t_last->get_ofType()->get_genname_template(my_scope);
3398 const char *oftype_name_str = oftype_name.c_str();
3399
3400 ReferenceChain refch (this, "While searching template");
3401 if (!flattened || my_scope->get_statementblock_scope()) { // this "if" may be redundant if all non-var templates are flattened
3402 str = mputstr(str, "// this is a var template\n");
3403
3404 if (compile_time()) goto compile_time;
3405 // run-time, variable sized init
3406
3407 // This is a record-of var template, like this:
3408 // var template rec_of_int vt_r := {
3409 // 1, 2, 3, permutation(10, all from x, 20), 4, 5 }
3410 // ^^^^^^^--- these ------------------------^^^^^
3411 // are known at compile time, but the length of the "all from"
3412 // is only known at run time.
3413 // Collect the indices where there is an "all from".
3414 dynamic_array<int> variables;
3415 size_t fixed_part = 0;
3416 if (has_permutation) {
3417 for (size_t i = 0; i < nof_ts; i++) {
3418 Template *t = u.templates->get_t_byIndex(i);
3419 if (t->templatetype == PERMUTATION_MATCH) {
3420 size_t num_p = t->u.templates->get_nof_ts();
3421 // t->u.templates is 2: "hello" and all from ...
3422 for (size_t j = 0; j < num_p; ++j) {
3423 Template *subt = t->u.templates->get_t_byIndex(j);
3424 if (subt->templatetype == ALL_FROM) {
3425 variables.add(j);
3426 }
3427 else fixed_part++;
3428 }
3429 }
3430 else fixed_part++;
3431 }
3432
3433 char* str_preamble = 0;
3434 char* str_set_size = mputprintf(0, "%s.set_size(%lu", name,
3435 (unsigned long)fixed_part);
3436
3437 // variable part
3438 for (size_t i = 0; i < nof_ts; i++) {
3439 Template *t = u.templates->get_t_byIndex(i);
3440 for (size_t k = 0, v = variables.size(); k < v; ++k) {
3441 if (t->templatetype != PERMUTATION_MATCH) continue; // ?? really nothing to do ??
3442 Template *subt = t->u.templates->get_t_byIndex(variables[k]);
3443 if (subt->templatetype == ALL_FROM) {
3444 Value *refv = subt->u.all_from->u.specific_value;
3445 // don't call get_Value(), it rips out the value from the template
3446
3447 if (refv->get_valuetype()!=Value::V_REFD) FATAL_ERROR("%s", __FUNCTION__);
3448 Common::Reference *ref = refv->get_reference();
3449 FieldOrArrayRefs *subrefs = ref->get_subrefs();
3450 Common::Assignment *ass = ref->get_refd_assignment();
3451
3452 str_set_size = mputstrn(str_set_size, " + ", 3);
3453
3454 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3455 if (ref_pard) {
3456 // in case of parametrised references:
3457 // - temporary parameters need to be declared (stored in str_preamble)
3458 // - the same temporary needs to be used at each call (generate_code_cached call)
3459 expression_struct expr;
3460 Code::init_expr(&expr);
3461
3462 ref_pard->generate_code_cached(&expr);
3463 str_set_size = mputprintf(str_set_size, "%s", expr.expr);
3464 if (expr.preamble)
3465 str_preamble = mputstr(str_preamble, expr.preamble);
3466
3467 Code::free_expr(&expr);
3468 }
3469 else {
3470 str_set_size = mputstr (str_set_size, ass->get_id().get_name().c_str());
3471 if (subrefs) {
3472 expression_struct expr;
3473 Code::init_expr(&expr);
3474
3475 subrefs->generate_code(&expr, ass);
3476 str_set_size = mputprintf(str_set_size, "%s", expr.expr);
3477
3478 Code::free_expr(&expr);
3479 }
3480 }
3abe9331 3481
3482 switch(ass->get_asstype()) {
3483 case Common::Assignment::A_CONST:
3484 case Common::Assignment::A_EXT_CONST:
3485 case Common::Assignment::A_MODULEPAR:
3486 case Common::Assignment::A_VAR:
3487 case Common::Assignment::A_PAR_VAL_IN:
3488 case Common::Assignment::A_PAR_VAL_OUT:
3489 case Common::Assignment::A_PAR_VAL_INOUT:
3490 case Common::Assignment::A_FUNCTION_RVAL:
3491 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3492 if (ass->get_Type()->field_is_optional(subrefs)) {
3493 str_set_size = mputstrn(str_set_size, "()", 2);
3494 }
3495 break;
3496 default:
3497 break;
3498 }
3499
970ed795
EL
3500 str_set_size = mputstr(str_set_size, ".n_elem()");
3501 }
3502 }
3503 }
3504
3505 str = mputstr(str, str_preamble);
3506 str = mputstr(str, str_set_size);
3507
3508 Free(str_preamble);
3509 Free(str_set_size);
3510
3511 str = mputstrn(str, ");\n", 3); // finally done set_size
3abe9331 3512
970ed795
EL
3513 size_t index = 0;
3514 string skipper, hopper;
3515 for (size_t i = 0; i < nof_ts; i++) {
3516 Template *t = u.templates->get_t_byIndex(i);
3517 switch (t->templatetype) {
3518 case ALL_FROM: {
3519 break; }
3520 case PERMUTATION_MATCH: {
3521 size_t nof_perm_ts = t->u.templates->get_nof_ts();
3522 for (size_t j = 0; j < nof_perm_ts; j++) {
3523 Int ix(index_offset + index + j);
3524 Template *permut_elem = t->u.templates->get_t_byIndex(j);
3525 if (permut_elem->templatetype == ALL_FROM) {
3526 expression_struct expr;
3527 Code::init_expr(&expr);
3528 switch (permut_elem->u.all_from->templatetype) {
3529 case SPECIFIC_VALUE: {
3530 Value *spec = permut_elem->u.all_from->u.specific_value;
3531 switch (spec->get_valuetype()) {
3532 case Common::Value::V_REFD: {
3533 Common::Reference *ref = spec->get_reference();
3534
3535 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3536 if (ref_pard)
3537 ref_pard->generate_code_cached(&expr);
3538 else
3539 ref->generate_code(&expr);
3abe9331 3540
3541 Common::Assignment* ass = ref->get_refd_assignment();
3542 switch(ass->get_asstype()) {
3543 case Common::Assignment::A_CONST:
3544 case Common::Assignment::A_EXT_CONST:
3545 case Common::Assignment::A_MODULEPAR:
3546 case Common::Assignment::A_VAR:
3547 case Common::Assignment::A_PAR_VAL_IN:
3548 case Common::Assignment::A_PAR_VAL_OUT:
3549 case Common::Assignment::A_PAR_VAL_INOUT:
3550 case Common::Assignment::A_FUNCTION_RVAL:
3551 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3552 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
3553 expr.expr = mputstrn(expr.expr, "()", 2);
3554 }
3555 break;
3556 default:
3557 break;
3558 }
970ed795
EL
3559
3560 break; }
3561 default:
3562 FATAL_ERROR("vtype %d", spec->get_valuetype());
3563 break;
3564 }
3565 break; }
3566
3567
3568 default:
3569 FATAL_ERROR("ttype %d", permut_elem->u.all_from->templatetype);
3570 break;
3571 }
3572 str = mputprintf(str,
3573 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3574 expr.expr);
3575
3576 str = permut_elem->generate_code_init_seof_element(str, name,
3577 (Int2string(ix) + skipper + " + i_i").c_str(),
3578 oftype_name_str);
3579
3580 str = mputstrn(str, "}\n", 2);
3581 skipper += "-1+";
3582 skipper += expr.expr;
3583 skipper += ".n_elem() /* 3005 */ ";
3584 Code::free_expr(&expr);
3585 }
3586 else {
3587 str = permut_elem->generate_code_init_seof_element(str, name,
3588 (Int2string(ix) + skipper).c_str(), oftype_name_str);
3589 }
3590 }
3591 // do not consider index_offset in case of permutation indicators
3592 str = mputprintf(str, "%s.add_permutation(%lu%s, %lu%s);\n", name,
3593 (unsigned long)index, hopper.c_str(),
3594 (unsigned long)(index + nof_perm_ts - 1), skipper.c_str());
3595 hopper = skipper;
3596 t->set_code_generated();
3597 index += nof_perm_ts;
3598 break; }
3599
3600 default:
3601 str = t->generate_code_init_seof_element(str, name,
3602 (Int2string(index_offset + index) + skipper).c_str(), oftype_name_str);
3603 // no break
3604 case TEMPLATE_NOTUSED:
3605 index++;
3606 break;
3607 }
3608 }
3609
3610 break;
3611
3612 }
3613
3614
3615 if (!has_permutation && has_allfrom()) {
3616 for (size_t i = 0; i < nof_ts; i++) {
3617 Template *t = u.templates->get_t_byIndex(i);
3618 if (t->templatetype == ALL_FROM) {
3619 variables.add(i);
3620 }
3621 else {
3622 fixed_part++;
3623 }
3624 }
3625 char* str_preamble = 0;
3626 char* str_set_size = mputprintf(0, "%s.set_size(%lu", name,
3627 (unsigned long)fixed_part);
3628
3f84031e 3629 // variable part
3630 for (size_t i = 0, v = variables.size(); i < v; ++i) {
3631 Template *t = u.templates->get_t_byIndex(variables[i]);
970ed795
EL
3632 if (t->templatetype == ALL_FROM) {
3633 Value *refv = t->u.all_from->u.specific_value;
3634 // don't call get_Value(), it rips out the value from the template
3635 if (refv->get_valuetype()!=Value::V_REFD) FATAL_ERROR("%s", __FUNCTION__);
3636 Common::Reference *ref = refv->get_reference();
3637 FieldOrArrayRefs *subrefs = ref->get_subrefs();
3638 Common::Assignment *ass = ref->get_refd_assignment();
3639 str_set_size = mputstrn(str_set_size, " + ", 3);
3640 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3641 if (ref_pard) {
3642 // in case of parametrised references:
3643 // - temporary parameters need to be declared (stored in str_preamble)
3644 // - the same temporary needs to be used at each call (generate_code_cached call)
3645 expression_struct expr;
3646 Code::init_expr(&expr);
3647
3648 ref_pard->generate_code_cached(&expr);
3649 str_set_size = mputprintf(str_set_size, "%s", expr.expr);
3650 if (expr.preamble)
3651 str_preamble = mputstr(str_preamble, expr.preamble);
3652 Code::free_expr(&expr);
3653 }
3654 else {
3655 str_set_size = mputstr (str_set_size, ass->get_id().get_name().c_str());
3656 if (subrefs) {
3657 expression_struct expr;
3658 Code::init_expr(&expr);
3659 subrefs->generate_code(&expr, ass);
3660 str_set_size = mputprintf(str_set_size, "%s", expr.expr);
3661 Code::free_expr(&expr);
3662 }
3663 }
3abe9331 3664
3665 switch(ass->get_asstype()) {
3666 case Common::Assignment::A_CONST:
3667 case Common::Assignment::A_EXT_CONST:
3668 case Common::Assignment::A_MODULEPAR:
3669 case Common::Assignment::A_VAR:
3670 case Common::Assignment::A_PAR_VAL_IN:
3671 case Common::Assignment::A_PAR_VAL_OUT:
3672 case Common::Assignment::A_PAR_VAL_INOUT:
3673 case Common::Assignment::A_FUNCTION_RVAL:
3674 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3675 if (ass->get_Type()->field_is_optional(subrefs)) {
3676 str_set_size = mputstrn(str_set_size, "()", 2);
3677 }
3678 break;
3679 default:
3680 break;
3681 }
3682
970ed795
EL
3683 str_set_size = mputstr(str_set_size, ".n_elem()");
3684 }
3685 }
3f84031e 3686 str = mputstr(str, str_preamble);
3687 str = mputstr(str, str_set_size);
3688 Free(str_preamble);
3689 Free(str_set_size);
3690 str = mputstrn(str, ");\n", 3); // finally done set_size
3691
3692 size_t index = 0;
3693 string skipper;
3694 for (size_t i = 0; i < nof_ts; i++) {
3695 Template *t = u.templates->get_t_byIndex(i);
3696 Int ix(index_offset + i);
3697 switch (t->templatetype) {
3698 case ALL_FROM: {
970ed795
EL
3699 expression_struct expr;
3700 Code::init_expr(&expr);
3701 switch (t->u.all_from->templatetype) {
3702 case SPECIFIC_VALUE: {
3703 Value *spec = t->u.all_from->u.specific_value;
3704 switch (spec->get_valuetype()) {
3705 case Common::Value::V_REFD: {
3706 Common::Reference *ref = spec->get_reference();
3707 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3708 if (ref_pard)
3709 ref_pard->generate_code_cached(&expr);
3710 else
3711 ref->generate_code(&expr);
3abe9331 3712
3713 Common::Assignment* ass = ref->get_refd_assignment();
3714 switch(ass->get_asstype()) {
3715 case Common::Assignment::A_CONST:
3716 case Common::Assignment::A_EXT_CONST:
3717 case Common::Assignment::A_MODULEPAR:
3718 case Common::Assignment::A_VAR:
3719 case Common::Assignment::A_PAR_VAL_IN:
3720 case Common::Assignment::A_PAR_VAL_OUT:
3721 case Common::Assignment::A_PAR_VAL_INOUT:
3722 case Common::Assignment::A_FUNCTION_RVAL:
3723 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3724 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
3725 expr.expr = mputstrn(expr.expr, "()", 2);
3726 }
3727 break;
3728 default:
3729 break;
3730 }
3731
970ed795
EL
3732 break; }
3733 default:
3734 FATAL_ERROR("vtype %d", spec->get_valuetype());
3735 break;
3736 }
3737 break; }
3738 default: {
3739 FATAL_ERROR("ttype %d", t->u.all_from->templatetype);
3740 break; }
3741 }
3742 str = mputprintf(str,
3743 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3744 expr.expr);
3745 str = t->generate_code_init_seof_element(str, name,
3746 (Int2string(ix) + skipper + " + i_i").c_str(),
3747 oftype_name_str);
3748 str = mputstrn(str, "}\n", 2);
3749 skipper += "-1+";
3750 skipper += expr.expr;
3751 skipper += ".n_elem() ";
3752 Code::free_expr(&expr);
3753 t->set_code_generated();
3754 ++index;
3755 break; }
3756 default: {
970ed795
EL
3757 str = t->generate_code_init_seof_element(str, name,
3758 (Int2string(index_offset + index) + skipper).c_str(), oftype_name_str);
3759 // no break
3760 case TEMPLATE_NOTUSED:
3761 ++index;
3762 break; }
3763 }
3764 }
3f84031e 3765 break;
970ed795
EL
3766 }
3767
3768 // else carry on
3769 }
3770compile_time:
3771 // setting the size first
3772 if (!has_allfrom())
3773 str = mputprintf(str, "%s.set_size(%lu);\n", name, (unsigned long) get_nof_listitems());
3774 // determining the index offset based on the governor
3775
3776 size_t index = 0;
3777 for (size_t i = 0; i < nof_ts; i++) {
3778 Template *t = u.templates->get_t_byIndex(i);
3779 switch (t->templatetype) {
3780 case PERMUTATION_MATCH: {
3781 size_t nof_perm_ts = t->u.templates->get_nof_ts();
3782 for (size_t j = 0; j < nof_perm_ts; j++) {
3783 Int ix(index_offset + index + j);
3784 str = t->u.templates->get_t_byIndex(j)
3785 ->generate_code_init_seof_element(str, name,
3786 Int2string(ix).c_str(), oftype_name_str);
3787 }
3788 // do not consider index_offset in case of permutation indicators
3789 str = mputprintf(str, "%s.add_permutation(%lu, %lu);\n", name,
3790 (unsigned long)index, (unsigned long) (index + nof_perm_ts - 1));
3791 t->set_code_generated();
3792 index += nof_perm_ts;
3793 break; }
3794
3795 default:
3796 str = t->generate_code_init_seof_element(str, name,
3797 Int2string(index_offset + index).c_str(), oftype_name_str);
3798 // no break
3799 case ALL_FROM:
3800 case TEMPLATE_NOTUSED:
3801 index++;
3802 }
3803 }
3804 break; }
3805 case INDEXED_TEMPLATE_LIST: {
3806 size_t nof_its = u.indexed_templates->get_nof_its();
3807 if (nof_its > 0) {
3808 Type *t_last = my_governor->get_type_refd_last();
3809 const string& oftype_name =
3810 t_last->get_ofType()->get_genname_template(my_scope);
3811 const char *oftype_name_str = oftype_name.c_str();
3812 // There's no need to generate a set_size call here. To do that, we
3813 // should know the size of the base template, which is not available
3814 // from here.
3815 for (size_t i = 0; i < nof_its; i++) {
3816 IndexedTemplate *it = u.indexed_templates->get_it_byIndex(i);
3817 const string& tmp_id_1 = get_temporary_id();
3818 str = mputstr(str, "{\n");
3819 Value *index = (it->get_index()).get_val();
3820 if (index->get_valuetype() != Value::V_INT) {
3821 const string& tmp_id_2 = get_temporary_id();
3822 str = mputprintf(str, "int %s;\n", tmp_id_2.c_str());
3823 str = index->generate_code_init(str, tmp_id_2.c_str());
3824 str = mputprintf(str, "%s& %s = %s[%s];\n", oftype_name_str,
3825 tmp_id_1.c_str(), name, tmp_id_2.c_str());
3826 } else {
3827 str = mputprintf(str, "%s& %s = %s[%s];\n", oftype_name_str,
3828 tmp_id_1.c_str(), name,
3829 Int2string(index->get_val_Int()->get_val()).c_str());
3830 }
3831 str = it->get_template()->generate_code_init(str, tmp_id_1.c_str());
3832 str = mputstr(str, "}\n");
3833 }
3834 } else {
3835 // It seems to be impossible in this case.
3836 str = mputprintf(str, "%s = NULL_VALUE;\n", name);
3837 }
3838 break; }
3839 default:
3840 FATAL_ERROR("Template::generate_code_init_seof()");
3841 return NULL;
3842 }
3843 return str;
3844 }
3845
3846 char *Template::generate_code_init_seof_element(char *str, const char *name,
3847 const char* index, const char *element_type_genname)
3848 {
3849 if (needs_temp_ref()) {
3850 const string& tmp_id = get_temporary_id();
3851 str = mputprintf(str, "{\n"
3852 "%s& %s = %s[%s];\n",
3853 element_type_genname, tmp_id.c_str(), name, index);
3854 str = generate_code_init(str, tmp_id.c_str());
3855 str = mputstr(str, "}\n");
3856 } else {
3857 char *embedded_name = mprintf("%s[%s]", name, index);
3858 str = generate_code_init(str, embedded_name);
3859 Free(embedded_name);
3860 }
3861 return str;
3862 }
3863
3864 char *Template::generate_code_init_all_from(char *str, const char *name)
3865 {
3866 // we are ALL_FROM, hence u.all_from
3867 switch (u.all_from->templatetype) {
3868 case SPECIFIC_VALUE: {
3869 Value *spec = u.all_from->u.specific_value;
3870 switch (spec->get_valuetype()) {
3871 case Common::Value::V_REFD: {
3872 Common::Reference *ref = spec->get_reference();
3873 expression_struct expr;
3874 Code::init_expr(&expr);
3875 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3876 if (ref_pard)
3877 ref_pard->generate_code_cached(&expr);
3878 else
3879 ref->generate_code(&expr);
3abe9331 3880
3881 Common::Assignment* ass = ref->get_refd_assignment();
3882 switch(ass->get_asstype()) {
3883 case Common::Assignment::A_CONST:
3884 case Common::Assignment::A_EXT_CONST:
3885 case Common::Assignment::A_MODULEPAR:
3886 case Common::Assignment::A_VAR:
3887 case Common::Assignment::A_PAR_VAL_IN:
3888 case Common::Assignment::A_PAR_VAL_OUT:
3889 case Common::Assignment::A_PAR_VAL_INOUT:
3890 case Common::Assignment::A_FUNCTION_RVAL:
3891 case Common::Assignment::A_EXT_FUNCTION_RVAL:
3892 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
3893 expr.expr = mputstrn(expr.expr, "()", 2);
3894 }
3895 break;
3896 default:
3897 break;
3898 }
3899
970ed795
EL
3900 str = mputprintf(str, "%s = %s[i_i];\n", name, expr.expr);
3901 // The caller will have to provide the for cycle with this variable
3902 Code::free_expr(&expr);
3903 break; }
3904 default:
3905 break;
3906 }
3907 break; }
3908 default:
3909 break;
3910 }
3911 return str;
3912 }
3913
3914 char *Template::generate_code_init_all_from_list(char *str, const char *name)
3915 {
3916 // FIXME: this is the third instance
3917 expression_struct expr;
3918 Code::init_expr(&expr);
3919 switch (u.all_from->templatetype) {
3920 case SPECIFIC_VALUE: {
3921 Value *spec = u.all_from->u.specific_value;
3922 switch (spec->get_valuetype()) {
3923 case Common::Value::V_REFD: {
3924 Common::Reference *ref = spec->get_reference();
3925 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
3926 if (ref_pard)
3927 ref_pard->generate_code_cached(&expr);
3928 else
3929 ref->generate_code(&expr);
3930 break; }
3931 default:
3932 FATAL_ERROR("vtype %d", spec->get_valuetype());
3933 break;
3934 }
3935 break; }
3936
3937 default:
3938 FATAL_ERROR("ttype %d", u.all_from->templatetype);
3939 break;
3940 }
3941
3942 if (expr.preamble)
3943 str = mputstr(str, expr.preamble);
3944
3945 str = mputprintf(str,
3946 "%s.set_type(VALUE_LIST, %s.n_elem());\n"
3947 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3948 name,
3949 expr.expr,
3950 expr.expr);
3951 string embedded_name(name);
3952 embedded_name += ".list_item(i_i)";
3953 str = generate_code_init_all_from(str, embedded_name.c_str());
3954 str = mputstrn(str, "}\n", 2);
3955
3956 Code::free_expr(&expr);
3957 return str;
3958 }
3959
3960 char *Template::generate_code_init_se(char *str, const char *name)
3961 { // named template list
3962 size_t nof_nts = u.named_templates->get_nof_nts();
3963 Type *type = my_governor->get_type_refd_last();
3964 if (type->get_nof_comps() > 0) {
3965 for (size_t i = 0; i < nof_nts; i++) {
3966 NamedTemplate *nt = u.named_templates->get_nt_byIndex(i);
3967 const Identifier& fieldname = nt->get_name();
3968 const char *fieldname_str = 0;
3969 string at("AT_");
3970 if (type->get_typetype()==Type::T_ANYTYPE) {
3971 at += fieldname.get_name();
3972 fieldname_str = at.c_str();
3973 }
3974 else {
3975 fieldname_str = fieldname.get_name().c_str();
3976 }
3977 Template *t = nt->get_template();
3978 if (t->needs_temp_ref()) {
3979 Type *field_type;
3980 if (type->get_typetype() == Type::T_SIGNATURE) {
3981 field_type = type->get_signature_parameters()
3982 ->get_param_byName(fieldname)->get_type();
3983 } else {
3984 field_type = type->get_comp_byName(fieldname)->get_type();
3985 }
3986 const string& tmp_id = get_temporary_id();
3987 const char *tmp_id_str = tmp_id.c_str();
3988 str = mputprintf(str, "{\n"
3989 "%s& %s = %s.%s();\n",
3990 field_type->get_genname_template(my_scope).c_str(), tmp_id_str,
3991 name, fieldname_str);
3992 str = t->generate_code_init(str, tmp_id_str);
3993 str = mputstr(str, "}\n");
3994 } else {
3995 char *embedded_name = mprintf("%s.%s()", name, fieldname_str);
3996 str = t->generate_code_init(str, embedded_name);
3997 Free(embedded_name);
3998 }
3999 }
4000 } else {
4001 str = mputprintf(str, "%s = NULL_VALUE;\n", name);
4002 }
4003 return str;
4004 }
4005
4006 char *Template::generate_code_init_list(char *str, const char *name,
4007 bool is_complemented) // VALUE_LIST or COMPLEMENTED_LIST
4008 {
4009 size_t nof_ts = u.templates->get_nof_ts();
4010 const string& type_name = my_governor->get_genname_template(my_scope);
4011 const char *type_name_str = type_name.c_str();
4012
4013 dynamic_array<int> variables;
4014 size_t fixed_part = 0;
4015 for (size_t i = 0; i < nof_ts; ++i) {
4016 Template *t = u.templates->get_t_byIndex(i);
4017 if (t->templatetype == ALL_FROM) {
4018 variables.add(i);
4019 }
4020 else ++fixed_part;
4021 }
4022
4023 if (variables.size() > 0) {
4024 char* str_preamble = 0;
3abe9331 4025 char* str_set_type = mprintf("%s.set_type(%s, %lu", name,
970ed795
EL
4026 (is_complemented ? "COMPLEMENTED_LIST" : "VALUE_LIST"),
4027 (unsigned long)fixed_part);
4028 // The code to compute the number of elements at run time (the variable part).
4029 // This is the sum of sizes of "all from"s.
4030 for (size_t v = 0, vs = variables.size(); v < vs; ++v) {
4031 Template *vt = u.templates->get_t_byIndex(variables[v]);
4032 if (vt->templatetype != ALL_FROM) FATAL_ERROR("must be ALL_FROM");
4033 if (vt->u.all_from->templatetype != SPECIFIC_VALUE) FATAL_ERROR("not value");
4034 Value *val = vt->u.all_from->u.specific_value;
4035 if (val->get_valuetype() != Value::V_REFD) FATAL_ERROR("ref expected from val");
4036 Common::Reference *ref = val->get_reference();
4037 FieldOrArrayRefs *subrefs = ref->get_subrefs();
4038 Common::Assignment *ass = ref->get_refd_assignment();
4039 if (!ass) FATAL_ERROR("Could not grab ass!");
4040
4041 str_set_type = mputstrn(str_set_type, " + ", 3);
4042
4043 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
4044 if (ref_pard) {
4045 // in case of parametrised references:
4046 // - temporary parameters need to be declared (stored in str_preamble)
4047 // - the same temporary needs to be used at each call (generate_code_cached call)
4048 expression_struct expr;
4049 Code::init_expr(&expr);
4050
4051 ref_pard->generate_code_cached(&expr);
4052 str_set_type = mputprintf(str_set_type, "%s", expr.expr);
4053 if (expr.preamble)
4054 str_preamble = mputstr(str_preamble, expr.preamble);
4055
4056 Code::free_expr(&expr);
4057 }
4058 else {
4059 str_set_type = mputstr (str_set_type, ass->get_id().get_name().c_str());
4060 if (subrefs) {
4061 expression_struct expr;
4062 Code::init_expr(&expr);
4063
4064 subrefs->generate_code(&expr, ass);
3abe9331 4065 str_set_type = mputprintf(str_set_type, "%s", expr.expr);
970ed795
EL
4066
4067 Code::free_expr(&expr);
4068 }
4069 }
3abe9331 4070
4071 switch(ass->get_asstype()) {
4072 case Common::Assignment::A_CONST:
4073 case Common::Assignment::A_EXT_CONST:
4074 case Common::Assignment::A_MODULEPAR:
4075 case Common::Assignment::A_VAR:
4076 case Common::Assignment::A_PAR_VAL_IN:
4077 case Common::Assignment::A_PAR_VAL_OUT:
4078 case Common::Assignment::A_PAR_VAL_INOUT:
4079 case Common::Assignment::A_FUNCTION_RVAL:
4080 case Common::Assignment::A_EXT_FUNCTION_RVAL:
4081 if (ass->get_Type()->field_is_optional(subrefs)) {
4082 str_set_type = mputstrn(str_set_type, "()", 2);
4083 }
4084 break;
4085 default:
4086 break;
4087 }
4088
970ed795
EL
4089 str_set_type = mputstr(str_set_type, ".n_elem()");
4090 }
4091
4092 str = mputstr(str, str_preamble);
4093 str = mputstr(str, str_set_type);
4094
4095 Free(str_preamble);
4096 Free(str_set_type);
4097
4098 str = mputstrn(str, ");\n", 3);
3abe9331 4099
970ed795
EL
4100 string shifty; // contains the expression used to calculate
4101 // the size increase due to the runtime expansion of "all from".
4102 // In nof_ts, each "all from" appears as 1, but actually contributes
4103 // more. So the increase (by which all elements after the "all from"
d44e3c4f 4104 // are shifted) is:  target_of_all_from.n_elem()-1
970ed795
EL
4105 // This needs to be accumulated for each "all from".
4106 for (size_t vi = 0; vi < nof_ts; ++vi) {
4107 Template *t = u.templates->get_t_byIndex(vi);
4108 switch (t->templatetype) {
4109 case VALUE_LIST_ALL_FROM:
4110 FATAL_ERROR("VALUE_LIST_ALL_FROM not handled");
4111 case ALL_FROM: {
4112 expression_struct expr;
4113 Code::init_expr(&expr);
4114 // variable one
4115 switch (t->u.all_from->templatetype) {
4116 case SPECIFIC_VALUE: {
4117 Value *sv = t->u.all_from->u.specific_value;
4118 switch (sv->get_valuetype()) {
4119 case Value::V_REFD: {
4120 Common::Reference *ref = sv->get_reference();
4121 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
4122 if (ref_pard)
4123 ref_pard->generate_code_cached(&expr);
4124 else
3abe9331 4125 ref->generate_code(&expr);
4126
4127 Common::Assignment* ass = ref->get_refd_assignment();
4128 switch(ass->get_asstype()) {
4129 case Common::Assignment::A_CONST:
4130 case Common::Assignment::A_EXT_CONST:
4131 case Common::Assignment::A_MODULEPAR:
4132 case Common::Assignment::A_VAR:
4133 case Common::Assignment::A_PAR_VAL_IN:
4134 case Common::Assignment::A_PAR_VAL_OUT:
4135 case Common::Assignment::A_PAR_VAL_INOUT:
4136 case Common::Assignment::A_FUNCTION_RVAL:
4137 case Common::Assignment::A_EXT_FUNCTION_RVAL:
4138 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
4139 expr.expr = mputstrn(expr.expr, "()", 2);
4140 }
4141 break;
4142 default:
4143 break;
4144 }
4145
970ed795
EL
4146 break; }
4147
4148 default:
4149 FATAL_ERROR("VT NOT HANDLED");
4150 } // switch valuetype
4151 break; }
4152
4153 default:
4154 FATAL_ERROR("ttype not handled");
4155 break;
4156 }
4157
4158 // All local variables should contain a single underscore,
4159 // to avoid potential clashes with field names.
4160 str = mputprintf(str, "for (int i_i= 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
4161 expr.expr);
4162
4163 if (t->needs_temp_ref()) {
4164 // Not possible, because t->templatetype is ALL_FROM
4165 FATAL_ERROR("temp ref not handled");
4166 }
4167 char *embedded_name = mprintf("%s.list_item(%lu + i_i%s)", name,
4168 (unsigned long) vi, shifty.c_str());
4169 str = t->generate_code_init(str, embedded_name);
4170 Free(embedded_name);
4171
4172 str = mputstrn(str, "}\n", 2);
4173
4174 shifty += "-1+";
4175 shifty += expr.expr;
4176 shifty += ".n_elem() /* 3303 */ ";
4177
4178 Code::free_expr(&expr);
4179 break; }
4180
4181 default: // "fixed one"
4182 if (t->needs_temp_ref()) { // FIXME: this is copypasta from below / but may need to be changed
4183 const string& tmp_id = get_temporary_id();
4184 const char *tmp_id_str = tmp_id.c_str();
4185 str = mputprintf(str, "{\n"
4186 "%s& %s = %s.list_item(%lu);\n",
4187 type_name_str, tmp_id_str, name, (unsigned long) vi);
4188 str = t->generate_code_init(str, tmp_id_str);
4189 str = mputstr(str, "}\n");
4190 } else {
4191 char *embedded_name = mprintf("%s.list_item(%lu%s)", name,
4192 (unsigned long) vi, shifty.c_str());
4193 str = t->generate_code_init(str, embedded_name);
4194 Free(embedded_name);
4195 }
4196 break;
4197 } // switch t->templatetype
4198 }
4199 }
4200 else {
4201 str = mputprintf(str, "%s.set_type(%s, %lu);\n", name,
4202 is_complemented ? "COMPLEMENTED_LIST" : "VALUE_LIST",
4203 (unsigned long) nof_ts);
4204 for (size_t i = 0; i < nof_ts; i++) {
4205 Template *t = u.templates->get_t_byIndex(i);
4206 if (t->needs_temp_ref()) {
4207 const string& tmp_id = get_temporary_id();
4208 const char *tmp_id_str = tmp_id.c_str();
4209 str = mputprintf(str, "{\n"
4210 "%s& %s = %s.list_item(%lu);\n",
4211 type_name_str, tmp_id_str, name, (unsigned long) i);
4212 str = t->generate_code_init(str, tmp_id_str);
4213 str = mputstr(str, "}\n");
4214 } else {
4215 char *embedded_name = mprintf("%s.list_item(%lu)", name,
4216 (unsigned long) i);
4217 str = t->generate_code_init(str, embedded_name);
4218 Free(embedded_name);
4219 }
4220 }
4221 }
4222 return str;
4223 }
4224
4225 char *Template::generate_code_init_set(char *str, const char *name,
4226 bool is_superset) // SUPERSET_MATCH and SUBSET_MATCH
4227 {
4228 size_t nof_ts = u.templates->get_nof_ts();
4229 const string& oftype_name =
4230 my_governor->get_ofType()->get_genname_template(my_scope);
4231 const char *oftype_name_str = oftype_name.c_str();
4232
4233 dynamic_array<int> variables;
4234 size_t fixed_part = 0;
4235 for (size_t i = 0; i < nof_ts; ++i) {
4236 Template *t = u.templates->get_t_byIndex(i);
4237 if (t->templatetype == ALL_FROM) {
4238 variables.add(i);
4239 }
4240 else ++fixed_part;
4241 }
4242
4243 //warning("There are %lu set elements", nof_ts);
4244 if (variables.size() > 0) {
4245 char* str_preamble = 0;
4246 char* str_set_type = mputprintf(0, "%s.set_type(%s, %lu", name,
4247 is_superset ? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) fixed_part);
4248
4249 for (size_t v = 0, vs = variables.size(); v < vs; ++v) {
4250 Template *vt = u.templates->get_t_byIndex(variables[v]);
4251 if (vt->templatetype != ALL_FROM) FATAL_ERROR("must be ALL_FROM");
4252 if (vt->u.all_from->templatetype != SPECIFIC_VALUE) FATAL_ERROR("not value");
4253 Value *val = vt->u.all_from->u.specific_value;
4254 if (val->get_valuetype() != Value::V_REFD) FATAL_ERROR("ref expected from val");
4255 Common::Reference *ref = val->get_reference();
4256 FieldOrArrayRefs *subrefs = ref->get_subrefs();
4257 Common::Assignment *ass = ref->get_refd_assignment();
4258 if (!ass) FATAL_ERROR("Could not grab ass!");
4259
4260 str_set_type = mputstrn(str_set_type, " + ", 3);
4261
4262 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
4263 if (ref_pard) {
4264 // in case of parametrised references:
4265 // - temporary parameters need to be declared (stored in str_preamble)
4266 // - the same temporary needs to be used at each call (generate_code_cached call)
4267 expression_struct expr;
4268 Code::init_expr(&expr);
4269
4270 ref_pard->generate_code_cached(&expr);
4271 str_set_type = mputprintf(str_set_type, "%s", expr.expr);
4272 if (expr.preamble)
4273 str_preamble = mputstr(str_preamble, expr.preamble);
4274
4275 Code::free_expr(&expr);
4276 }
4277 else {
4278 str_set_type = mputstr (str_set_type, ass->get_id().get_name().c_str());
4279 if (subrefs) {
4280 expression_struct expr;
4281 Code::init_expr(&expr);
4282
4283 subrefs->generate_code(&expr, ass);
4284 str_set_type = mputprintf(str_set_type, "%s", expr.expr);
4285
4286 Code::free_expr(&expr);
4287 }
4288 }
3abe9331 4289
4290 switch(ass->get_asstype()) {
4291 case Common::Assignment::A_CONST:
4292 case Common::Assignment::A_EXT_CONST:
4293 case Common::Assignment::A_MODULEPAR:
4294 case Common::Assignment::A_VAR:
4295 case Common::Assignment::A_PAR_VAL_IN:
4296 case Common::Assignment::A_PAR_VAL_OUT:
4297 case Common::Assignment::A_PAR_VAL_INOUT:
4298 case Common::Assignment::A_FUNCTION_RVAL:
4299 case Common::Assignment::A_EXT_FUNCTION_RVAL:
4300 if (ass->get_Type()->field_is_optional(subrefs)) {
4301 str_set_type = mputstrn(str_set_type, "()", 2);
4302 }
4303 break;
4304 default:
4305 break;
4306 }
4307
970ed795
EL
4308 str_set_type = mputstr(str_set_type, ".n_elem()");
4309 }
4310
4311 str = mputstr(str, str_preamble);
4312 str = mputstr(str, str_set_type);
4313
4314 Free(str_preamble);
4315 Free(str_set_type);
4316
4317 str = mputstrn(str, ");\n", 3);
4318
4319 string shifty;
4320 for (size_t i = 0; i < nof_ts; i++) {
4321 Template *t = u.templates->get_t_byIndex(i);
4322 switch (t->templatetype) {
4323 case ALL_FROM: {
4324 expression_struct expr; // FIXME copypasta from init_list above !
4325 Code::init_expr(&expr);
4326 // variable one
4327 switch (t->u.all_from->templatetype) {
4328 case SPECIFIC_VALUE: {
4329 Value *sv = t->u.all_from->u.specific_value;
4330 switch (sv->get_valuetype()) {
4331 case Value::V_REFD: {
4332 Common::Reference *ref = sv->get_reference();
4333 Ref_pard* ref_pard = dynamic_cast<Ref_pard*>(ref);
4334 if (ref_pard)
4335 ref_pard->generate_code_cached(&expr);
4336 else
4337 ref->generate_code(&expr);
3abe9331 4338
4339 Common::Assignment* ass = ref->get_refd_assignment();
4340 switch(ass->get_asstype()) {
4341 case Common::Assignment::A_CONST:
4342 case Common::Assignment::A_EXT_CONST:
4343 case Common::Assignment::A_MODULEPAR:
4344 case Common::Assignment::A_VAR:
4345 case Common::Assignment::A_PAR_VAL_IN:
4346 case Common::Assignment::A_PAR_VAL_OUT:
4347 case Common::Assignment::A_PAR_VAL_INOUT:
4348 case Common::Assignment::A_FUNCTION_RVAL:
4349 case Common::Assignment::A_EXT_FUNCTION_RVAL:
4350 if (ass->get_Type()->field_is_optional(ref->get_subrefs())) {
4351 expr.expr = mputstrn(expr.expr, "()", 2);
4352 }
4353 break;
4354 default:
4355 break;
4356 }
4357
970ed795
EL
4358 break; }
4359
4360 default:
4361 FATAL_ERROR("VT NOT HANDLED");
4362 } // switch valuetype
4363 break; }
4364
4365 default:
4366 FATAL_ERROR("ttype not handled");
4367 break;
4368 }
4369
4370 str = mputprintf(str,
4371 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
4372 expr.expr);
4373
4374 // Name for the LHS
4375 char *embedded_name = mprintf("%s.set_item(%lu%s + i_i)", name,
4376 (unsigned long) i, shifty.c_str());
4377 str = t->generate_code_init_all_from(str, embedded_name);
4378 Free(embedded_name);
4379
4380 str = mputstrn(str, "}\n", 2);
4381
4382 shifty += "-1+";
4383 shifty += expr.expr;
4384 shifty += ".n_elem() /* 3442 */";
4385 Code::free_expr(&expr);
4386 break; }
4387 case VALUE_LIST_ALL_FROM:
4388 FATAL_ERROR("Not possible");
4389 break; // not reached
4390
4391 default:
4392 if (t->needs_temp_ref()) {
4393 const string& tmp_id = get_temporary_id();
4394 const char *tmp_id_str = tmp_id.c_str();
4395 str = mputprintf(str, "{\n"
4396 "%s& %s = %s.set_item(%lu%s);\n",
4397 oftype_name_str, tmp_id_str, name, (unsigned long) i, shifty.c_str());
4398 str = t->generate_code_init(str, tmp_id_str);
4399 str = mputstr(str, "}\n");
4400 } else {
4401 char *embedded_name = mprintf("%s.set_item(%lu%s)", name,
4402 (unsigned long) i, shifty.c_str());
4403 str = t->generate_code_init(str, embedded_name);
4404 Free(embedded_name);
4405 }
4406 break;
4407 } // switch t->templatetype
4408 }
4409
4410 }
4411 else {
4412 str = mputprintf(str, "%s.set_type(%s, %lu);\n", name,
4413 is_superset ? "SUPERSET_MATCH" : "SUBSET_MATCH", (unsigned long) nof_ts);
4414 for (size_t i = 0; i < nof_ts; i++) {
4415 Template *t = u.templates->get_t_byIndex(i);
4416 if (t->needs_temp_ref()) {
4417 const string& tmp_id = get_temporary_id();
4418 const char *tmp_id_str = tmp_id.c_str();
4419 str = mputprintf(str, "{\n"
4420 "%s& %s = %s.set_item(%lu);\n",
4421 oftype_name_str, tmp_id_str, name, (unsigned long) i);
4422 str = t->generate_code_init(str, tmp_id_str);
4423 str = mputstr(str, "}\n");
4424 } else {
4425 char *embedded_name = mprintf("%s.set_item(%lu)", name,
4426 (unsigned long) i);
4427 str = t->generate_code_init(str, embedded_name);
4428 Free(embedded_name);
4429 }
4430 }
4431 }
4432 return str;
4433 }
4434
4435 void Template::generate_code_expr_invoke(expression_struct *expr)
4436 {
4437 Value *last_v = u.invoke.v->get_value_refd_last();
4438 if (last_v->get_valuetype() == Value::V_FUNCTION) {
4439 Common::Assignment *function = last_v->get_refd_fat();
4440 expr->expr = mputprintf(expr->expr, "%s(",
4441 function->get_genname_from_scope(my_scope).c_str());
4442 u.invoke.ap_list->generate_code_alias(expr,
4443 function->get_FormalParList(), function->get_RunsOnType(), false);
4444 } else {
4445 u.invoke.v->generate_code_expr_mandatory(expr);
4446 expr->expr = mputstr(expr->expr, ".invoke(");
4447 Type* gov_last = u.invoke.v->get_expr_governor_last();
4448 u.invoke.ap_list->generate_code_alias(expr, 0,
4449 gov_last->get_fat_runs_on_type(), gov_last->get_fat_runs_on_self());
4450 }
4451 expr->expr = mputc(expr->expr, ')');
4452 }
4453
51fa56b9 4454 char *Template::rearrange_init_code_refd(char *str, Common::Module* usage_mod)
970ed795
EL
4455 {
4456 if (templatetype != TEMPLATE_REFD)
4457 FATAL_ERROR("Template::rearrange_init_code_refd()");
51fa56b9 4458 ActualParList *actual_parlist = u.ref.ref->get_parlist();
970ed795
EL
4459 // generate code for the templates that are used in the actual parameter
4460 // list of the reference
4461 Common::Assignment *ass = u.ref.ref->get_refd_assignment();
51fa56b9 4462 if (actual_parlist) str = actual_parlist->rearrange_init_code(str, usage_mod);
970ed795
EL
4463 // do nothing if the reference does not point to a template definition
4464 if (ass->get_asstype() != Common::Assignment::A_TEMPLATE) return str;
970ed795 4465 Template *t = ass->get_Template();
51fa56b9 4466 FormalParList *formal_parlist = ass->get_FormalParList();
4467 if (formal_parlist) {
970ed795
EL
4468 // the reference points to a parameterized template
4469 // we must perform the rearrangement for all non-parameterized templates
51fa56b9 4470 // that are referred by the parameterized template regardless of the
970ed795 4471 // sub-references of u.ref.ref
51fa56b9 4472 str = t->rearrange_init_code(str, usage_mod);
4473 // the parameterized template's default values must also be generated
4474 // (this only generates their value assignments, their declarations will
4475 // be generated when the template's definition is reached)
4476 if (ass->get_my_scope()->get_scope_mod_gen() == usage_mod) {
4477 str = formal_parlist->generate_code_defval(str);
4478 }
970ed795
EL
4479 } else {
4480 // the reference points to a non-parameterized template
4481 FieldOrArrayRefs *subrefs = u.ref.ref->get_subrefs();
4482 if (subrefs) {
4483 // we should follow the sub-references as much as we can
4484 // and perform the rearrangement for the referred field only
4485 for (size_t i = 0; i < subrefs->get_nof_refs(); i++) {
4486 FieldOrArrayRef *ref = subrefs->get_ref(i);
4487 if (ref->get_type() == FieldOrArrayRef::FIELD_REF) {
4488 // stop if the body does not have fields
4489 if (t->templatetype != NAMED_TEMPLATE_LIST) break;
4490 // get the sub-template of the referred field
4491 t = t->u.named_templates->get_nt_byName(*ref->get_id())
4492 ->get_template();
4493 } else {
4494 // stop if the body is not a list
4495 if (t->templatetype != TEMPLATE_LIST) break;
4496 Value *array_index = ref->get_val()->get_value_refd_last();
4497 // stop if the index cannot be evaluated at compile time
4498 if (array_index->get_valuetype() != Value::V_INT) break;
4499 Int index = array_index->get_val_Int()->get_val();
4500 // index transformation in case of arrays
4501 if (t->my_governor->get_typetype() == Type::T_ARRAY)
4502 index -= t->my_governor->get_dimension()->get_offset();
4503 // get the template with the given index
4504 t = t->get_listitem_byIndex(index);
4505 }
4506 }
4507 }
4508 // otherwise if the reference points to a top-level template
4509 // we should initialize its entire body
51fa56b9 4510 if (ass->get_my_scope()->get_scope_mod_gen() == usage_mod) {
4511 str = t->generate_code_init(str, t->get_lhs_name().c_str());
4512 }
970ed795
EL
4513 }
4514 return str;
4515 }
4516
51fa56b9 4517 char *Template::rearrange_init_code_invoke(char *str, Common::Module* usage_mod)
970ed795 4518 {
2861f5cd 4519 str = u.invoke.v->rearrange_init_code(str, usage_mod);
51fa56b9 4520 str = u.invoke.ap_list->rearrange_init_code(str, usage_mod);
970ed795
EL
4521 return str;
4522 }
4523
4524 bool Template::needs_temp_ref()
4525 {
4526 if (length_restriction || is_ifpresent) return true;
4527 switch (templatetype) {
4528 case OMIT_VALUE:
4529 case ANY_VALUE:
4530 case ANY_OR_OMIT:
4531 case SPECIFIC_VALUE:
4532 case TEMPLATE_REFD:
4533 case TEMPLATE_INVOKE:
4534 case BSTR_PATTERN:
4535 case HSTR_PATTERN:
4536 case OSTR_PATTERN:
4537 case CSTR_PATTERN:
4538 case USTR_PATTERN:
4539 return false;
4540 case TEMPLATE_LIST:
4541 // temporary reference is needed if the template has at least one
4542 // element (excluding not used symbols)
4543 for (size_t i = 0; i < u.templates->get_nof_ts(); i++) {
4544 if (u.templates->get_t_byIndex(i)->templatetype != TEMPLATE_NOTUSED)
4545 return true;
4546 }
4547 return false;
4548 case INDEXED_TEMPLATE_LIST:
4549 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++) {
4550 if (u.indexed_templates->get_it_byIndex(i)->get_template()
4551 ->templatetype != TEMPLATE_NOTUSED)
4552 return true;
4553 }
4554 return false;
4555 case NAMED_TEMPLATE_LIST:
4556 return u.named_templates->get_nof_nts() > 1;
4557 case ALL_FROM:
4558 case VALUE_LIST_ALL_FROM:
4559 return false;
4560 case VALUE_LIST:
4561 case COMPLEMENTED_LIST:
4562 case VALUE_RANGE:
4563 case SUPERSET_MATCH:
4564 case SUBSET_MATCH:
4565 return true;
4566 case TEMPLATE_ERROR:
4567 case TEMPLATE_NOTUSED:
4568 FATAL_ERROR("Template::needs_temp_ref()");
4569 case PERMUTATION_MATCH:
4570 // FIXME
4571 return false;
4572 }
4573 return false;
4574 }
4575
4576 bool Template::has_single_expr()
4577 {
4578 if (length_restriction || is_ifpresent || get_needs_conversion())
4579 return false;
4580 switch (templatetype) {
4581 case OMIT_VALUE:
4582 case ANY_VALUE:
4583 case ANY_OR_OMIT:
4584 case BSTR_PATTERN:
4585 case HSTR_PATTERN:
4586 case OSTR_PATTERN:
4587 case CSTR_PATTERN:
4588 case USTR_PATTERN:
4589 return true;
4590 case SPECIFIC_VALUE:
4591 return u.specific_value->has_single_expr();
4592 case TEMPLATE_REFD: {
4593 Template *t_last = get_template_refd_last();
4594 if (t_last != this && t_last->has_single_expr()) {
4595 for (Scope *t_scope = my_scope; t_scope;
4596 t_scope = t_scope->get_parent_scope()) {
4597 // return true if t_last is visible from my scope
4598 if (t_scope == t_last->my_scope) return true;
4599 }
4600 }
4601 // otherwise consider the reference itself
4602 return u.ref.ref->has_single_expr(); }
4603 case TEMPLATE_INVOKE:
4604 if (!u.invoke.v->has_single_expr()) return false;
4605 for (size_t i = 0; i < u.invoke.ap_list->get_nof_pars(); i++)
4606 if (!u.invoke.ap_list->get_par(i)->has_single_expr()) return false;
4607 return true;
4608 case TEMPLATE_LIST:
4609 return u.templates->get_nof_ts() == 0;
4610 case NAMED_TEMPLATE_LIST: {
4611 if (!my_governor) FATAL_ERROR("Template::has_single_expr()");
4612 Type *type = my_governor->get_type_refd_last();
4613 return type->get_nof_comps() == 0; }
4614 case INDEXED_TEMPLATE_LIST:
4615 return u.indexed_templates->get_nof_its() == 0;
4616 case VALUE_LIST:
4617 case COMPLEMENTED_LIST:
4618 case VALUE_RANGE:
4619 case SUPERSET_MATCH:
4620 case SUBSET_MATCH:
4621 case PERMUTATION_MATCH:
4622 return false;
4623 case ALL_FROM:
4624 case VALUE_LIST_ALL_FROM:
4625 return false;
4626 default:
4627 FATAL_ERROR("Template::has_single_expr()");
4628 return false;
4629 }
4630 }
4631
4632 string Template::get_single_expr(bool cast_needed)
4633 {
4634 if (cast_needed && (length_restriction || is_ifpresent))
4635 FATAL_ERROR("Template::get_single_expr()");
4636 string ret_val;
4637 switch (templatetype) {
4638 case OMIT_VALUE:
4639 ret_val = "OMIT_VALUE";
4640 break;
4641 case ANY_VALUE:
4642 ret_val = "ANY_VALUE";
4643 break;
4644 case ANY_OR_OMIT:
4645 ret_val = "ANY_OR_OMIT";
4646 break;
4647 case SPECIFIC_VALUE:
4648 ret_val = u.specific_value->get_single_expr();
4649 break;
4650 case TEMPLATE_REFD: {
4651 // convert the reference to a single expression
4652 expression_struct expr;
4653 Code::init_expr(&expr);
4654 u.ref.ref->generate_code(&expr);
4655 if (expr.preamble || expr.postamble)
4656 FATAL_ERROR("Template::get_single_expr()");
4657 ret_val = expr.expr;
4658 Code::free_expr(&expr);
4659 return ret_val;
4660 }
4661 case TEMPLATE_INVOKE: {
4662 expression_struct expr;
4663 Code::init_expr(&expr);
4664 generate_code_expr_invoke(&expr);
4665 if (expr.preamble || expr.postamble)
4666 FATAL_ERROR("Template::get_single_expr()");
4667 ret_val = expr.expr;
4668 Code::free_expr(&expr);
4669 return ret_val; }
4670 case TEMPLATE_LIST:
4671 if (u.templates->get_nof_ts() != 0)
4672 FATAL_ERROR("Template::get_single_expr()");
4673 ret_val = "NULL_VALUE";
4674 break;
4675 case NAMED_TEMPLATE_LIST:
4676 if (u.named_templates->get_nof_nts() != 0)
4677 FATAL_ERROR("Template::get_single_expr()");
4678 ret_val = "NULL_VALUE";
4679 break;
4680 case INDEXED_TEMPLATE_LIST:
4681 if (u.indexed_templates->get_nof_its() != 0)
4682 FATAL_ERROR("Template::get_single_expr()");
4683 ret_val = "NULL_VALUE";
4684 break;
4685 case BSTR_PATTERN:
4686 return get_my_scope()->get_scope_mod_gen()
4687 ->add_bitstring_pattern(*u.pattern);
4688 case HSTR_PATTERN:
4689 return get_my_scope()->get_scope_mod_gen()
4690 ->add_hexstring_pattern(*u.pattern);
4691 case OSTR_PATTERN:
4692 return get_my_scope()->get_scope_mod_gen()
4693 ->add_octetstring_pattern(*u.pattern);
4694 case CSTR_PATTERN:
4695 case USTR_PATTERN:
4696 return u.pstring
4697 ->create_charstring_literals(get_my_scope()->get_scope_mod_gen());
4698 default:
4699 FATAL_ERROR("Template::get_single_expr()");
4700 }
4701 if (cast_needed) ret_val = my_governor->get_genname_template(my_scope) +
4702 "(" + ret_val + ")";
4703 return ret_val;
4704 }
4705
4706 void Template::dump(unsigned level) const
4707 {
4708 DEBUG(level, "%s", get_templatetype_str());
4709 switch (templatetype) {
4710 case TEMPLATE_ERROR:
4711 case OMIT_VALUE:
4712 case ANY_VALUE:
4713 case ANY_OR_OMIT:
4714 break;
4715 case SPECIFIC_VALUE:
4716 u.specific_value->dump(level+1);
4717 break;
4718 case TEMPLATE_REFD:
4719 u.ref.ref->dump(level+1);
4720 break;
4721 case TEMPLATE_INVOKE:
4722 u.invoke.v->dump(level+1);
4723 if (u.invoke.ap_list) u.invoke.ap_list->dump(level + 1);
4724 else if (u.invoke.t_list) u.invoke.t_list->dump(level + 1);
4725 break;
4726 case TEMPLATE_LIST:
4727 case VALUE_LIST:
4728 case COMPLEMENTED_LIST:
4729 case SUPERSET_MATCH:
4730 case SUBSET_MATCH:
4731 case PERMUTATION_MATCH:
4732 for (size_t i = 0; i < u.templates->get_nof_ts(); i++)
4733 u.templates->get_t_byIndex(i)->dump(level+1);
4734 break;
4735 case NAMED_TEMPLATE_LIST:
4736 for (size_t i = 0; i < u.named_templates->get_nof_nts(); i++)
4737 u.named_templates->get_nt_byIndex(i)->dump(level+1);
4738 break;
4739 case INDEXED_TEMPLATE_LIST:
4740 for (size_t i = 0; i < u.indexed_templates->get_nof_its(); i++)
4741 u.indexed_templates->get_it_byIndex(i)->dump(level+1);
4742 break;
4743 case VALUE_RANGE:
4744 u.value_range->dump(level);
4745 break;
4746 case BSTR_PATTERN:
4747 case HSTR_PATTERN:
4748 case OSTR_PATTERN:
4749 DEBUG(level+1, "%s", u.pattern->c_str());
4750 break;
4751 case CSTR_PATTERN:
4752 case USTR_PATTERN:
4753 u.pstring->dump(level+1);
4754 break;
4755 case ALL_FROM:
4756 case VALUE_LIST_ALL_FROM:
4757 u.all_from->dump(level+1);
4758 break;
4759 default:
4760 break;
4761 }
4762 if (length_restriction) length_restriction->dump(level + 1);
4763 }
4764
4765 bool Template::has_allfrom() const
4766 { // the code generation of all from is not fully implemented. This helps avoid of using it.
4767 if (templatetype != TEMPLATE_LIST) FATAL_ERROR("has_allfrom(): Templatetype shall be TEMPLATE_LIST");
4768 size_t nof_ts = u.templates->get_nof_ts();
4769 for (size_t i = 0; i < nof_ts; i++) {
4770 if (u.templates->get_t_byIndex(i)->templatetype == ALL_FROM) {
4771 return true;
4772 }
4773 }
4774 return false;
4775 }
4776
4777 // =================================
4778 // ===== TemplateInstance
4779 // =================================
4780
4781 TemplateInstance::TemplateInstance(const TemplateInstance& p)
4782 : Node(p), Location(p)
4783 {
4784 type = p.type ? p.type->clone() : 0;
4785 derived_reference = p.derived_reference ? p.derived_reference->clone() : 0;
4786 template_body = p.template_body->clone();
4787 }
4788
4789 TemplateInstance::TemplateInstance(Type *p_type, Ref_base *p_ref,
4790 Template *p_body) : Node(), Location(), type(p_type),
4791 derived_reference(p_ref), template_body(p_body)
4792 {
4793 if (!p_body) FATAL_ERROR("TemplateInstance::TemplateInstance()");
4794 if (type) type->set_ownertype(Type::OT_TEMPLATE_INST, this);
4795 }
4796
4797 TemplateInstance::~TemplateInstance()
4798 {
4799 delete type;
4800 delete derived_reference;
4801 delete template_body;
4802 }
4803
4804 void TemplateInstance::release()
4805 {
4806 type = 0;
4807 derived_reference = 0;
4808 template_body = 0;
4809 }
4810
4811 TemplateInstance *TemplateInstance::clone() const
4812 {
4813 return new TemplateInstance(*this);
4814 }
4815
4816 void TemplateInstance::set_fullname(const string& p_fullname)
4817 {
4818 Node::set_fullname(p_fullname);
4819 if (type) type->set_fullname(p_fullname + ".<type>");
4820 if (derived_reference)
4821 derived_reference->set_fullname(p_fullname + ".<derived_reference>");
4822 template_body->set_fullname(p_fullname);
4823 }
4824
4825 void TemplateInstance::set_my_scope(Scope *p_scope)
4826 {
4827 if (type) type->set_my_scope(p_scope);
4828 if (derived_reference) derived_reference->set_my_scope(p_scope);
4829 template_body->set_my_scope(p_scope);
4830 }
4831
4832 Type::typetype_t TemplateInstance::get_expr_returntype
4833 (Type::expected_value_t exp_val)
4834 {
4835 Type *t = get_expr_governor(exp_val);
4836 if (t) return t->get_type_refd_last()->get_typetype_ttcn3();
4837 else return template_body->get_expr_returntype(exp_val);
4838 }
4839
4840 Type *TemplateInstance::get_expr_governor(Type::expected_value_t exp_val)
4841 {
4842 if (type) return type;
4843 if (derived_reference) {
4844 Type *ret_val = chk_DerivedRef(0);
4845 if (ret_val) return ret_val;
4846 }
4847 return template_body->get_expr_governor(exp_val);
4848 }
4849
4850 void TemplateInstance::chk(Type *governor)
4851 {
4852 if (!governor) FATAL_ERROR("TemplateInstance::chk()");
4853 governor = chk_Type(governor);
4854 governor = chk_DerivedRef(governor);
4855 template_body->set_my_governor(governor);
4856 governor->chk_this_template_ref(template_body);
4857 governor->chk_this_template_generic(template_body,
4858 (derived_reference != 0 ? INCOMPLETE_ALLOWED : INCOMPLETE_NOT_ALLOWED),
4859 OMIT_ALLOWED, ANY_OR_OMIT_ALLOWED, SUB_CHK, NOT_IMPLICIT_OMIT, 0);
4860 }
4861
4862 Type *TemplateInstance::chk_Type(Type *governor)
4863 {
4864 if (!type) return governor;
4865 {
4866 Error_Context cntxt(type, "In explicit type specification");
4867 type->chk();
4868 }
4869 TypeCompatInfo info(template_body->get_template_refd_last()
4870 ->get_my_scope()->get_scope_mod(), governor, type,
4871 true, false);
4872 TypeChain l_chain;
4873 TypeChain r_chain;
4874 if (!governor) return type;
3f84031e 4875 else if (governor->is_compatible(type, &info, &l_chain, &r_chain, true)) {
970ed795
EL
4876 return governor;
4877 } else {
4878 if (info.is_subtype_error()) {
4879 type->error("%s", info.get_subtype_error().c_str());
4880 } else
4881 if (!info.is_erroneous()) {
4882 type->error("Incompatible explicit type specification: `%s' was "
4883 "expected instead of `%s'",
4884 governor->get_typename().c_str(),
4885 type->get_typename().c_str());
4886 } else {
4887 type->error("%s", info.get_error_str_str().c_str());
4888 }
4889 return type;
4890 }
4891 }
4892
4893 Type *TemplateInstance::chk_DerivedRef(Type *governor)
4894 {
4895 if (!derived_reference) return governor;
4896 Error_Context cntxt(derived_reference, "In derived reference");
4897 Common::Assignment *ass = derived_reference->get_refd_assignment();
4898 // the base template reference must not have sub-references
4899 if (derived_reference->get_subrefs())
4900 FATAL_ERROR("TemplateInstance::chk_DerivedRef()");
4901 bool set_bt = false;
4902 if (!ass) goto error;
4903 switch (ass->get_asstype()) {
4904 case Common::Assignment::A_TEMPLATE:
4905 set_bt = true;
4906 // no break
4907 case Common::Assignment::A_MODULEPAR_TEMP:
4908 case Common::Assignment::A_VAR_TEMPLATE:
4909 case Common::Assignment::A_PAR_TEMPL_IN:
4910 case Common::Assignment::A_PAR_TEMPL_OUT:
4911 case Common::Assignment::A_PAR_TEMPL_INOUT:
4912 case Common::Assignment::A_FUNCTION_RTEMP:
4913 case Common::Assignment::A_EXT_FUNCTION_RTEMP: {
4914 if (!governor) governor = type;
4915 Type *base_template_type = ass->get_Type();
4916 if (governor) {
4917 TypeCompatInfo info(template_body->get_template_refd_last()
4918 ->get_my_scope()->get_scope_mod(), governor, type,
4919 true, false);
4920 TypeChain l_chain;
4921 TypeChain r_chain;
4922 if (!governor->is_compatible(base_template_type, &info, &l_chain,
4923 &r_chain)) {
4924 if (info.is_subtype_error()) {
4925 derived_reference->error("%s", info.get_subtype_error().c_str());
4926 } else
4927 if (!info.is_erroneous()) {
4928 derived_reference->error("Base template `%s' has incompatible "
4929 "type: `%s' was expected instead of `%s'",
4930 ass->get_fullname().c_str(),
4931 governor->get_typename().c_str(),
4932 base_template_type->get_typename().c_str());
4933 } else {
4934 derived_reference->error("%s", info.get_error_str_str().c_str());
4935 }
4936 // if explicit type specification is omitted
4937 // check the template body against the type of the base template
4938 if (!type) governor = base_template_type;
4939 set_bt = false;
4940 } else {
4941 if (info.needs_conversion())
4942 template_body->set_needs_conversion();
4943 }
4944 } else governor = base_template_type;
4945 break; }
4946 default:
4947 derived_reference->error("Reference to a template was expected instead "
4948 "of %s", ass->get_description().c_str());
4949 goto error;
4950 }
4951 if (set_bt) template_body->set_base_template(ass->get_Template());
4952 return governor;
4953 error:
4954 // drop the erroneous derived_reference to avoid further errors
4955 delete derived_reference;
4956 derived_reference = 0;
4957 return governor;
4958 }
4959
4960 void TemplateInstance::chk_recursions(ReferenceChain& refch)
4961 {
4962 template_body->chk_recursions(refch);
4963 }
4964
4965 bool TemplateInstance::is_string_type(Type::expected_value_t exp_val)
4966 {
4967 switch (get_expr_returntype(exp_val)) {
4968 case Type::T_CSTR:
4969 case Type::T_USTR:
4970 case Type::T_BSTR:
4971 case Type::T_HSTR:
4972 case Type::T_OSTR:
4973 return true;
4974 default:
4975 return false;
4976 }
4977 }
4978
4979 bool TemplateInstance::chk_restriction(const char* definition_name,
3abe9331 4980 template_restriction_t template_restriction, const Location* usage_loc)
970ed795
EL
4981 {
4982 bool needs_runtime_check = false;
4983 if (derived_reference) // if modified
4984 {
4985 Common::Assignment *ass = derived_reference->get_refd_assignment();
4986 switch (ass->get_asstype()) {
4987 case Common::Assignment::A_TEMPLATE:
4988 // already added to template_body as base template by chk_DerivedRef()
4989 needs_runtime_check = template_body->chk_restriction(
3abe9331 4990 definition_name, template_restriction, usage_loc);
970ed795
EL
4991 break;
4992 case Common::Assignment::A_MODULEPAR_TEMP:
4993 case Common::Assignment::A_VAR_TEMPLATE:
4994 case Common::Assignment::A_EXT_FUNCTION_RTEMP:
4995 case Common::Assignment::A_FUNCTION_RTEMP:
4996 case Common::Assignment::A_PAR_TEMPL_IN:
4997 case Common::Assignment::A_PAR_TEMPL_OUT:
4998 case Common::Assignment::A_PAR_TEMPL_INOUT: {
4999 // create a temporary Template to be added as the base template and
5000 // check, remove and delete after checked
5001 if (template_body->get_base_template())
5002 FATAL_ERROR("TemplateInstance::chk_restriction()");
5003 template_body->set_base_template(new Template(derived_reference));
5004 needs_runtime_check = template_body->chk_restriction(
3abe9331 5005 definition_name, template_restriction, usage_loc);
970ed795
EL
5006 delete template_body->get_base_template();
5007 template_body->set_base_template(0);
5008 } break;
5009 default:
5010 break;
5011 }
5012 } else { // simple
5013 needs_runtime_check = template_body->chk_restriction(definition_name,
3abe9331 5014 template_restriction, usage_loc);
970ed795
EL
5015 }
5016 return needs_runtime_check;
5017 }
5018
5019 bool TemplateInstance::has_single_expr()
5020 {
5021 if (derived_reference) return false;
5022 else if (type) return false;
5023 else return template_body->has_single_expr();
5024 }
5025
5026 void TemplateInstance::set_code_section(
5027 GovernedSimple::code_section_t p_code_section)
5028 {
5029 if (derived_reference) derived_reference->set_code_section(p_code_section);
5030 template_body->set_code_section(p_code_section);
5031 }
5032
5033 bool TemplateInstance::needs_temp_ref()
5034 {
5035 if (template_body->get_templatetype() != Template::SPECIFIC_VALUE)
5036 return false;
5037 Value *val = template_body->get_specific_value();
5038 if (val->get_valuetype() == Value::V_REFD) {
5039 FieldOrArrayRefs *refs = val->get_reference()->get_subrefs();
5040 if (!refs) return false;
5041 // We need at least a 2-long reference chain. E.g. "a[0].b". 3.0.4
5042 // can't handle a normal reference following an indexed reference. The
5043 // indexed reference must be on the first place. Code like: "a.b[0].c"
5044 // compiles fine.
5045 if (refs->get_nof_refs() < 2
5046 || refs->get_ref(0)->get_type() != FieldOrArrayRef::ARRAY_REF)
5047 return false;
5048 } else {
5049 return false;
5050 }
5051 return true;
5052 }
5053
5054 void TemplateInstance::generate_code(expression_struct *expr,
5055 template_restriction_t template_restriction)
5056 {
5057 if (derived_reference) {
5058 // preserve the target expression
5059 char *expr_backup = expr->expr;
5060 // reset the space for the target expression
5061 expr->expr = NULL;
5062 derived_reference->generate_code(expr);
5063 // now the C++ equivalent of the base template reference is in expr->expr
5064 const string& tmp_id = template_body->get_temporary_id();
5065 const char *tmp_id_str = tmp_id.c_str();
5066 // create a temporary variable and copy the contents of base template
5067 // into it
5068 expr->preamble = mputprintf(expr->preamble, "%s %s(%s);\n",
5069 template_body->get_my_governor()->get_genname_template(
5070 template_body->get_my_scope()).c_str(), tmp_id_str, expr->expr);
5071 // perform the modifications on the temporary variable
5072 expr->preamble = template_body->generate_code_init(expr->preamble,
5073 tmp_id_str);
5074 // runtime template restriction check
5075 if (template_restriction!=TR_NONE)
5076 expr->preamble = Template::generate_restriction_check_code(
5077 expr->preamble, tmp_id_str, template_restriction);
5078 // the base template reference is no longer needed
5079 Free(expr->expr);
5080 // restore the target expression append the name of the temporary
5081 // variable to it
5082 expr->expr = mputstr(expr_backup, tmp_id_str);
5083 } else template_body->generate_code_expr(expr, template_restriction);
5084 }
5085
51fa56b9 5086 char *TemplateInstance::rearrange_init_code(char *str, Common::Module* usage_mod)
970ed795
EL
5087 {
5088 if (derived_reference) {
51fa56b9 5089 ActualParList *actual_parlist = derived_reference->get_parlist();
970ed795
EL
5090 Common::Assignment *ass = derived_reference->get_refd_assignment();
5091 if (!ass) FATAL_ERROR("TemplateInstance::rearrange_init_code()");
51fa56b9 5092 if (actual_parlist) str = actual_parlist->rearrange_init_code(str, usage_mod);
5093 if (ass->get_asstype() == Common::Assignment::A_TEMPLATE) {
970ed795 5094 Template *t = ass->get_Template();
51fa56b9 5095 FormalParList *formal_parlist = ass->get_FormalParList();
5096 if (formal_parlist) {
970ed795
EL
5097 // the referred template is parameterized
5098 // the embedded referenced templates shall be visited
51fa56b9 5099 str = t->rearrange_init_code(str, usage_mod);
5100 // the constants used for default values have to be initialized now
5101 if (ass->get_my_scope()->get_scope_mod_gen() == usage_mod) {
5102 str = formal_parlist->generate_code_defval(str);
5103 }
970ed795
EL
5104 } else {
5105 // the referred template is not parameterized
5106 // its entire body has to be initialized now
51fa56b9 5107 if (ass->get_my_scope()->get_scope_mod_gen() == usage_mod) {
5108 str = t->generate_code_init(str, t->get_lhs_name().c_str());
5109 }
970ed795
EL
5110 }
5111 }
5112 }
51fa56b9 5113 str = template_body->rearrange_init_code(str, usage_mod);
970ed795
EL
5114 return str;
5115 }
5116
5117 void TemplateInstance::append_stringRepr(string& str) const
5118 {
5119 if (type) {
5120 str += type->get_typename();
5121 str += " : ";
5122 }
5123 if (derived_reference) {
5124 str += "modifies ";
5125 str += derived_reference->get_dispname();
5126 str += " := ";
5127 }
5128 str += template_body->get_stringRepr();
5129 }
5130
5131 void TemplateInstance::dump(unsigned level) const
5132 {
5133 if (type) {
5134 DEBUG(level, "type:");
5135 type->dump(level + 1);
5136 }
5137 if (derived_reference) {
5138 DEBUG(level, "modifies:");
5139 derived_reference->dump(level + 1);
5140 }
5141 template_body->dump(level);
5142 }
5143
5144 Value* TemplateInstance::get_specific_value() const
5145 {
5146 if (type) return NULL;
5147 if (derived_reference) return NULL;
5148 if (template_body->is_length_restricted() || template_body->get_ifpresent())
5149 return NULL;
5150 if (template_body->get_templatetype()!=Template::SPECIFIC_VALUE) return NULL;
5151 return template_body->get_specific_value();
5152 }
5153
5154 Def_Template* TemplateInstance::get_Referenced_Base_Template()
5155 { // it may return 0
5156 if (!get_Template()) return NULL;
5157 Ttcn::Template::templatetype_t tpt = get_Template()->get_templatetype();
5158 if (Ttcn::Template::TEMPLATE_REFD != tpt) return NULL;
5159 Ttcn::Ref_base* refbase = get_Template()->get_reference();
5160 Ttcn::Reference * ref = dynamic_cast<Ttcn::Reference*>(refbase);
5161 if (!ref) return NULL;
5162 Common::Assignment* ass = ref->get_refd_assignment();
5163 Ttcn::Definition* def = dynamic_cast<Ttcn::Definition*>(ass);
5164 if (!def) return NULL;
5165 Ttcn::Def_Template* deftemp = dynamic_cast<Ttcn::Def_Template*>(def);
5166 if (!deftemp) return NULL;
5167
5168 return deftemp;
5169 }
5170
5171}
5172
This page took 0.219152 seconds and 5 git commands to generate.