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