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
16 * Zalanyi, Balazs Andor
19 ******************************************************************************/
20 #include "TtcnTemplate.hh"
21 #include "../Identifier.hh"
22 #include "Templatestuff.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"
31 #include "../../common/dbgnew.hh"
32 #include "Attributes.hh"
36 // =================================
38 // =================================
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
)
45 switch (templatetype
) {
47 case TEMPLATE_NOTUSED
:
53 u
.specific_value
= p
.u
.specific_value
->clone();
56 u
.ref
.ref
= p
.u
.ref
.ref
->clone();
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;
66 case VALUE_LIST_ALL_FROM
:
67 u
.all_from
= p
.u
.all_from
->clone();
71 case COMPLEMENTED_LIST
:
74 case PERMUTATION_MATCH
:
75 u
.templates
= p
.u
.templates
->clone(); // FATAL_ERROR
77 case NAMED_TEMPLATE_LIST
:
78 u
.named_templates
= p
.u
.named_templates
->clone();
80 case INDEXED_TEMPLATE_LIST
:
81 u
.indexed_templates
= p
.u
.indexed_templates
->clone();
84 u
.value_range
= p
.u
.value_range
->clone();
89 u
.pattern
= new string(*p
.u
.pattern
);
93 u
.pstring
= p
.u
.pstring
->clone();
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();
101 // FATAL_ERROR("Template::Template()");
104 p
.length_restriction
? p
.length_restriction
->clone() : 0; // FATAL_ERR
107 void Template::clean_up()
109 switch(templatetype
) {
111 case TEMPLATE_NOTUSED
:
117 delete u
.specific_value
;
122 case TEMPLATE_INVOKE
:
124 delete u
.invoke
.t_list
;
125 delete u
.invoke
.ap_list
;
129 case COMPLEMENTED_LIST
:
132 case PERMUTATION_MATCH
:
136 case VALUE_LIST_ALL_FROM
:
139 case NAMED_TEMPLATE_LIST
:
140 delete u
.named_templates
;
142 case INDEXED_TEMPLATE_LIST
:
143 delete u
.indexed_templates
;
146 delete u
.value_range
;
158 if (u
.dec_match
.str_enc
!= NULL
) {
159 delete u
.dec_match
.str_enc
;
161 delete u
.dec_match
.target
;
164 // FATAL_ERROR("Template::clean_up()");
168 string
Template::create_stringRepr()
171 switch (templatetype
) {
173 ret_val
+= "<erroneous template>";
175 case TEMPLATE_NOTUSED
:
188 ret_val
+= u
.specific_value
->get_stringRepr();
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();
196 case TEMPLATE_INVOKE
: {
197 ret_val
+= u
.invoke
.v
->get_stringRepr();
198 ret_val
+= ".invoke(";
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();
207 if (u
.templates
->get_nof_ts() > 0) {
209 u
.templates
->append_stringRepr(ret_val
);
211 } else ret_val
+= "{ }";
213 case NAMED_TEMPLATE_LIST
:
215 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++) {
216 if (i
> 0) ret_val
+= ", ";
218 NamedTemplate
*nt
= u
.named_templates
->get_nt_byIndex(i
);
219 ret_val
+= nt
->get_name().get_dispname();
221 ret_val
+= nt
->get_template()->get_stringRepr();
225 case INDEXED_TEMPLATE_LIST
:
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
);
233 ret_val
+= it
->get_template()->get_stringRepr();
239 u
.templates
->append_stringRepr(ret_val
);
242 case COMPLEMENTED_LIST
:
243 ret_val
+= "complement(";
244 u
.templates
->append_stringRepr(ret_val
);
248 u
.value_range
->append_stringRepr(ret_val
);
251 ret_val
+= "superset(";
252 u
.templates
->append_stringRepr(ret_val
);
256 ret_val
+= "subset(";
257 u
.templates
->append_stringRepr(ret_val
);
260 case PERMUTATION_MATCH
:
261 ret_val
+= "permutation(";
262 u
.templates
->append_stringRepr(ret_val
);
267 ret_val
+= *u
.pattern
;
272 ret_val
+= *u
.pattern
;
277 ret_val
+= *u
.pattern
;
282 ret_val
+= "pattern \"";
283 ret_val
+= u
.pstring
->get_full_str();
287 ret_val
+= "decmatch ";
288 if (u
.dec_match
.str_enc
!= NULL
) {
290 ret_val
+= u
.dec_match
.str_enc
->get_val_str();
293 ret_val
+= u
.dec_match
.target
->get_expr_governor(
294 Type::EXPECTED_TEMPLATE
)->get_stringRepr();
296 ret_val
+= u
.dec_match
.target
->get_Template()->create_stringRepr();
299 ret_val
+= "<unknown template>";
302 if (length_restriction
) length_restriction
->append_stringRepr(ret_val
);
303 if (is_ifpresent
) ret_val
+= " ifpresent";
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)
315 case TEMPLATE_NOTUSED
:
321 FATAL_ERROR("Template::Template()");
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)
331 if (!v
) FATAL_ERROR("Template::Template()");
332 u
.specific_value
= v
;
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)
341 if(!p_ref
) FATAL_ERROR("Template::Template()");
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)
356 case COMPLEMENTED_LIST
:
359 case PERMUTATION_MATCH
:
362 FATAL_ERROR("Template::Template()");
364 if (!ts
) FATAL_ERROR("Template::Template()");
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;
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)
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)
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)
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
;
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)
407 if (!nts
) FATAL_ERROR("Template::Template()");
408 u
.named_templates
= nts
;
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),
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
==
424 has_permutation
= true;
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)
436 if (!vr
) FATAL_ERROR("Template::Template()");
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)
452 FATAL_ERROR("Template::Template()");
454 if (!p_patt
) FATAL_ERROR("Template::Template()");
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)
464 if (!p_ps
) FATAL_ERROR("Template::Template()");
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)
475 FATAL_ERROR("Template::Template()");
477 u
.dec_match
.str_enc
= v
;
478 u
.dec_match
.target
= ti
;
481 Template::~Template()
484 delete length_restriction
;
487 Template
*Template::clone() const
489 return new Template(*this);
492 void Template::set_fullname(const string
& p_fullname
)
494 GovernedSimple::set_fullname(p_fullname
);
495 switch (templatetype
) {
497 case TEMPLATE_NOTUSED
:
506 u
.specific_value
->set_fullname(p_fullname
);
509 u
.ref
.ref
->set_fullname(p_fullname
);
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
);
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
) + "]");
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
) + "]");
528 case NAMED_TEMPLATE_LIST
:
529 u
.named_templates
->set_fullname(p_fullname
);
532 case VALUE_LIST_ALL_FROM
:
533 u
.all_from
->set_fullname(p_fullname
);
536 case COMPLEMENTED_LIST
:
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
) + ")");
546 u
.value_range
->set_fullname(p_fullname
);
550 u
.pstring
->set_fullname(p_fullname
);
553 if (u
.dec_match
.str_enc
!= NULL
) {
554 u
.dec_match
.str_enc
->set_fullname(p_fullname
+ ".<string_encoding>");
556 u
.dec_match
.target
->set_fullname(p_fullname
+ ".<decoding_target>");
559 // FATAL_ERROR("Template::set_fullname()");
561 if (length_restriction
)
562 length_restriction
->set_fullname(p_fullname
+ ".<length_restriction>");
565 void Template::set_my_scope(Scope
*p_scope
)
567 GovernedSimple::set_my_scope(p_scope
);
568 switch (templatetype
) {
570 case TEMPLATE_NOTUSED
:
579 u
.specific_value
->set_my_scope(p_scope
);
582 u
.ref
.ref
->set_my_scope(p_scope
);
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
);
590 case VALUE_LIST_ALL_FROM
:
591 u
.all_from
->set_my_scope(p_scope
);
595 case COMPLEMENTED_LIST
:
598 case PERMUTATION_MATCH
:
599 u
.templates
->set_my_scope(p_scope
);
601 case NAMED_TEMPLATE_LIST
:
602 u
.named_templates
->set_my_scope(p_scope
);
604 case INDEXED_TEMPLATE_LIST
:
605 u
.indexed_templates
->set_my_scope(p_scope
);
608 u
.value_range
->set_my_scope(p_scope
);
612 u
.pstring
->set_my_scope(p_scope
);
615 if (u
.dec_match
.str_enc
!= NULL
) {
616 u
.dec_match
.str_enc
->set_my_scope(p_scope
);
618 u
.dec_match
.target
->set_my_scope(p_scope
);
621 // FATAL_ERROR("Template::set_my_scope()");
623 if (length_restriction
) length_restriction
->set_my_scope(p_scope
);
626 void Template::set_genname_recursive(const string
& p_genname
)
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();
634 if (type
->get_typetype() == Type::T_ARRAY
)
635 offset
= type
->get_dimension()->get_offset();
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
);
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
);
666 void Template::set_genname_prefix(const char *p_genname_prefix
)
668 GovernedSimple::set_genname_prefix(p_genname_prefix
);
669 switch (templatetype
) {
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
);
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
);
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
);
689 void Template::set_code_section(code_section_t p_code_section
)
691 GovernedSimple::set_code_section(p_code_section
);
692 switch (templatetype
) {
694 u
.specific_value
->set_code_section(p_code_section
);
697 u
.ref
.ref
->set_code_section(p_code_section
);
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
);
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
);
708 case COMPLEMENTED_LIST
:
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
);
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
);
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
);
726 u
.value_range
->set_code_section(p_code_section
);
730 u
.pstring
->set_code_section(p_code_section
);
733 if (u
.dec_match
.str_enc
!= NULL
) {
734 u
.dec_match
.str_enc
->set_code_section(p_code_section
);
736 u
.dec_match
.target
->set_code_section(p_code_section
);
741 if (length_restriction
)
742 length_restriction
->set_code_section(p_code_section
);
745 void Template::set_templatetype(templatetype_t p_templatetype
)
747 if (p_templatetype
== templatetype
) return;
748 if (p_templatetype
== TEMPLATE_ERROR
) {
750 templatetype
= TEMPLATE_ERROR
;
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();
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
);
769 FATAL_ERROR("Template::set_templatetype()");
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();
786 case Type::T_SIGNATURE
:
790 if (nof_temps
== 0 && nof_comps
== 0) break;
792 FATAL_ERROR("Template::set_templatetype()");
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
:
800 case Type::T_SEQ_A
: case Type::T_SET_A
:
803 case Type::T_SIGNATURE
: // be precise
805 default: // not possible, fatal error ?
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
);
816 size_t upper_limit
; // min(nof_temps, nof_comps)
818 if (nof_temps
<= nof_comps
) {
819 upper_limit
= nof_temps
;
822 upper_limit
= nof_comps
;
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;
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
);
836 u
.named_templates
->set_my_scope(get_my_scope());
837 u
.named_templates
->set_fullname(get_fullname());
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()");
844 case CSTR_PATTERN
: // current type
845 if (p_templatetype
== USTR_PATTERN
)
846 templatetype
= USTR_PATTERN
;
848 FATAL_ERROR("Template::set_templatetype()");
851 FATAL_ERROR("Template::set_templatetype()");
853 templatetype
= p_templatetype
;
856 const char *Template::get_templatetype_str() const
858 switch(templatetype
) {
860 return "erroneous template";
861 case TEMPLATE_NOTUSED
:
862 return "not used symbol";
868 return "any or omit";
870 return "specific value";
872 return "referenced template";
873 case TEMPLATE_INVOKE
:
874 return "template returning invoke";
876 case VALUE_LIST_ALL_FROM
:
877 return "template with 'all from'";
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";
885 return "value range match";
887 return "value list match";
888 case COMPLEMENTED_LIST
:
889 return "complemented list match";
891 return "superset match";
893 return "subset match";
894 case PERMUTATION_MATCH
:
895 return "permutation match";
897 return "bitstring pattern";
899 return "hexstring pattern";
901 return "octetstring pattern";
903 return "character string pattern";
905 return "universal string pattern";
907 return "decoded content match";
909 return "unknown template";
913 bool Template::is_undef_lowerid()
915 return templatetype
== SPECIFIC_VALUE
&&
916 u
.specific_value
->is_undef_lowerid();
919 void Template::set_lowerid_to_ref()
921 switch (templatetype
) {
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);
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
);
941 } else set_templatetype(TEMPLATE_ERROR
);
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();
950 u
.value_range
->set_lowerid_to_ref();
957 Type::typetype_t
Template::get_expr_returntype(Type::expected_value_t exp_val
)
959 switch (templatetype
) {
961 return Type::T_ERROR
;
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
; }
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
;
979 return Type::T_UNDEF
;
981 return u
.value_range
->get_expr_returntype(exp_val
);
984 return Type::T_SETOF
;
996 return Type::T_UNDEF
;
1000 Type
*Template::get_expr_governor(Type::expected_value_t exp_val
)
1002 if (my_governor
) return my_governor
;
1003 switch (templatetype
) {
1004 case SPECIFIC_VALUE
:
1005 return u
.specific_value
->get_expr_governor(exp_val
);
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
);
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
);
1021 case TEMPLATE_INVOKE
: {
1022 Type
*t
= u
.invoke
.v
->get_expr_governor(Type::EXPECTED_DYNAMIC_VALUE
);
1024 if(u
.invoke
.v
->get_valuetype() != Value::V_ERROR
)
1025 u
.invoke
.v
->error("A value of type function expected");
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());
1037 return t
->get_function_return_type();
1038 case Type::T_ALTSTEP
:
1041 u
.invoke
.v
->error("A value of type function expected instead of `%s'",
1042 t
->get_typename().c_str());
1047 return Type::get_pooltype(get_expr_returntype(exp_val
));
1050 set_templatetype(TEMPLATE_ERROR
);
1054 void Template::set_my_governor(Type
*p_gov
)
1057 FATAL_ERROR("Template::set_my_governor(): NULL parameter");
1061 Type
*Template::get_my_governor() const
1066 void Template::set_length_restriction(LengthRestriction
*p_lr
)
1068 if (length_restriction
) FATAL_ERROR("Template::set_length_restriction()");
1069 length_restriction
= p_lr
;
1072 Template::completeness_t
1073 Template::get_completeness_condition_seof(bool incomplete_allowed
)
1075 if (!incomplete_allowed
) return C_MUST_COMPLETE
;
1076 else if (!base_template
) return C_MAY_INCOMPLETE
;
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
;
1091 switch (my_governor
->get_type_refd_last()->get_typetype()) {
1094 // only the first elements can be incomplete
1097 // we are in error recovery
1098 return C_MAY_INCOMPLETE
;
1100 break; // should not get here
1102 // partial overwriting is not allowed for literal specific values,
1103 // matching ranges/lists/sets and patterns
1104 return C_MUST_COMPLETE
;
1109 Template::completeness_t
Template::get_completeness_condition_choice
1110 (bool incomplete_allowed
, const Identifier
& p_fieldname
)
1112 if (!incomplete_allowed
) return C_MUST_COMPLETE
;
1113 else if (!base_template
) return C_MAY_INCOMPLETE
;
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
;
1131 // partial overwriting is not allowed for literal specific values,
1132 // matching ranges/lists/sets and patterns
1133 return C_MUST_COMPLETE
;
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
);
1144 Value
*Template::get_specific_value() const
1146 if (templatetype
!= SPECIFIC_VALUE
)
1147 FATAL_ERROR("Template::get_specific_value()");
1148 return u
.specific_value
;
1151 Ref_base
*Template::get_reference() const
1153 if (templatetype
!= TEMPLATE_REFD
)
1154 FATAL_ERROR("Template::get_reference()");
1158 ValueRange
*Template::get_value_range() const
1160 if (templatetype
!= VALUE_RANGE
)
1161 FATAL_ERROR("Template::get_value_range()");
1162 return u
.value_range
;
1165 PatternString
* Template::get_cstr_pattern() const
1167 if (templatetype
!= CSTR_PATTERN
)
1168 FATAL_ERROR("Template::get_cstr_pattern()");
1172 PatternString
* Template::get_ustr_pattern() const
1174 if (templatetype
!= USTR_PATTERN
)
1175 FATAL_ERROR("Template::get_ustr_pattern()");
1179 size_t Template::get_nof_comps() const
1181 switch (templatetype
) {
1184 case COMPLEMENTED_LIST
:
1185 case SUPERSET_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();
1194 FATAL_ERROR("Template::get_of_comps()");
1199 Template
*Template::get_temp_byIndex(size_t n
) const
1201 switch (templatetype
) {
1204 case COMPLEMENTED_LIST
:
1205 case SUPERSET_MATCH
:
1207 case PERMUTATION_MATCH
:
1208 return u
.templates
->get_t_byIndex(n
);
1210 FATAL_ERROR("Template::get_temp_byIndex()");
1215 IndexedTemplate
*Template::get_indexedtemp_byIndex(size_t n
) const
1217 if (templatetype
!= INDEXED_TEMPLATE_LIST
)
1218 FATAL_ERROR("Template::get_indexedtemp_byIndex()");
1219 return u
.indexed_templates
->get_it_byIndex(n
);
1222 NamedTemplate
*Template::get_namedtemp_byIndex(size_t n
) const
1224 if (templatetype
!= NAMED_TEMPLATE_LIST
)
1225 FATAL_ERROR("Template::get_namedtemp_byIndex()");
1226 return u
.named_templates
->get_nt_byIndex(n
);
1229 Template
*Template::get_all_from() const
1231 if (templatetype
!= ALL_FROM
1232 &&templatetype
!= VALUE_LIST_ALL_FROM
)
1233 FATAL_ERROR("Template::get_all_from()");
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
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();
1252 } else return u
.templates
->get_nof_ts();
1255 Template
*Template::get_listitem_byIndex(size_t n
) const
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
;
1269 if (n
== index
) return t
;
1273 FATAL_ERROR("Template::get_listitem_byIndex(): index overflow");
1275 } else return u
.templates
->get_t_byIndex(n
);
1278 /** \todo revise and merge with get_template_refd() */
1279 Template
* Template::get_template_refd_last(ReferenceChain
*refch
)
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
;
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
;
1296 // otherwise evaluate the reference
1299 refch
->mark_state();
1300 destroy_refch
= false;
1302 refch
= new ReferenceChain(this, "While searching referenced template");
1303 destroy_refch
= true;
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
);
1313 ret_val
= u
.ref
.refd_last
;
1315 // a circular reference was found
1316 set_templatetype(TEMPLATE_ERROR
);
1319 if (destroy_refch
) delete refch
;
1320 else refch
->prev_state();
1324 Template
* Template::get_refd_sub_template(Ttcn::FieldOrArrayRefs
*subrefs
,
1326 ReferenceChain
*refch
)
1328 if (!subrefs
) return this;
1330 for (size_t i
=0; i
<subrefs
->get_nof_refs(); i
++) {
1332 t
=t
->get_template_refd_last(refch
);
1333 t
->set_lowerid_to_ref();
1334 switch(t
->templatetype
) {
1335 case TEMPLATE_ERROR
:
1338 case INDEXED_TEMPLATE_LIST
:
1341 case SPECIFIC_VALUE
:
1342 (void)t
->u
.specific_value
->get_refd_sub_value(
1343 subrefs
, i
, usedInIsbound
, refch
); // only to report errors
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
,
1352 else t
=t
->get_refd_array_template(ref
->get_val(), usedInIsbound
, refch
);
1357 Value
* Template::get_string_encoding() const
1359 if (templatetype
!= DECODE_MATCH
) {
1360 FATAL_ERROR("Template::get_decode_target()");
1362 return u
.dec_match
.str_enc
;
1365 TemplateInstance
* Template::get_decode_target() const
1367 if (templatetype
!= DECODE_MATCH
) {
1368 FATAL_ERROR("Template::get_decode_target()");
1370 return u
.dec_match
.target
;
1373 Template
* Template::get_template_refd(ReferenceChain
*refch
)
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
);
1389 // Why do we not set u.ref.refd_last ?
1391 else if (subrefs
&& subrefs
->has_unfoldable_index()) {
1392 // some array indices could not be evaluated
1394 u
.ref
.refd_last
= this;
1395 } else if (u
.ref
.ref
->getUsedInIsbound()) {
1397 u
.ref
.refd_last
= this;
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");
1409 set_templatetype(TEMPLATE_ERROR
);
1413 // the reference is unfoldable
1419 Template
* Template::get_refd_field_template(const Identifier
& field_id
,
1420 const Location
& loc
, bool usedInIsbound
, ReferenceChain
*refch
)
1422 switch (templatetype
) {
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());
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()) {
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());
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);
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 ");
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());
1474 return nt
->get_template();
1479 typetype_str
="record";
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());
1488 } else if (templatetype
!= NAMED_TEMPLATE_LIST
) {
1489 // this is an invalid matching mechanism
1490 // the error should be already reported
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
);
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());
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());
1516 Template
* Template::get_refd_array_template(Value
*array_index
,
1518 ReferenceChain
*refch
)
1520 switch (templatetype
) {
1525 case COMPLEMENTED_LIST
:
1526 case SUPERSET_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());
1536 Value
*v_index
= array_index
->get_value_refd_last(refch
);
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;
1544 array_index
->error("An integer value was expected as index");
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()) {
1555 typetype_str
="record";
1558 if (index_available
) {
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());
1565 } else if (templatetype
!= TEMPLATE_LIST
) {
1566 // remain silent the error has been already reported
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
);
1579 // the index is not available or the error has been reported above
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()))
1594 // remain silent, the error has been already reported
1598 // the index is not available or the error has been reported above
1603 array_index
->error("Invalid array element reference: type `%s' cannot "
1604 "be indexed", t
->get_typename().c_str());
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
);
1614 if(ret_val
->get_templatetype() == TEMPLATE_NOTUSED
)
1615 error("Not used symbol is not allowed in this context");
1618 } else return ret_val
;
1621 bool Template::temps_contains_anyornone_symbol() const
1623 switch (templatetype
) {
1625 case SUPERSET_MATCH
:
1627 case PERMUTATION_MATCH
:
1630 FATAL_ERROR("Template::temps_contains_anyornone_symbol()");
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
) {
1638 // 'all from' clauses not known at compile time are also considered
1641 case PERMUTATION_MATCH
:
1643 if (t
->temps_contains_anyornone_symbol()) return true;
1652 size_t Template::get_nof_comps_not_anyornone() const
1654 switch (templatetype
) {
1656 case SUPERSET_MATCH
:
1658 case PERMUTATION_MATCH
:
1661 FATAL_ERROR("Template::get_nof_comps_not_anyornone()");
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
) {
1672 case PERMUTATION_MATCH
:
1674 ret_val
+= t
->get_nof_comps_not_anyornone();
1677 // other types are counted as 1
1685 bool Template::pattern_contains_anyornone_symbol() const
1687 switch (templatetype
) {
1691 return u
.pattern
->find('*') < u
.pattern
->size();
1696 FATAL_ERROR("Template::pattern_contains_anyornone_symbol()");
1701 size_t Template::get_min_length_of_pattern() const
1704 switch (templatetype
) {
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
++;
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
]) {
1725 // count as 1 and skip over the next hex digit
1735 FATAL_ERROR("Template::get_min_length_of_pattern()");
1740 bool Template::is_Value() const
1742 if (length_restriction
|| is_ifpresent
) return false;
1743 switch (templatetype
) {
1744 case TEMPLATE_ERROR
:
1745 case TEMPLATE_NOTUSED
:
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;
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;
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;
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;
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
:
1793 Value
*Template::get_Value()
1796 switch(templatetype
) {
1797 case TEMPLATE_ERROR
:
1798 ret_val
= new Value(Value::V_ERROR
);
1800 case TEMPLATE_NOTUSED
:
1801 ret_val
= new Value(Value::V_NOTUSED
);
1804 ret_val
= new Value(Value::V_OMIT
);
1806 case SPECIFIC_VALUE
:
1807 ret_val
= u
.specific_value
;
1808 u
.specific_value
= 0;
1809 set_templatetype(TEMPLATE_ERROR
);
1811 case TEMPLATE_LIST
: {
1812 Values
*vs
= new Values
;
1813 size_t nof_ts
= u
.templates
->get_nof_ts();
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();
1820 ret_val
= new Value(Value::V_SEQOF
, vs
);
1821 if (gov
) gov
= gov
->get_parent_type();
1822 if (gov
) ret_val
->set_my_governor(gov
);
1824 case NAMED_TEMPLATE_LIST
: {
1825 NamedValues
*nvs
= new NamedValues
;
1826 size_t nof_nts
= u
.named_templates
->get_nof_nts();
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
);
1836 ret_val
= new Value(Value::V_SEQ
, nvs
);
1837 if (gov
) gov
= gov
->get_parent_type();
1838 if (gov
) ret_val
->set_my_governor(gov
);
1840 case INDEXED_TEMPLATE_LIST
: {
1841 Values
*ivs
= new Values(true);
1842 size_t nof_its
= u
.indexed_templates
->get_nof_its();
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
);
1852 ret_val
= new Value(Value::V_SEQOF
, ivs
);
1853 if (gov
) gov
= gov
->get_parent_type();
1854 if (gov
) ret_val
->set_my_governor(gov
);
1857 FATAL_ERROR("Template::get_Value()");
1861 ret_val
->set_location(*this);
1862 ret_val
->set_my_scope(get_my_scope());
1863 ret_val
->set_fullname(get_fullname());
1867 bool Template::is_Ref() const
1869 if (length_restriction
|| is_ifpresent
|| templatetype
!= SPECIFIC_VALUE
)
1871 Value
*v
= u
.specific_value
;
1872 switch (v
->get_valuetype()) {
1873 case Value::V_UNDEF_LOWERID
:
1876 if (dynamic_cast<Ref_base
*>(v
->get_reference())) return true;
1883 Ref_base
*Template::get_Ref()
1885 if (templatetype
!= SPECIFIC_VALUE
)
1886 FATAL_ERROR("Template::get_Ref()");
1887 return u
.specific_value
->steal_ttcn_ref_base();
1890 void Template::chk_recursions(ReferenceChain
& refch
)
1892 if (recurs_checked
) return;
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;
1898 t
->u
.ref
.ref
->get_refd_assignment(true); // make sure the parameter list is checked
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;
1905 t
->set_lowerid_to_ref();
1906 switch (t
->templatetype
) {
1907 case SPECIFIC_VALUE
:
1908 t
->u
.specific_value
->chk_recursions(refch
);
1912 case COMPLEMENTED_LIST
:
1913 case SUPERSET_MATCH
:
1915 case PERMUTATION_MATCH
:
1916 for (size_t i
= 0; i
< t
->u
.templates
->get_nof_ts(); i
++) {
1918 t
->u
.templates
->get_t_byIndex(i
)->chk_recursions(refch
);
1922 case NAMED_TEMPLATE_LIST
:
1923 for (size_t i
= 0; i
< t
->u
.named_templates
->get_nof_nts(); i
++) {
1925 t
->u
.named_templates
->get_nt_byIndex(i
)
1926 ->get_template()->chk_recursions(refch
);
1930 case INDEXED_TEMPLATE_LIST
:
1931 for (size_t i
= 0; i
< t
->u
.indexed_templates
->get_nof_its(); i
++) {
1933 t
->u
.indexed_templates
->get_it_byIndex(i
)
1934 ->get_template()->chk_recursions(refch
);
1940 t
->u
.pstring
->chk_recursions(refch
);
1943 t
->u
.dec_match
.target
->chk_recursions(refch
);
1949 recurs_checked
= true;
1952 void Template::chk_specific_value(bool allow_omit
)
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");
1958 chk_specific_value_generic();
1961 void Template::chk_specific_value_generic()
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
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
);
1981 case TEMPLATE_INVOKE
:
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();
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();
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();
2001 t
->error("A specific value was expected instead of %s",
2002 t
->get_templatetype_str());
2005 t
->specific_value_checked
= true;
2006 specific_value_checked
= true;
2009 void Template::chk_invoke()
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();
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
);
2023 if (u
.invoke
.v
->get_valuetype() != Value::V_ERROR
)
2024 u
.invoke
.v
->error("A value of type function was expected in the "
2026 set_templatetype(TEMPLATE_ERROR
);
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;
2037 u
.invoke
.ap_list
= 0;
2039 parlist
->set_fullname(get_fullname());
2040 parlist
->set_my_scope(get_my_scope());
2041 u
.invoke
.ap_list
= parlist
;
2045 Templates
*Template::harbinger(Template
*t
, bool from_permutation
, bool killer
)
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;
2061 // check for subreferences in the 'all from' target
2062 FieldOrArrayRefs
* subrefs
= ref
->get_subrefs();
2063 if (NULL
!= subrefs
) {
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();
2073 Common::Assignment
*ass
= ref
->get_refd_assignment();
2074 if (ass
== NULL
) { // perhaps erroneous
2078 Common::Assignment::asstype_t asst
= ass
->get_asstype();
2080 case Common::Assignment::A_TEMPLATE
: {
2081 Template
*tpl
= ass
->get_Template();
2082 // tpl is the template whose name appears after the "all from"
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
2101 if (can_flatten
&& !subref
->get_val()->is_unfoldable()) {
2102 switch(tpl
->get_templatetype()) {
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
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
2127 case INDEXED_TEMPLATE_LIST
:
2128 can_flatten
= false; // currently not supported
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
2139 // one of the array indexes is a reference => cannot flatten
2140 can_flatten
= false;
2142 type
= type
->get_ofType()->get_type_refd_last();
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());
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());
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
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
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
2191 type
= type
->get_comp_byName(*subref
->get_id())->get_type()->get_type_refd_last();
2195 if (NULL
!= tpl
) { // tpl is set to null if an error occurs
2197 Template::templatetype_t tpltt
= tpl
->get_templatetype();
2199 case INDEXED_TEMPLATE_LIST
: // currently not supported
2200 case TEMPLATE_REFD
: {
2201 delete new_templates
;
2209 size_t nvl
= tpl
->get_nof_comps();
2210 for (size_t ti
= 0; ti
< nvl
; ++ti
) {
2211 Template
*orig
= tpl
->get_temp_byIndex(ti
);
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;
2223 if (from_permutation
) {
2224 break; // AnyElementOrNone allowed in "all from" now
2227 case PERMUTATION_MATCH
:
2228 t
->error("'all from' can not refer to permutation or AnyElementsOrNone");
2229 t
->set_templatetype(TEMPLATE_ERROR
);
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
);
2243 // Cannot flatten at compile time
2244 delete new_templates
;
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()) {
2257 case PERMUTATION_MATCH
:
2258 t
->error("'all from' can not refer to permutation or AnyElementsOrNone");
2259 t
->set_templatetype(TEMPLATE_ERROR
);
2264 delete new_templates
;
2271 tpl
->error("Matching mechanism can not be used as target of 'all from'");
2274 tpl
->error("A template of type '%s' can not be used as target of 'all from'",
2275 type
->get_typename().c_str());
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
;
2288 type
->error("A template of type `%s' can not be used as target of 'all from'",
2289 type
->get_typename().c_str());
2291 } // switch(typetype)
2295 if (killer
) delete t
;
2299 case Common::Assignment::A_CONST
: { // all from a constant definition
2300 Common::Value
*val
= ass
->get_Value();
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());
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());
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'");
2338 // one of the array indexes is a reference => cannot flatten
2339 can_flatten
= false;
2341 type
= type
->get_ofType()->get_type_refd_last();
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());
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());
2361 type
= type
->get_comp_byName(*subref
->get_id())->get_type()->get_type_refd_last();
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'");
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");
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
: {
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
);
2395 delete new_templates
;
2402 type
->error("A constant of type `%s' can not be used as target of 'all from'",
2403 type
->get_typename().c_str());
2405 } // switch(typetype)
2407 if (killer
) delete t
;
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
:
2414 case Common::Assignment::A_PAR_TEMPL_IN
:
2415 case Common::Assignment::A_PAR_TEMPL_INOUT
:
2416 case Common::Assignment::A_PAR_TEMPL_OUT
:
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
:
2421 case Common::Assignment::A_PAR_VAL_INOUT
:
2422 case Common::Assignment::A_PAR_VAL_OUT
:
2423 case Common::Assignment::A_FUNCTION_RVAL
:
2424 case Common::Assignment::A_EXT_FUNCTION_RVAL
: {
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());
2440 type
= type
->get_ofType()->get_type_refd_last();
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());
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());
2460 type
= type
->get_comp_byName(*subref
->get_id())->get_type()->get_type_refd_last();
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
2472 // not an array type => error
2473 const char* ass_name
= ass
->get_assname();
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
:
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
:
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";
2496 case Common::Assignment::A_FUNCTION_RVAL
:
2497 descr
= "A function returning a value";
2499 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
2500 descr
= "An external function returning a template";
2502 case Common::Assignment::A_EXT_FUNCTION_RVAL
:
2503 descr
= "An external function returning a value";
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());
2512 } // switch(typetype)
2516 FATAL_ERROR("harbinger asst %d", asst
);
2522 FATAL_ERROR("unexpected all from inside all from");
2525 FATAL_ERROR("tt %d", t
->u
.all_from
->templatetype
);
2528 return new_templates
;
2531 bool Template::flatten(bool from_permutation
)
2533 switch (templatetype
) {
2536 case COMPLEMENTED_LIST
:
2537 case SUPERSET_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);
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
);
2560 new_templates
->add_t(t
); // transfer it unchanged
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);
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
2578 new_templates
->add_t(t
); // transfer it unchanged
2581 break; } // case ALL_FROM
2583 case PERMUTATION_MATCH
: {
2584 // permut inside a value list: { 1, permut(), 2 }
2585 flattened
&= t
->flatten(true);
2586 new_templates
->add_t(t
);
2590 // case COMPLEMENTED_LIST:
2591 // case SUPERSET_MATCH:
2592 // case SUBSET_MATCH:
2594 flattened
&=t
->flatten(false);
2595 new_templates
->add_t(t
);
2598 new_templates
->add_t(t
);
2601 t
= 0; // take it away from the original
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());
2611 case VALUE_LIST_ALL_FROM
: {
2612 Templates
*new_templates
= harbinger(this, from_permutation
, false);
2613 if (new_templates
) {
2615 // now we can change the type
2616 templatetype
= VALUE_LIST
;
2617 u
.templates
= new_templates
;
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
:
2628 case BSTR_PATTERN
: case HSTR_PATTERN
: case OSTR_PATTERN
:
2629 case CSTR_PATTERN
: case USTR_PATTERN
: case DECODE_MATCH
:
2633 set_fullname(get_fullname()); // recompute fullname (esp. for components)
2634 set_my_scope(get_my_scope());
2639 const char* Template::get_restriction_name(template_restriction_t tr
)
2651 FATAL_ERROR("Template::get_restriction_name()");
2656 template_restriction_t
Template::get_sub_restriction(
2657 template_restriction_t tr
, Ref_base
* ref
)
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();
2664 Type
* t
= ass
->get_Type();
2666 ReferenceChain
refch(ref
, "While checking template restriction");
2667 t
= t
->get_field_type(ref
->get_subrefs(), Type::EXPECTED_TEMPLATE
,
2669 if (t
) is_optional
= false;
2678 return is_optional
? TR_OMIT
: TR_VALUE
;
2680 return is_optional
? TR_NONE
: TR_PRESENT
;
2682 FATAL_ERROR("Template::get_sub_restriction()");
2687 bool Template::is_less_restrictive(template_restriction_t needed_tr
,
2688 template_restriction_t refd_tr
)
2690 switch (needed_tr
) {
2694 return refd_tr
!=TR_VALUE
;
2696 return refd_tr
!=TR_VALUE
&& refd_tr
!=TR_OMIT
;
2698 return refd_tr
!=TR_VALUE
&& refd_tr
!=TR_PRESENT
;
2700 FATAL_ERROR("Template::is_less_restrictive()");
2705 char* Template::generate_restriction_check_code(char* str
, const char* name
,
2706 template_restriction_t tr
)
2708 const char* tr_name
;
2713 tr_name
= "TR_OMIT";
2716 tr_name
= "TR_VALUE";
2719 tr_name
= "TR_PRESENT";
2722 FATAL_ERROR("Template::generate_restriction_check_code()");
2724 return mputprintf(str
, "%s.check_restriction(%s%s);\n", name
, tr_name
,
2725 (omit_in_value_list
? ", NULL, TRUE" : ""));
2728 // embedded templates -> check needed only for case of TR_OMIT
2729 bool Template::chk_restriction_named_list(const char* definition_name
,
2730 map
<string
, void>& checked_map
, size_t needed_checked_cnt
,
2731 const Location
* usage_loc
)
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
)) {
2742 bool nrc
= tmpl
->chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2743 needs_runtime_check
= needs_runtime_check
|| nrc
;
2744 checked_map
.add(name
, 0);
2747 if (base_template
) {
2748 bool nrc
= base_template
->chk_restriction_named_list(definition_name
,
2749 checked_map
, needed_checked_cnt
, usage_loc
);
2750 needs_runtime_check
= needs_runtime_check
|| nrc
;
2755 error("Restriction on %s does not allow usage of %s",
2756 definition_name
, get_templatetype_str());
2759 // others will be converted to specific value
2762 return needs_runtime_check
;
2765 bool Template::chk_restriction_refd(const char* definition_name
,
2766 template_restriction_t template_restriction
, const Location
* usage_loc
)
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();
2778 bool nrc
= t_last
->chk_restriction(definition_name
,
2779 template_restriction
, usage_loc
);
2780 needs_runtime_check
= needs_runtime_check
|| nrc
;
2783 case Common::Assignment::A_MODULEPAR_TEMP
:
2784 is_var_template
= true;
2785 refd_tr
= TR_NONE
; // can't place restriction on this thing
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();
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;
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();
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();
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());
2827 return needs_runtime_check
;
2830 bool Template::chk_restriction(const char* definition_name
,
2831 template_restriction_t template_restriction
,
2832 const Location
* usage_loc
)
2834 bool needs_runtime_check
= false;
2835 bool erroneous
= false;
2836 switch (template_restriction
) {
2841 if (length_restriction
) {
2842 usage_loc
->error("Restriction on %s does not allow usage of length "
2843 "restriction", definition_name
);
2847 usage_loc
->error("Restriction on %s does not allow usage of `ifpresent'",
2851 switch(templatetype
) {
2852 case TEMPLATE_ERROR
:
2854 case TEMPLATE_NOTUSED
:
2855 if (base_template
) {
2856 bool nrc
= base_template
->chk_restriction(definition_name
,
2857 template_restriction
, usage_loc
);
2858 needs_runtime_check
= needs_runtime_check
|| nrc
;
2860 else needs_runtime_check
= true;
2862 case SPECIFIC_VALUE
:
2863 case TEMPLATE_INVOKE
:
2865 case TEMPLATE_REFD
: {
2866 bool nrc
= chk_restriction_refd(definition_name
, template_restriction
,
2868 needs_runtime_check
= needs_runtime_check
|| nrc
;
2871 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2872 bool nrc
= u
.templates
->get_t_byIndex(i
)->
2873 chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2874 needs_runtime_check
= needs_runtime_check
|| nrc
;
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()) {
2886 case Type::T_SIGNATURE
:
2887 needed_checked_cnt
= my_governor
->get_nof_comps();
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()->
2895 chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2896 needs_runtime_check
= needs_runtime_check
|| nrc
;
2897 if (needed_checked_cnt
)
2899 u
.named_templates
->get_nt_byIndex(i
)->get_name().get_name(), 0);
2901 if (needed_checked_cnt
) {
2902 bool nrc
= base_template
->chk_restriction_named_list(definition_name
,
2903 checked_map
, needed_checked_cnt
, usage_loc
);
2904 needs_runtime_check
= needs_runtime_check
|| nrc
;
2905 checked_map
.clear();
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()->
2911 chk_restriction(definition_name
, TR_OMIT
, usage_loc
);
2912 needs_runtime_check
= needs_runtime_check
|| nrc
;
2914 needs_runtime_check
= true; // only basic check, needs runtime check
2917 if (template_restriction
==TR_OMIT
) break;
2918 // Else restriction is TR_VALUE, but template type is OMIT:
2919 // fall through to error.
2921 usage_loc
->error("Restriction on %s does not allow usage of %s",
2922 definition_name
, get_templatetype_str());
2929 usage_loc
->error("Restriction on %s does not allow usage of `ifpresent'",
2933 switch(templatetype
) {
2934 case TEMPLATE_REFD
: {
2935 bool nrc
= chk_restriction_refd(definition_name
, template_restriction
,
2937 needs_runtime_check
= needs_runtime_check
|| nrc
;
2940 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
2941 bool nrc
= u
.templates
->get_t_byIndex(i
)->
2942 chk_restriction(definition_name
, template_restriction
, usage_loc
);
2943 needs_runtime_check
= needs_runtime_check
|| nrc
;
2946 case COMPLEMENTED_LIST
:
2947 // some basic check, always needs runtime check
2948 needs_runtime_check
= true;
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;
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());
2969 usage_loc
->error("Restriction on %s does not allow usage of %s",
2970 definition_name
, get_templatetype_str());
2974 break; // all others are ok
2978 FATAL_ERROR("Template::chk_restriction()");
2980 if (erroneous
&& usage_loc
!= this) {
2981 // display the template's location, too
2982 note("Referenced template is here");
2984 return needs_runtime_check
;
2987 void Template::generate_code_expr(expression_struct
*expr
,
2988 template_restriction_t template_restriction
)
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());
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
, ')');
3009 // A simple unfoldable referenced template.
3010 if (!get_needs_conversion()) {
3011 u
.ref
.ref
->generate_code(expr
);
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(),
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
,
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
);
3043 case TEMPLATE_INVOKE
:
3044 generate_code_expr_invoke(expr
);
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();
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
);
3066 char *Template::generate_code_init(char *str
, const char *name
)
3068 if (get_code_generated()) return str
;
3069 set_code_generated();
3071 str
= err_descr
->generate_code_init_str(str
, string(name
)+"_err_descr");
3073 switch (templatetype
) {
3082 str
= mputprintf(str
, "%s = %s;\n", name
, get_single_expr(false).c_str());
3084 case SPECIFIC_VALUE
:
3085 if (get_code_section() == CS_POST_INIT
)
3086 str
= u
.specific_value
->rearrange_init_code(str
, my_scope
->get_scope_mod_gen());
3087 str
= u
.specific_value
->generate_code_init(str
, name
);
3090 str
= generate_code_init_refd(str
, name
);
3092 case TEMPLATE_INVOKE
:
3093 if (get_code_section() == CS_POST_INIT
)
3094 str
= rearrange_init_code_invoke(str
, my_scope
->get_scope_mod_gen());
3095 str
= generate_code_init_invoke(str
, name
);
3098 case INDEXED_TEMPLATE_LIST
:
3099 str
= generate_code_init_seof(str
, name
);
3101 case NAMED_TEMPLATE_LIST
:
3102 str
= generate_code_init_se(str
, name
);
3104 case VALUE_LIST_ALL_FROM
:
3105 str
= generate_code_init_all_from_list(str
, name
);
3108 str
= generate_code_init_all_from(str
, name
);
3111 str
= generate_code_init_list(str
, name
, false);
3113 case COMPLEMENTED_LIST
:
3114 str
= generate_code_init_list(str
, name
, true);
3117 if (get_code_section() == CS_POST_INIT
)
3118 str
= u
.value_range
->rearrange_init_code(str
, my_scope
->get_scope_mod_gen());
3119 str
= u
.value_range
->generate_code_init(str
, name
);
3121 case SUPERSET_MATCH
:
3122 str
= generate_code_init_set(str
, name
, true);
3125 str
= generate_code_init_set(str
, name
, false);
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
);
3132 str
= generate_code_init_dec_match(str
, name
);
3134 case TEMPLATE_NOTUSED
:
3136 case TEMPLATE_ERROR
:
3138 FATAL_ERROR("Template::generate_code_init()");
3140 if (length_restriction
) {
3141 if (get_code_section() == CS_POST_INIT
)
3142 str
= length_restriction
->rearrange_init_code(str
, my_scope
->get_scope_mod_gen());
3143 str
= length_restriction
->generate_code_init(str
, name
);
3145 if (is_ifpresent
) str
= mputprintf(str
, "%s.set_ifpresent();\n", name
);
3147 str
= mputprintf(str
, "%s.set_err_descr(&%s_err_descr);\n", name
, name
);
3152 char *Template::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
3154 switch (templatetype
) {
3155 case SPECIFIC_VALUE
:
3156 str
= u
.specific_value
->rearrange_init_code(str
, usage_mod
);
3159 str
= rearrange_init_code_refd(str
, usage_mod
);
3161 case TEMPLATE_INVOKE
:
3162 str
= rearrange_init_code_invoke(str
, usage_mod
);
3166 case COMPLEMENTED_LIST
:
3167 case SUPERSET_MATCH
:
3169 case PERMUTATION_MATCH
:
3170 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
3171 str
= u
.templates
->get_t_byIndex(i
)->rearrange_init_code(str
, usage_mod
);
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()
3176 ->rearrange_init_code(str
, usage_mod
);
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()
3181 ->rearrange_init_code(str
, usage_mod
);
3184 str
= u
.value_range
->rearrange_init_code(str
, usage_mod
);
3189 if (length_restriction
) str
= length_restriction
->rearrange_init_code(str
, usage_mod
);
3193 bool Template::use_single_expr_for_init()
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())
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()) {
3209 // do not calculate expressions again
3211 case Value::V_REFD
: {
3212 // v_last is an unfoldable value reference
3213 // the scope of the definition that v_last refers to
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;
3222 // otherwise return false
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();
3231 char *Template::generate_code_init_refd(char *str
, const char *name
)
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());
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();
3243 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
3244 // the reference points to (a field of) a template
3245 if (ass
->get_FormalParList()) {
3246 // the referred template is parameterized
3247 // generate the initialization sequence first for all dependent
3248 // non-parameterized templates
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()) {
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;
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
,
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
);
3282 str
= mputprintf(str
, "%s = %s;\n", name
, expr
.expr
);
3284 str
= mputstr(str
, expr
.postamble
);
3285 str
= mputstr(str
, "}\n");
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
,
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
);
3306 str
= mputprintf(str
, "%s = %s;\n", name
, expr
.expr
);
3309 Code::free_expr(&expr
);
3314 char *Template::generate_code_init_invoke(char *str
, const char *name
)
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
);
3323 char *Template::generate_rearrange_init_code_refd(char *str
,
3324 expression_struct
*expr
)
3326 /** Initially we can assume that:
3327 * - this is a referenced template and a part of a non-parameterized
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
;
3335 // first try to find the smallest dependent template
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();
3350 for (size_t i
= subrefs
->get_nof_refs(); i
> 0; i
--)
3351 refstack
.push(subrefs
->get_ref(i
- 1));
3353 // jump to the referred top-level template
3354 t
= ass
->get_Template();
3355 // start the iteration from the beginning
3357 // stop otherwise: the reference cannot be followed
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())
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
);
3381 // the topmost sub-reference was processed
3382 // it can be erased from the stack
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());
3397 expr
->expr
= mputc(expr
->expr
, '[');
3398 subref
->get_val()->generate_code_expr(expr
);
3399 expr
->expr
= mputc(expr
->expr
, ']');
3405 bool Template::compile_time() const
3407 switch (templatetype
) {
3409 case VALUE_LIST_ALL_FROM
:
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
3429 // "Complex" templates need to look at all elements
3432 case COMPLEMENTED_LIST
:
3433 case SUPERSET_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;
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())
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())
3452 return true; // not reached
3455 char *Template::generate_code_init_seof(char *str
, const char *name
)
3457 switch (templatetype
) {
3458 case TEMPLATE_LIST
: {
3459 size_t nof_ts
= u
.templates
->get_nof_ts();
3461 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3466 Type
*t_last
= my_governor
->get_type_refd_last();
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();
3472 // indexing always starts from zero
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();
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");
3484 if (compile_time()) goto compile_time
;
3485 // run-time, variable sized init
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
) {
3513 char* str_preamble
= 0;
3514 char* str_set_size
= mputprintf(0, "%s.set_size(%lu", name
,
3515 (unsigned long)fixed_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
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();
3532 str_set_size
= mputstrn(str_set_size
, " + ", 3);
3534 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
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
);
3542 ref_pard
->generate_code_cached(&expr
);
3543 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3545 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3547 Code::free_expr(&expr
);
3550 str_set_size
= mputstr (str_set_size
, ass
->get_id().get_name().c_str());
3552 expression_struct expr
;
3553 Code::init_expr(&expr
);
3555 subrefs
->generate_code(&expr
, ass
);
3556 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3558 Code::free_expr(&expr
);
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);
3580 str_set_size
= mputstr(str_set_size
, ".n_elem()");
3585 str
= mputstr(str
, str_preamble
);
3586 str
= mputstr(str
, str_set_size
);
3591 str
= mputstrn(str
, ");\n", 3); // finally done set_size
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
) {
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();
3615 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
3617 ref_pard
->generate_code_cached(&expr
);
3619 ref
->generate_code(&expr
);
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);
3642 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3649 FATAL_ERROR("ttype %d", permut_elem
->u
.all_from
->templatetype
);
3652 str
= mputprintf(str
,
3653 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3656 str
= permut_elem
->generate_code_init_seof_element(str
, name
,
3657 (Int2string(ix
) + skipper
+ " + i_i").c_str(),
3660 str
= mputstrn(str
, "}\n", 2);
3662 skipper
+= expr
.expr
;
3663 skipper
+= ".n_elem() /* 3005 */ ";
3664 Code::free_expr(&expr
);
3667 str
= permut_elem
->generate_code_init_seof_element(str
, name
,
3668 (Int2string(ix
) + skipper
).c_str(), oftype_name_str
);
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());
3676 t
->set_code_generated();
3677 index
+= nof_perm_ts
;
3681 str
= t
->generate_code_init_seof_element(str
, name
,
3682 (Int2string(index_offset
+ index
) + skipper
).c_str(), oftype_name_str
);
3684 case TEMPLATE_NOTUSED
:
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
) {
3705 char* str_preamble
= 0;
3706 char* str_set_size
= mputprintf(0, "%s.set_size(%lu", name
,
3707 (unsigned long)fixed_part
);
3710 for (size_t i
= 0, v
= variables
.size(); i
< v
; ++i
) {
3711 Template
*t
= u
.templates
->get_t_byIndex(variables
[i
]);
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
);
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
);
3728 ref_pard
->generate_code_cached(&expr
);
3729 str_set_size
= mputprintf(str_set_size
, "%s", expr
.expr
);
3731 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
3732 Code::free_expr(&expr
);
3735 str_set_size
= mputstr (str_set_size
, ass
->get_id().get_name().c_str());
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
);
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);
3763 str_set_size
= mputstr(str_set_size
, ".n_elem()");
3766 str
= mputstr(str
, str_preamble
);
3767 str
= mputstr(str
, str_set_size
);
3770 str
= mputstrn(str
, ");\n", 3); // finally done set_size
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
) {
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
);
3789 ref_pard
->generate_code_cached(&expr
);
3791 ref
->generate_code(&expr
);
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);
3814 FATAL_ERROR("vtype %d", spec
->get_valuetype());
3819 FATAL_ERROR("ttype %d", t
->u
.all_from
->templatetype
);
3822 str
= mputprintf(str
,
3823 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
3825 str
= t
->generate_code_init_seof_element(str
, name
,
3826 (Int2string(ix
) + skipper
+ " + i_i").c_str(),
3828 str
= mputstrn(str
, "}\n", 2);
3830 skipper
+= expr
.expr
;
3831 skipper
+= ".n_elem() ";
3832 Code::free_expr(&expr
);
3833 t
->set_code_generated();
3837 str
= t
->generate_code_init_seof_element(str
, name
,
3838 (Int2string(index_offset
+ index
) + skipper
).c_str(), oftype_name_str
);
3840 case TEMPLATE_NOTUSED
:
3851 // setting the size first
3853 str
= mputprintf(str
, "%s.set_size(%lu);\n", name
, (unsigned long) get_nof_listitems());
3854 // determining the index offset based on the governor
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
);
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
;
3876 str
= t
->generate_code_init_seof_element(str
, name
,
3877 Int2string(index_offset
+ index
).c_str(), oftype_name_str
);
3880 case TEMPLATE_NOTUSED
:
3885 case INDEXED_TEMPLATE_LIST
: {
3886 size_t nof_its
= u
.indexed_templates
->get_nof_its();
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
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());
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());
3911 str
= it
->get_template()->generate_code_init(str
, tmp_id_1
.c_str());
3912 str
= mputstr(str
, "}\n");
3915 // It seems to be impossible in this case.
3916 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
3920 FATAL_ERROR("Template::generate_code_init_seof()");
3926 char *Template::generate_code_init_seof_element(char *str
, const char *name
,
3927 const char* index
, const char *element_type_genname
)
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");
3937 char *embedded_name
= mprintf("%s[%s]", name
, index
);
3938 str
= generate_code_init(str
, embedded_name
);
3939 Free(embedded_name
);
3944 char *Template::generate_code_init_all_from(char *str
, const char *name
)
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
);
3957 ref_pard
->generate_code_cached(&expr
);
3959 ref
->generate_code(&expr
);
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);
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
);
3994 char *Template::generate_code_init_all_from_list(char *str
, const char *name
)
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
);
4007 ref_pard
->generate_code_cached(&expr
);
4009 ref
->generate_code(&expr
);
4012 FATAL_ERROR("vtype %d", spec
->get_valuetype());
4018 FATAL_ERROR("ttype %d", u
.all_from
->templatetype
);
4023 str
= mputstr(str
, expr
.preamble
);
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",
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);
4036 Code::free_expr(&expr
);
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;
4050 if (type
->get_typetype()==Type::T_ANYTYPE
) {
4051 at
+= fieldname
.get_name();
4052 fieldname_str
= at
.c_str();
4055 fieldname_str
= fieldname
.get_name().c_str();
4057 Template
*t
= nt
->get_template();
4058 if (t
->needs_temp_ref()) {
4060 if (type
->get_typetype() == Type::T_SIGNATURE
) {
4061 field_type
= type
->get_signature_parameters()
4062 ->get_param_byName(fieldname
)->get_type();
4064 field_type
= type
->get_comp_byName(fieldname
)->get_type();
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");
4075 char *embedded_name
= mprintf("%s.%s()", name
, fieldname_str
);
4076 str
= t
->generate_code_init(str
, embedded_name
);
4077 Free(embedded_name
);
4081 str
= mputprintf(str
, "%s = NULL_VALUE;\n", name
);
4086 char *Template::generate_code_init_list(char *str
, const char *name
,
4087 bool is_complemented
) // VALUE_LIST or COMPLEMENTED_LIST
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();
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
) {
4103 if (variables
.size() > 0) {
4104 char* str_preamble
= 0;
4105 char* str_set_type
= mprintf("%s.set_type(%s, %lu", name
,
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!");
4121 str_set_type
= mputstrn(str_set_type
, " + ", 3);
4123 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
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
);
4131 ref_pard
->generate_code_cached(&expr
);
4132 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4134 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
4136 Code::free_expr(&expr
);
4139 str_set_type
= mputstr (str_set_type
, ass
->get_id().get_name().c_str());
4141 expression_struct expr
;
4142 Code::init_expr(&expr
);
4144 subrefs
->generate_code(&expr
, ass
);
4145 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4147 Code::free_expr(&expr
);
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);
4169 str_set_type
= mputstr(str_set_type
, ".n_elem()");
4172 str
= mputstr(str
, str_preamble
);
4173 str
= mputstr(str
, str_set_type
);
4178 str
= mputstrn(str
, ");\n", 3);
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"
4184 // are shifted) is: target_of_all_from.n_elem()-1
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");
4192 expression_struct expr
;
4193 Code::init_expr(&expr
);
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
);
4203 ref_pard
->generate_code_cached(&expr
);
4205 ref
->generate_code(&expr
);
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);
4229 FATAL_ERROR("VT NOT HANDLED");
4230 } // switch valuetype
4234 FATAL_ERROR("ttype not handled");
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",
4243 if (t
->needs_temp_ref()) {
4244 // Not possible, because t->templatetype is ALL_FROM
4245 FATAL_ERROR("temp ref not handled");
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
);
4252 str
= mputstrn(str
, "}\n", 2);
4255 shifty
+= expr
.expr
;
4256 shifty
+= ".n_elem() /* 3303 */ ";
4258 Code::free_expr(&expr
);
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");
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
);
4277 } // switch t->templatetype
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");
4295 char *embedded_name
= mprintf("%s.list_item(%lu)", name
,
4297 str
= t
->generate_code_init(str
, embedded_name
);
4298 Free(embedded_name
);
4305 char *Template::generate_code_init_set(char *str
, const char *name
,
4306 bool is_superset
) // SUPERSET_MATCH and SUBSET_MATCH
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();
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
) {
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
);
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!");
4340 str_set_type
= mputstrn(str_set_type
, " + ", 3);
4342 Ref_pard
* ref_pard
= dynamic_cast<Ref_pard
*>(ref
);
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
);
4350 ref_pard
->generate_code_cached(&expr
);
4351 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4353 str_preamble
= mputstr(str_preamble
, expr
.preamble
);
4355 Code::free_expr(&expr
);
4358 str_set_type
= mputstr (str_set_type
, ass
->get_id().get_name().c_str());
4360 expression_struct expr
;
4361 Code::init_expr(&expr
);
4363 subrefs
->generate_code(&expr
, ass
);
4364 str_set_type
= mputprintf(str_set_type
, "%s", expr
.expr
);
4366 Code::free_expr(&expr
);
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);
4388 str_set_type
= mputstr(str_set_type
, ".n_elem()");
4391 str
= mputstr(str
, str_preamble
);
4392 str
= mputstr(str
, str_set_type
);
4397 str
= mputstrn(str
, ");\n", 3);
4400 for (size_t i
= 0; i
< nof_ts
; i
++) {
4401 Template
*t
= u
.templates
->get_t_byIndex(i
);
4402 switch (t
->templatetype
) {
4404 expression_struct expr
; // FIXME copypasta from init_list above !
4405 Code::init_expr(&expr
);
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
);
4415 ref_pard
->generate_code_cached(&expr
);
4417 ref
->generate_code(&expr
);
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);
4441 FATAL_ERROR("VT NOT HANDLED");
4442 } // switch valuetype
4446 FATAL_ERROR("ttype not handled");
4450 str
= mputprintf(str
,
4451 "for (int i_i = 0, i_lim = %s.n_elem(); i_i < i_lim; ++i_i) {\n",
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
);
4460 str
= mputstrn(str
, "}\n", 2);
4463 shifty
+= expr
.expr
;
4464 shifty
+= ".n_elem() /* 3442 */";
4465 Code::free_expr(&expr
);
4467 case VALUE_LIST_ALL_FROM
:
4468 FATAL_ERROR("Not possible");
4469 break; // not reached
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");
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
);
4487 } // switch t->templatetype
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");
4505 char *embedded_name
= mprintf("%s.set_item(%lu)", name
,
4507 str
= t
->generate_code_init(str
, embedded_name
);
4508 Free(embedded_name
);
4515 char* Template::generate_code_init_dec_match(char* str
, const char* name
)
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();
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
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"
4541 "val.decode(%s_descr_, buff, TTCN_EncDec::CT_%s);\n"
4542 // make sure the buffer is empty after decoding and no errors occurred
4543 "if (TTCN_EncDec::get_last_error_type() != TTCN_EncDec::ET_NONE || "
4544 "buff.get_read_len() != 0) return FALSE;\n"
4545 // finally, match the decoded value against the target template
4546 "return target.match(val%s);\n"
4548 "virtual void log() const\n"
4550 // the decoding target is always logged as an in-line template
4551 "TTCN_Logger::log_event_str(\"%s: \");\n"
4555 "%s.set_type(DECODE_MATCH);\n"
4556 "{\n", class_tmp_id
.c_str(),
4557 target_type
->get_genname_template(my_scope
).c_str(), class_tmp_id
.c_str(),
4558 target_type
->get_genname_template(my_scope
).c_str(),
4559 target_type
->get_genname_value(my_scope
).c_str(),
4560 target_type
->get_genname_typedescriptor(my_scope
).c_str(),
4561 target_type
->get_coding(false).c_str(),
4562 omit_in_value_list
? ", TRUE" : "", type_name
, name
);
4565 // generate the decoding target into a temporary
4566 string target_tmp_id
= my_scope
->get_scope_mod_gen()->get_temporary_id();
4567 if (u
.dec_match
.target
->get_DerivedRef() != NULL
) {
4568 // it's a derived reference: initialize the decoding target with the
4569 // base template first
4570 expression_struct ref_expr
;
4571 Code::init_expr(&ref_expr
);
4572 u
.dec_match
.target
->get_DerivedRef()->generate_code(&ref_expr
);
4573 if (ref_expr
.preamble
!= NULL
) {
4574 str
= mputstr(str
, ref_expr
.preamble
);
4576 str
= mputprintf(str
, "%s %s(%s);\n",
4577 target_type
->get_genname_template(my_scope
).c_str(),
4578 target_tmp_id
.c_str(), ref_expr
.expr
);
4579 if (ref_expr
.postamble
!= NULL
) {
4580 str
= mputstr(str
, ref_expr
.postamble
);
4582 Code::free_expr(&ref_expr
);
4585 str
= mputprintf(str
, "%s %s;\n",
4586 target_type
->get_genname_template(my_scope
).c_str(),
4587 target_tmp_id
.c_str());
4589 str
= u
.dec_match
.target
->get_Template()->generate_code_init(str
,
4590 target_tmp_id
.c_str());
4592 // the string encoding format might be an expression, generate its preamble here
4593 expression_struct coding_expr
;
4594 Code::init_expr(&coding_expr
);
4595 if (u
.dec_match
.str_enc
!= NULL
) {
4596 u
.dec_match
.str_enc
->generate_code_expr(&coding_expr
);
4597 if (coding_expr
.preamble
!= NULL
) {
4598 str
= mputstr(str
, coding_expr
.preamble
);
4601 // initialize the decmatch template with an instance of the new class
4602 // (pass the temporary template to the new instance's constructor) and
4603 // the encoding format if it's an universal charstring
4604 str
= mputprintf(str
,
4605 "%s.set_decmatch(new Dec_Match_%s(%s)%s%s);\n",
4606 name
, class_tmp_id
.c_str(), target_tmp_id
.c_str(),
4607 (coding_expr
.expr
!= NULL
) ? ", " : "",
4608 (coding_expr
.expr
!= NULL
) ? coding_expr
.expr
: "");
4609 if (coding_expr
.postamble
!= NULL
) {
4610 str
= mputstr(str
, coding_expr
.postamble
);
4612 Code::free_expr(&coding_expr
);
4613 str
= mputstr(str
, "}\n");
4617 void Template::generate_code_expr_invoke(expression_struct
*expr
)
4619 Value
*last_v
= u
.invoke
.v
->get_value_refd_last();
4620 if (last_v
->get_valuetype() == Value::V_FUNCTION
) {
4621 Common::Assignment
*function
= last_v
->get_refd_fat();
4622 expr
->expr
= mputprintf(expr
->expr
, "%s(",
4623 function
->get_genname_from_scope(my_scope
).c_str());
4624 u
.invoke
.ap_list
->generate_code_alias(expr
,
4625 function
->get_FormalParList(), function
->get_RunsOnType(), false);
4627 u
.invoke
.v
->generate_code_expr_mandatory(expr
);
4628 expr
->expr
= mputstr(expr
->expr
, ".invoke(");
4629 Type
* gov_last
= u
.invoke
.v
->get_expr_governor_last();
4630 u
.invoke
.ap_list
->generate_code_alias(expr
, 0,
4631 gov_last
->get_fat_runs_on_type(), gov_last
->get_fat_runs_on_self());
4633 expr
->expr
= mputc(expr
->expr
, ')');
4636 char *Template::rearrange_init_code_refd(char *str
, Common::Module
* usage_mod
)
4638 if (templatetype
!= TEMPLATE_REFD
)
4639 FATAL_ERROR("Template::rearrange_init_code_refd()");
4640 ActualParList
*actual_parlist
= u
.ref
.ref
->get_parlist();
4641 // generate code for the templates that are used in the actual parameter
4642 // list of the reference
4643 Common::Assignment
*ass
= u
.ref
.ref
->get_refd_assignment();
4644 if (actual_parlist
) str
= actual_parlist
->rearrange_init_code(str
, usage_mod
);
4645 // do nothing if the reference does not point to a template definition
4646 if (ass
->get_asstype() != Common::Assignment::A_TEMPLATE
) return str
;
4647 Template
*t
= ass
->get_Template();
4648 FormalParList
*formal_parlist
= ass
->get_FormalParList();
4649 if (formal_parlist
) {
4650 // the reference points to a parameterized template
4651 // we must perform the rearrangement for all non-parameterized templates
4652 // that are referred by the parameterized template regardless of the
4653 // sub-references of u.ref.ref
4654 str
= t
->rearrange_init_code(str
, usage_mod
);
4655 // the parameterized template's default values must also be generated
4656 // (this only generates their value assignments, their declarations will
4657 // be generated when the template's definition is reached)
4658 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
4659 str
= formal_parlist
->generate_code_defval(str
);
4662 // the reference points to a non-parameterized template
4663 FieldOrArrayRefs
*subrefs
= u
.ref
.ref
->get_subrefs();
4665 // we should follow the sub-references as much as we can
4666 // and perform the rearrangement for the referred field only
4667 for (size_t i
= 0; i
< subrefs
->get_nof_refs(); i
++) {
4668 FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
4669 if (ref
->get_type() == FieldOrArrayRef::FIELD_REF
) {
4670 // stop if the body does not have fields
4671 if (t
->templatetype
!= NAMED_TEMPLATE_LIST
) break;
4672 // get the sub-template of the referred field
4673 t
= t
->u
.named_templates
->get_nt_byName(*ref
->get_id())
4676 // stop if the body is not a list
4677 if (t
->templatetype
!= TEMPLATE_LIST
) break;
4678 Value
*array_index
= ref
->get_val()->get_value_refd_last();
4679 // stop if the index cannot be evaluated at compile time
4680 if (array_index
->get_valuetype() != Value::V_INT
) break;
4681 Int index
= array_index
->get_val_Int()->get_val();
4682 // index transformation in case of arrays
4683 if (t
->my_governor
->get_typetype() == Type::T_ARRAY
)
4684 index
-= t
->my_governor
->get_dimension()->get_offset();
4685 // get the template with the given index
4686 t
= t
->get_listitem_byIndex(index
);
4690 // otherwise if the reference points to a top-level template
4691 // we should initialize its entire body
4692 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
4693 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
4699 char *Template::rearrange_init_code_invoke(char *str
, Common::Module
* usage_mod
)
4701 str
= u
.invoke
.v
->rearrange_init_code(str
, usage_mod
);
4702 str
= u
.invoke
.ap_list
->rearrange_init_code(str
, usage_mod
);
4706 bool Template::needs_temp_ref()
4708 if (length_restriction
|| is_ifpresent
) return true;
4709 switch (templatetype
) {
4713 case SPECIFIC_VALUE
:
4715 case TEMPLATE_INVOKE
:
4721 case TEMPLATE_NOTUSED
:
4724 // temporary reference is needed if the template has at least one
4725 // element (excluding not used symbols)
4726 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++) {
4727 if (u
.templates
->get_t_byIndex(i
)->templatetype
!= TEMPLATE_NOTUSED
)
4731 case INDEXED_TEMPLATE_LIST
:
4732 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++) {
4733 if (u
.indexed_templates
->get_it_byIndex(i
)->get_template()
4734 ->templatetype
!= TEMPLATE_NOTUSED
)
4738 case NAMED_TEMPLATE_LIST
:
4739 return u
.named_templates
->get_nof_nts() > 1;
4741 case VALUE_LIST_ALL_FROM
:
4744 case COMPLEMENTED_LIST
:
4746 case SUPERSET_MATCH
:
4750 case TEMPLATE_ERROR
:
4751 FATAL_ERROR("Template::needs_temp_ref()");
4752 case PERMUTATION_MATCH
:
4759 bool Template::has_single_expr()
4761 if (length_restriction
|| is_ifpresent
|| get_needs_conversion())
4763 switch (templatetype
) {
4772 case TEMPLATE_NOTUSED
:
4774 case SPECIFIC_VALUE
:
4775 return u
.specific_value
->has_single_expr();
4776 case TEMPLATE_REFD
: {
4777 Template
*t_last
= get_template_refd_last();
4778 if (t_last
!= this && t_last
->has_single_expr()) {
4779 for (Scope
*t_scope
= my_scope
; t_scope
;
4780 t_scope
= t_scope
->get_parent_scope()) {
4781 // return true if t_last is visible from my scope
4782 if (t_scope
== t_last
->my_scope
) return true;
4785 // otherwise consider the reference itself
4786 return u
.ref
.ref
->has_single_expr(); }
4787 case TEMPLATE_INVOKE
:
4788 if (!u
.invoke
.v
->has_single_expr()) return false;
4789 for (size_t i
= 0; i
< u
.invoke
.ap_list
->get_nof_pars(); i
++)
4790 if (!u
.invoke
.ap_list
->get_par(i
)->has_single_expr()) return false;
4793 return u
.templates
->get_nof_ts() == 0;
4794 case NAMED_TEMPLATE_LIST
: {
4795 if (!my_governor
) FATAL_ERROR("Template::has_single_expr()");
4796 Type
*type
= my_governor
->get_type_refd_last();
4797 return type
->get_nof_comps() == 0; }
4798 case INDEXED_TEMPLATE_LIST
:
4799 return u
.indexed_templates
->get_nof_its() == 0;
4801 case COMPLEMENTED_LIST
:
4803 case SUPERSET_MATCH
:
4805 case PERMUTATION_MATCH
:
4809 case VALUE_LIST_ALL_FROM
:
4812 FATAL_ERROR("Template::has_single_expr()");
4817 string
Template::get_single_expr(bool cast_needed
)
4819 if (cast_needed
&& (length_restriction
|| is_ifpresent
))
4820 FATAL_ERROR("Template::get_single_expr()");
4822 switch (templatetype
) {
4824 ret_val
= "OMIT_VALUE";
4827 ret_val
= "ANY_VALUE";
4830 ret_val
= "ANY_OR_OMIT";
4832 case SPECIFIC_VALUE
:
4833 ret_val
= u
.specific_value
->get_single_expr();
4835 case TEMPLATE_REFD
: {
4836 // convert the reference to a single expression
4837 expression_struct expr
;
4838 Code::init_expr(&expr
);
4839 u
.ref
.ref
->generate_code(&expr
);
4840 if (expr
.preamble
|| expr
.postamble
)
4841 FATAL_ERROR("Template::get_single_expr()");
4842 ret_val
= expr
.expr
;
4843 Code::free_expr(&expr
);
4846 case TEMPLATE_INVOKE
: {
4847 expression_struct expr
;
4848 Code::init_expr(&expr
);
4849 generate_code_expr_invoke(&expr
);
4850 if (expr
.preamble
|| expr
.postamble
)
4851 FATAL_ERROR("Template::get_single_expr()");
4852 ret_val
= expr
.expr
;
4853 Code::free_expr(&expr
);
4856 if (u
.templates
->get_nof_ts() != 0)
4857 FATAL_ERROR("Template::get_single_expr()");
4858 ret_val
= "NULL_VALUE";
4860 case NAMED_TEMPLATE_LIST
:
4861 if (u
.named_templates
->get_nof_nts() != 0)
4862 FATAL_ERROR("Template::get_single_expr()");
4863 ret_val
= "NULL_VALUE";
4865 case INDEXED_TEMPLATE_LIST
:
4866 if (u
.indexed_templates
->get_nof_its() != 0)
4867 FATAL_ERROR("Template::get_single_expr()");
4868 ret_val
= "NULL_VALUE";
4871 return get_my_scope()->get_scope_mod_gen()
4872 ->add_bitstring_pattern(*u
.pattern
);
4874 return get_my_scope()->get_scope_mod_gen()
4875 ->add_hexstring_pattern(*u
.pattern
);
4877 return get_my_scope()->get_scope_mod_gen()
4878 ->add_octetstring_pattern(*u
.pattern
);
4882 ->create_charstring_literals(get_my_scope()->get_scope_mod_gen());
4884 FATAL_ERROR("Template::get_single_expr()");
4886 if (cast_needed
) ret_val
= my_governor
->get_genname_template(my_scope
) +
4887 "(" + ret_val
+ ")";
4891 void Template::dump(unsigned level
) const
4893 DEBUG(level
, "%s", get_templatetype_str());
4894 switch (templatetype
) {
4895 case TEMPLATE_ERROR
:
4900 case SPECIFIC_VALUE
:
4901 u
.specific_value
->dump(level
+1);
4904 u
.ref
.ref
->dump(level
+1);
4906 case TEMPLATE_INVOKE
:
4907 u
.invoke
.v
->dump(level
+1);
4908 if (u
.invoke
.ap_list
) u
.invoke
.ap_list
->dump(level
+ 1);
4909 else if (u
.invoke
.t_list
) u
.invoke
.t_list
->dump(level
+ 1);
4913 case COMPLEMENTED_LIST
:
4914 case SUPERSET_MATCH
:
4916 case PERMUTATION_MATCH
:
4917 for (size_t i
= 0; i
< u
.templates
->get_nof_ts(); i
++)
4918 u
.templates
->get_t_byIndex(i
)->dump(level
+1);
4920 case NAMED_TEMPLATE_LIST
:
4921 for (size_t i
= 0; i
< u
.named_templates
->get_nof_nts(); i
++)
4922 u
.named_templates
->get_nt_byIndex(i
)->dump(level
+1);
4924 case INDEXED_TEMPLATE_LIST
:
4925 for (size_t i
= 0; i
< u
.indexed_templates
->get_nof_its(); i
++)
4926 u
.indexed_templates
->get_it_byIndex(i
)->dump(level
+1);
4929 u
.value_range
->dump(level
);
4934 DEBUG(level
+1, "%s", u
.pattern
->c_str());
4938 u
.pstring
->dump(level
+1);
4941 case VALUE_LIST_ALL_FROM
:
4942 u
.all_from
->dump(level
+1);
4945 if (u
.dec_match
.str_enc
!= NULL
) {
4946 DEBUG(level
, "string encoding:");
4947 u
.dec_match
.str_enc
->dump(level
+ 1);
4949 DEBUG(level
, "decoding target:");
4950 u
.dec_match
.target
->dump(level
+ 1);
4955 if (length_restriction
) length_restriction
->dump(level
+ 1);
4958 bool Template::has_allfrom() const
4959 { // the code generation of all from is not fully implemented. This helps avoid of using it.
4960 if (templatetype
!= TEMPLATE_LIST
) FATAL_ERROR("has_allfrom(): Templatetype shall be TEMPLATE_LIST");
4961 size_t nof_ts
= u
.templates
->get_nof_ts();
4962 for (size_t i
= 0; i
< nof_ts
; i
++) {
4963 if (u
.templates
->get_t_byIndex(i
)->templatetype
== ALL_FROM
) {
4970 // =================================
4971 // ===== TemplateInstance
4972 // =================================
4974 TemplateInstance::TemplateInstance(const TemplateInstance
& p
)
4975 : Node(p
), Location(p
)
4977 type
= p
.type
? p
.type
->clone() : 0;
4978 derived_reference
= p
.derived_reference
? p
.derived_reference
->clone() : 0;
4979 template_body
= p
.template_body
->clone();
4982 TemplateInstance::TemplateInstance(Type
*p_type
, Ref_base
*p_ref
,
4983 Template
*p_body
) : Node(), Location(), type(p_type
),
4984 derived_reference(p_ref
), template_body(p_body
)
4986 if (!p_body
) FATAL_ERROR("TemplateInstance::TemplateInstance()");
4987 if (type
) type
->set_ownertype(Type::OT_TEMPLATE_INST
, this);
4990 TemplateInstance::~TemplateInstance()
4993 delete derived_reference
;
4994 delete template_body
;
4997 void TemplateInstance::release()
5000 derived_reference
= 0;
5004 TemplateInstance
*TemplateInstance::clone() const
5006 return new TemplateInstance(*this);
5009 void TemplateInstance::set_fullname(const string
& p_fullname
)
5011 Node::set_fullname(p_fullname
);
5012 if (type
) type
->set_fullname(p_fullname
+ ".<type>");
5013 if (derived_reference
)
5014 derived_reference
->set_fullname(p_fullname
+ ".<derived_reference>");
5015 template_body
->set_fullname(p_fullname
);
5018 void TemplateInstance::set_my_scope(Scope
*p_scope
)
5020 if (type
) type
->set_my_scope(p_scope
);
5021 if (derived_reference
) derived_reference
->set_my_scope(p_scope
);
5022 template_body
->set_my_scope(p_scope
);
5025 Type::typetype_t
TemplateInstance::get_expr_returntype
5026 (Type::expected_value_t exp_val
)
5028 Type
*t
= get_expr_governor(exp_val
);
5029 if (t
) return t
->get_type_refd_last()->get_typetype_ttcn3();
5030 else return template_body
->get_expr_returntype(exp_val
);
5033 Type
*TemplateInstance::get_expr_governor(Type::expected_value_t exp_val
)
5035 if (type
) return type
;
5036 if (derived_reference
) {
5037 Type
*ret_val
= chk_DerivedRef(0);
5038 if (ret_val
) return ret_val
;
5040 return template_body
->get_expr_governor(exp_val
);
5043 void TemplateInstance::chk(Type
*governor
)
5045 if (!governor
) FATAL_ERROR("TemplateInstance::chk()");
5046 governor
= chk_Type(governor
);
5047 governor
= chk_DerivedRef(governor
);
5048 template_body
->set_my_governor(governor
);
5049 governor
->chk_this_template_ref(template_body
);
5050 governor
->chk_this_template_generic(template_body
,
5051 (derived_reference
!= 0 ? INCOMPLETE_ALLOWED
: INCOMPLETE_NOT_ALLOWED
),
5052 OMIT_ALLOWED
, ANY_OR_OMIT_ALLOWED
, SUB_CHK
, NOT_IMPLICIT_OMIT
, 0);
5055 Type
*TemplateInstance::chk_Type(Type
*governor
)
5057 if (!type
) return governor
;
5059 Error_Context
cntxt(type
, "In explicit type specification");
5062 TypeCompatInfo
info(template_body
->get_template_refd_last()
5063 ->get_my_scope()->get_scope_mod(), governor
, type
,
5067 if (!governor
) return type
;
5068 else if (governor
->is_compatible(type
, &info
, &l_chain
, &r_chain
, true)) {
5071 if (info
.is_subtype_error()) {
5072 type
->error("%s", info
.get_subtype_error().c_str());
5074 if (!info
.is_erroneous()) {
5075 type
->error("Incompatible explicit type specification: `%s' was "
5076 "expected instead of `%s'",
5077 governor
->get_typename().c_str(),
5078 type
->get_typename().c_str());
5080 type
->error("%s", info
.get_error_str_str().c_str());
5086 Type
*TemplateInstance::chk_DerivedRef(Type
*governor
)
5088 if (!derived_reference
) return governor
;
5089 Error_Context
cntxt(derived_reference
, "In derived reference");
5090 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
5091 // the base template reference must not have sub-references
5092 if (derived_reference
->get_subrefs())
5093 FATAL_ERROR("TemplateInstance::chk_DerivedRef()");
5094 bool set_bt
= false;
5095 if (!ass
) goto error
;
5096 switch (ass
->get_asstype()) {
5097 case Common::Assignment::A_TEMPLATE
:
5100 case Common::Assignment::A_MODULEPAR_TEMP
:
5101 case Common::Assignment::A_VAR_TEMPLATE
:
5102 case Common::Assignment::A_PAR_TEMPL_IN
:
5103 case Common::Assignment::A_PAR_TEMPL_OUT
:
5104 case Common::Assignment::A_PAR_TEMPL_INOUT
:
5105 case Common::Assignment::A_FUNCTION_RTEMP
:
5106 case Common::Assignment::A_EXT_FUNCTION_RTEMP
: {
5107 if (!governor
) governor
= type
;
5108 Type
*base_template_type
= ass
->get_Type();
5110 TypeCompatInfo
info(template_body
->get_template_refd_last()
5111 ->get_my_scope()->get_scope_mod(), governor
, type
,
5115 if (!governor
->is_compatible(base_template_type
, &info
, &l_chain
,
5117 if (info
.is_subtype_error()) {
5118 derived_reference
->error("%s", info
.get_subtype_error().c_str());
5120 if (!info
.is_erroneous()) {
5121 derived_reference
->error("Base template `%s' has incompatible "
5122 "type: `%s' was expected instead of `%s'",
5123 ass
->get_fullname().c_str(),
5124 governor
->get_typename().c_str(),
5125 base_template_type
->get_typename().c_str());
5127 derived_reference
->error("%s", info
.get_error_str_str().c_str());
5129 // if explicit type specification is omitted
5130 // check the template body against the type of the base template
5131 if (!type
) governor
= base_template_type
;
5134 if (info
.needs_conversion())
5135 template_body
->set_needs_conversion();
5137 } else governor
= base_template_type
;
5140 derived_reference
->error("Reference to a template was expected instead "
5141 "of %s", ass
->get_description().c_str());
5144 if (set_bt
) template_body
->set_base_template(ass
->get_Template());
5147 // drop the erroneous derived_reference to avoid further errors
5148 delete derived_reference
;
5149 derived_reference
= 0;
5153 void TemplateInstance::chk_recursions(ReferenceChain
& refch
)
5155 template_body
->chk_recursions(refch
);
5158 bool TemplateInstance::is_string_type(Type::expected_value_t exp_val
)
5160 switch (get_expr_returntype(exp_val
)) {
5172 bool TemplateInstance::chk_restriction(const char* definition_name
,
5173 template_restriction_t template_restriction
, const Location
* usage_loc
)
5175 bool needs_runtime_check
= false;
5176 if (derived_reference
) // if modified
5178 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
5179 switch (ass
->get_asstype()) {
5180 case Common::Assignment::A_TEMPLATE
:
5181 // already added to template_body as base template by chk_DerivedRef()
5182 needs_runtime_check
= template_body
->chk_restriction(
5183 definition_name
, template_restriction
, usage_loc
);
5185 case Common::Assignment::A_MODULEPAR_TEMP
:
5186 case Common::Assignment::A_VAR_TEMPLATE
:
5187 case Common::Assignment::A_EXT_FUNCTION_RTEMP
:
5188 case Common::Assignment::A_FUNCTION_RTEMP
:
5189 case Common::Assignment::A_PAR_TEMPL_IN
:
5190 case Common::Assignment::A_PAR_TEMPL_OUT
:
5191 case Common::Assignment::A_PAR_TEMPL_INOUT
: {
5192 // create a temporary Template to be added as the base template and
5193 // check, remove and delete after checked
5194 if (template_body
->get_base_template())
5195 FATAL_ERROR("TemplateInstance::chk_restriction()");
5196 template_body
->set_base_template(new Template(derived_reference
));
5197 needs_runtime_check
= template_body
->chk_restriction(
5198 definition_name
, template_restriction
, usage_loc
);
5199 delete template_body
->get_base_template();
5200 template_body
->set_base_template(0);
5206 needs_runtime_check
= template_body
->chk_restriction(definition_name
,
5207 template_restriction
, usage_loc
);
5209 return needs_runtime_check
;
5212 bool TemplateInstance::has_single_expr()
5214 if (derived_reference
) return false;
5215 else if (type
) return false;
5216 else return template_body
->has_single_expr();
5219 void TemplateInstance::set_code_section(
5220 GovernedSimple::code_section_t p_code_section
)
5222 if (derived_reference
) derived_reference
->set_code_section(p_code_section
);
5223 template_body
->set_code_section(p_code_section
);
5226 bool TemplateInstance::needs_temp_ref()
5228 if (template_body
->get_templatetype() != Template::SPECIFIC_VALUE
)
5230 Value
*val
= template_body
->get_specific_value();
5231 if (val
->get_valuetype() == Value::V_REFD
) {
5232 FieldOrArrayRefs
*refs
= val
->get_reference()->get_subrefs();
5233 if (!refs
) return false;
5234 // We need at least a 2-long reference chain. E.g. "a[0].b". 3.0.4
5235 // can't handle a normal reference following an indexed reference. The
5236 // indexed reference must be on the first place. Code like: "a.b[0].c"
5238 if (refs
->get_nof_refs() < 2
5239 || refs
->get_ref(0)->get_type() != FieldOrArrayRef::ARRAY_REF
)
5247 void TemplateInstance::generate_code(expression_struct
*expr
,
5248 template_restriction_t template_restriction
)
5250 if (derived_reference
) {
5251 // preserve the target expression
5252 char *expr_backup
= expr
->expr
;
5253 // reset the space for the target expression
5255 derived_reference
->generate_code(expr
);
5256 // now the C++ equivalent of the base template reference is in expr->expr
5257 const string
& tmp_id
= template_body
->get_temporary_id();
5258 const char *tmp_id_str
= tmp_id
.c_str();
5259 // create a temporary variable and copy the contents of base template
5261 expr
->preamble
= mputprintf(expr
->preamble
, "%s %s(%s);\n",
5262 template_body
->get_my_governor()->get_genname_template(
5263 template_body
->get_my_scope()).c_str(), tmp_id_str
, expr
->expr
);
5264 // perform the modifications on the temporary variable
5265 expr
->preamble
= template_body
->generate_code_init(expr
->preamble
,
5267 // runtime template restriction check
5268 if (template_restriction
!=TR_NONE
)
5269 expr
->preamble
= Template::generate_restriction_check_code(
5270 expr
->preamble
, tmp_id_str
, template_restriction
);
5271 // the base template reference is no longer needed
5273 // restore the target expression append the name of the temporary
5275 expr
->expr
= mputstr(expr_backup
, tmp_id_str
);
5276 } else template_body
->generate_code_expr(expr
, template_restriction
);
5279 char *TemplateInstance::rearrange_init_code(char *str
, Common::Module
* usage_mod
)
5281 if (derived_reference
) {
5282 ActualParList
*actual_parlist
= derived_reference
->get_parlist();
5283 Common::Assignment
*ass
= derived_reference
->get_refd_assignment();
5284 if (!ass
) FATAL_ERROR("TemplateInstance::rearrange_init_code()");
5285 if (actual_parlist
) str
= actual_parlist
->rearrange_init_code(str
, usage_mod
);
5286 if (ass
->get_asstype() == Common::Assignment::A_TEMPLATE
) {
5287 Template
*t
= ass
->get_Template();
5288 FormalParList
*formal_parlist
= ass
->get_FormalParList();
5289 if (formal_parlist
) {
5290 // the referred template is parameterized
5291 // the embedded referenced templates shall be visited
5292 str
= t
->rearrange_init_code(str
, usage_mod
);
5293 // the constants used for default values have to be initialized now
5294 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
5295 str
= formal_parlist
->generate_code_defval(str
);
5298 // the referred template is not parameterized
5299 // its entire body has to be initialized now
5300 if (ass
->get_my_scope()->get_scope_mod_gen() == usage_mod
) {
5301 str
= t
->generate_code_init(str
, t
->get_lhs_name().c_str());
5306 str
= template_body
->rearrange_init_code(str
, usage_mod
);
5310 void TemplateInstance::append_stringRepr(string
& str
) const
5313 str
+= type
->get_typename();
5316 if (derived_reference
) {
5318 str
+= derived_reference
->get_dispname();
5321 str
+= template_body
->get_stringRepr();
5324 void TemplateInstance::dump(unsigned level
) const
5327 DEBUG(level
, "type:");
5328 type
->dump(level
+ 1);
5330 if (derived_reference
) {
5331 DEBUG(level
, "modifies:");
5332 derived_reference
->dump(level
+ 1);
5334 template_body
->dump(level
);
5337 Value
* TemplateInstance::get_specific_value() const
5339 if (type
) return NULL
;
5340 if (derived_reference
) return NULL
;
5341 if (template_body
->is_length_restricted() || template_body
->get_ifpresent())
5343 if (template_body
->get_templatetype()!=Template::SPECIFIC_VALUE
) return NULL
;
5344 return template_body
->get_specific_value();
5347 Def_Template
* TemplateInstance::get_Referenced_Base_Template()
5348 { // it may return 0
5349 if (!get_Template()) return NULL
;
5350 Ttcn::Template::templatetype_t tpt
= get_Template()->get_templatetype();
5351 if (Ttcn::Template::TEMPLATE_REFD
!= tpt
) return NULL
;
5352 Ttcn::Ref_base
* refbase
= get_Template()->get_reference();
5353 Ttcn::Reference
* ref
= dynamic_cast<Ttcn::Reference
*>(refbase
);
5354 if (!ref
) return NULL
;
5355 Common::Assignment
* ass
= ref
->get_refd_assignment();
5356 Ttcn::Definition
* def
= dynamic_cast<Ttcn::Definition
*>(ass
);
5357 if (!def
) return NULL
;
5358 Ttcn::Def_Template
* deftemp
= dynamic_cast<Ttcn::Def_Template
*>(def
);
5359 if (!deftemp
) return NULL
;