1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include "../common/dbgnew.hh"
10 #include "CompField.hh"
11 #include "EnumItem.hh"
12 #include "SigParam.hh"
18 #include "record_of.h"
19 #include "functionref.h"
22 #include "ttcn3/Ttcnstuff.hh"
23 #include "ttcn3/ArrayDimensions.hh"
24 #include "ttcn3/Attributes.hh"
25 #include "ttcn3/signature.h"
26 #include "XerAttributes.hh"
28 #include "asn1/TableConstraint.hh"
29 #include "asn1/Object.hh"
30 #include "asn1/Tag.hh"
31 #include "asn1/Ref.hh"
33 #include "CodeGenHelper.hh"
35 #include "../common/JSON_Tokenizer.hh"
40 using Ttcn::SingleWithAttrib
;
42 void Type::generate_code(output_struct
*target
)
44 if (code_generated
) return;
45 generate_code_embedded_before(target
);
46 // escape from recursion loops
47 if (code_generated
) return;
48 code_generated
= true;
49 generate_code_typedescriptor(target
);
50 string sourcefile
= get_sourcefile_attribute();
51 if (!sourcefile
.empty()) {
52 generate_code_include(sourcefile
, target
);
57 generate_code_Enum(target
);
63 generate_code_Choice(target
);
69 generate_code_Se(target
);
73 generate_code_SeOf(target
);
76 u
.port
->generate_code(target
);
79 generate_code_Array(target
);
82 generate_code_Signature(target
);
87 generate_code_Fat(target
);
90 generate_code_alias(target
);
94 generate_code_embedded_after(target
);
96 if (has_done_attribute()) generate_code_done(target
);
97 if (sub_type
) sub_type
->generate_code(*target
);
101 void Type::generate_code_include(const string
& sourcefile
, output_struct
*target
)
103 const char* name
= get_genname_own().c_str();
104 const char* dispname
= get_fullname().c_str();
105 target
->header
.class_decls
= mputprintf(target
->header
.class_decls
,
107 "class %s_template;\n",
110 target
->header
.class_defs
= mputprintf(target
->header
.class_defs
,
111 "// Implementation of type %s\n"
112 "#include \"%s.hh\"\n",
113 dispname
, sourcefile
.c_str());
116 void Type::generate_code_embedded_before(output_struct
*target
)
123 size_t nof_comps
= get_nof_comps();
124 for (size_t i
= 0; i
< nof_comps
; i
++) {
125 CompField
*cf
= get_comp_byIndex(i
);
126 if (!cf
->get_is_optional()) {
127 // generate code for mandatory record/set fields only
128 cf
->get_type()->generate_code(
129 CodeGenHelper::GetInstance().get_outputstruct(
130 cf
->get_type()->get_type_refd_last()
133 CodeGenHelper::GetInstance().finalize_generation(
134 cf
->get_type()->get_type_refd_last()
136 // escape from recursion loops
137 if (code_generated
) break;
145 Type
*type_refd
= get_type_refd();
146 // generate code for the referenced type only if it is defined
147 // in the same module
148 if (my_scope
->get_scope_mod_gen() ==
149 type_refd
->my_scope
->get_scope_mod_gen())
150 type_refd
->generate_code(target
);
153 // the parameter types and the return type shall be generated
154 if (u
.signature
.parameters
) {
155 size_t nof_params
= u
.signature
.parameters
->get_nof_params();
156 for (size_t i
= 0; i
< nof_params
; i
++) {
157 u
.signature
.parameters
->get_param_byIndex(i
)->get_type()
158 ->generate_code(target
);
161 if (u
.signature
.return_type
)
162 u
.signature
.return_type
->generate_code(target
);
165 u
.array
.element_type
->generate_code(target
);
172 void Type::generate_code_embedded_after(output_struct
*target
)
179 size_t nof_comps
= get_nof_comps();
180 for (size_t i
= 0; i
< nof_comps
; i
++) {
181 CompField
*cf
= get_comp_byIndex(i
);
182 if (cf
->get_is_optional()) {
183 // generate code for optional record/set fields only
184 // mandatory fields are already completed
185 Type
*t
= cf
->get_type();
186 if (!t
->is_pure_refd()) t
->generate_code(target
);
193 size_t nof_comps
= get_nof_comps();
194 for (size_t i
= 0; i
< nof_comps
; i
++) {
195 // generate code for all union fields
196 Type
*t
= get_comp_byIndex(i
)->get_type();
197 if (!t
->is_pure_refd()) t
->generate_code(target
);
201 if (u
.secho
.my_tableconstraint
) {
202 // generate code for all embedded settings of the object set
203 // that is used in the table constraint
204 Asn::ObjectSet
*os
= u
.secho
.my_tableconstraint
->get_os();
205 if (os
->get_my_scope()->get_scope_mod_gen() ==
206 my_scope
->get_scope_mod_gen()) os
->generate_code(target
);
211 // generate code for the embedded type
212 if (!u
.seof
.ofType
->is_pure_refd()) u
.seof
.ofType
->generate_code(target
);
217 size_t nof_params
= u
.fatref
.fp_list
->get_nof_fps();
218 for(size_t i
= 0; i
< nof_params
; i
++) {
219 u
.fatref
.fp_list
->get_fp_byIndex(i
)->get_Type()
220 ->generate_code(target
);
228 void Type::generate_code_typedescriptor(output_struct
*target
)
230 bool force_xer
= false;
231 switch (get_type_refd_last()->typetype
) {
234 // do not generate any type descriptor for these non-data types
247 force_xer
= has_encoding(CT_XER
); // && (is_ref() || (xerattrib && !xerattrib->empty()));
251 } // switch(ownertype)
255 const string
& gennameown
= get_genname_own();
256 const char *gennameown_str
= gennameown
.c_str();
257 const string
& gennametypedescriptor
= get_genname_typedescriptor(my_scope
);
258 //printf("generate_code_typedescriptor(%s)\n", gennameown_str);
260 // FIXME: force_xer should be elminated. if a type needs a descriptor,
261 // it should say so via get_genname_typedescriptor()
263 /* genname{type,ber,raw,text,xer}descriptor == gennameown is true if
264 * the type needs its own {type,ber,raw,text,xer}descriptor
265 * and can't use the descriptor of one of the built-in types.
267 if (gennametypedescriptor
== gennameown
269 // the type has its own type descriptor
270 bool generate_ber
= has_encoding(CT_BER
) && enable_ber();
271 const string
& gennameberdescriptor
= get_genname_berdescriptor();
272 if (generate_ber
&& gennameberdescriptor
== gennameown
)
273 generate_code_berdescriptor(target
);
275 bool generate_raw
= has_encoding(CT_RAW
) && enable_raw();
276 const string
& gennamerawdescriptor
= get_genname_rawdescriptor();
277 if (generate_raw
&& gennamerawdescriptor
== gennameown
)
278 generate_code_rawdescriptor(target
);
280 bool generate_text
= has_encoding(CT_TEXT
) && enable_text();
281 const string
& gennametextdescriptor
= get_genname_textdescriptor();
282 if (generate_text
&& gennametextdescriptor
== gennameown
)
283 generate_code_textdescriptor(target
);
285 bool generate_xer
= has_encoding(CT_XER
) && enable_xer();
286 const string
& gennamexerdescriptor
= get_genname_xerdescriptor();
287 if (generate_xer
&& gennamexerdescriptor
== gennameown
)
288 generate_code_xerdescriptor(target
);
289 else target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
290 "// No XER for %s\n", gennamexerdescriptor
.c_str());
292 const string
& gennamejsondescriptor
= get_genname_jsondescriptor();
293 bool generate_json
= has_encoding(CT_JSON
) && enable_json() &&
294 gennamejsondescriptor
== gennameown
;
296 generate_code_jsondescriptor(target
);
299 // the type descriptor must be always exported.
300 // embedded (possibly unnamed) types can be referenced from other modules
301 // using field/array sub-references
302 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
303 "extern const TTCN_Typedescriptor_t %s_descr_;\n", gennameown_str
);
304 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
305 "const TTCN_Typedescriptor_t %s_descr_ = { \"%s\", ", gennameown_str
,
306 get_fullname().c_str());
309 target
->source
.global_vars
=mputprintf
310 (target
->source
.global_vars
,
311 "&%s_ber_, ", gennameberdescriptor
.c_str());
313 target
->source
.global_vars
=mputstr
314 (target
->source
.global_vars
, "NULL, ");
317 target
->source
.global_vars
=mputprintf
318 (target
->source
.global_vars
,
319 "&%s_raw_, ", gennamerawdescriptor
.c_str());
321 target
->source
.global_vars
=mputstr
322 (target
->source
.global_vars
, "NULL, ");
325 target
->source
.global_vars
=mputprintf
326 (target
->source
.global_vars
,
327 "&%s_text_, ", gennametextdescriptor
.c_str());
329 target
->source
.global_vars
=mputstr
330 (target
->source
.global_vars
, "NULL, ");
333 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
334 "&%s_xer_, ", gennamexerdescriptor
.c_str());
336 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
340 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
341 "&%s_json_, ", gennamejsondescriptor
.c_str());
343 switch(get_type_refd_last()->typetype
) {
355 case T_NUMERICSTRING
:
356 case T_PRINTABLESTRING
:
357 case T_TELETEXSTRING
:
358 case T_VIDEOTEXSTRING
:
360 case T_GRAPHICSTRING
:
361 case T_VISIBLESTRING
:
362 case T_GENERALSTRING
:
363 case T_UNIVERSALSTRING
:
370 // use predefined JSON descriptors instead of null pointers for basic types
371 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
372 "&%s_json_, ", gennamejsondescriptor
.c_str());
376 // use a predefined JSON descriptor for enumerated types
377 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
378 "&ENUMERATED_json_, ");
381 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
386 if (T_SEQOF
== get_type_refd_last()->typetype
||
387 T_SETOF
== get_type_refd_last()->typetype
) {
388 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
389 "&%s_descr_, ", get_type_refd_last()->u
.seof
.ofType
->get_genname_typedescriptor(my_scope
).c_str());
392 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
396 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
397 "TTCN_Typedescriptor_t::%s };\n"
401 , get_genname_typedescr_asnbasetype());
403 // the type uses the type descriptor of another type
405 // we need to generate an aliased type descriptor only if the type is
406 // directly accessible by the user
407 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
408 "extern const TTCN_Typedescriptor_t& %s_descr_;\n", gennameown_str
);
409 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
410 "const TTCN_Typedescriptor_t& %s_descr_ = %s_descr_;\n",
411 gennameown_str
, gennametypedescriptor
.c_str());
415 target
->source
.global_vars
= mputprintf( target
->source
.global_vars
,
416 "// %s_descr_ not needed, use %s_descr_\n",
417 gennameown_str
, gennametypedescriptor
.c_str());
418 } // if(needs_alias())
421 } // if (gennameown == gennametypedescriptor)
424 void Type::generate_code_berdescriptor(output_struct
*target
)
426 const char *gennameown_str
= get_genname_own().c_str();
427 char *str
= mprintf("static const ASN_Tag_t %s_tag_[] = { ",
429 Tags
*joinedtags
= build_tags_joined();
430 size_t tagarraysize
= joinedtags
->get_nof_tags();
431 for (size_t i
= 0; i
< tagarraysize
; i
++) {
432 if (i
> 0) str
= mputstr(str
, ", ");
433 Tag
*t_tag
= joinedtags
->get_tag_byIndex(i
);
434 str
= mputprintf(str
, "{ %s, %su }", t_tag
->get_tagclass_str(),
435 Int2string(t_tag
->get_tagvalue()).c_str());
438 str
= mputstr(str
, "};\n");
439 target
->source
.global_vars
= mputstr(target
->source
.global_vars
, str
);
441 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
442 "extern const ASN_BERdescriptor_t %s_ber_;\n", gennameown_str
);
443 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
444 "const ASN_BERdescriptor_t %s_ber_ = { %luu, %s_tag_ };\n",
445 gennameown_str
, (unsigned long)tagarraysize
, gennameown_str
);
448 static const char* whitespace_action
[3] = {"PRESERVE", "REPLACE", "COLLAPSE"};
450 extern void change_name(string
&name
, XerAttributes::NameChange change
);
451 // implemented in Type_chk.cc
453 void Type::generate_code_xerdescriptor(output_struct
* target
)
455 const char *gennameown_str
= get_genname_own().c_str();
456 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
457 "extern const XERdescriptor_t %s_xer_;\n", gennameown_str
);
462 string full_s
= ot
->get_fullname();
463 size_t dot_pos
= full_s
.rfind('.');
464 if (full_s
.size() == dot_pos
) dot_pos
= 0;
465 last_s
= full_s
.substr(dot_pos
+1); // FIXME: may be better to use replace(pos, n, s)
467 if ('&'==last_s
[0] // object class field ?
468 ||'<'==last_s
[0]) { // <oftype> and the like
470 ot
= ot
->get_type_refd();
471 /* Fetch the referenced type and use that. Do not use
472 * get_type_refd_last() here. In case of a record-of user-defined type:
473 * <ttcn>type integer MyInt; type record of MyInt MyRecof;</ttcn>
474 * we want "MyInt" and not "integer" */
477 else { // probably a built-in type, punt with the C++ class name
478 last_s
= ot
->get_genname_value(0);
485 // Name for basic XER which ignores all the EXER fanciness
486 string
bxer_name(last_s
);
489 //fprintf(stderr, "%2d gno='%s'\tfn='%s'\n", typetype, gennameown_str, last_s.c_str());
490 int atrib
=0, any_atr
=0, any_elem
=0, base64
=0, decimal
=0, embed
=0, list
=0,
491 text
=0, untagged
=0, use_nil
=0, use_number
=0, use_order
=0, use_qname
=0,
492 use_type_attr
=0, ws
=0, has_1untag
=0, form_qualified
=0, any_from
=0,
493 any_except
=0, nof_ns_uris
=0;
494 const char* dfe_str
= 0;
496 char* oftype_descr_name
= 0;
498 change_name(last_s
, xerattrib
->name_
);
500 if (xerattrib
->namespace_
.uri
&& xerattrib
->namespace_
.prefix
) {
501 ns_index
= my_scope
->get_scope_mod()->get_ns_index(
502 xerattrib
->namespace_
.prefix
);
503 // This is known to have succeeded
506 any_atr
= has_aa(xerattrib
);
507 any_elem
= has_ae(xerattrib
);
508 atrib
= xerattrib
->attribute_
;
509 base64
= xerattrib
->base64_
;
510 decimal
= xerattrib
->decimal_
;
511 embed
= xerattrib
->embedValues_
;
512 form_qualified
= (xerattrib
->form_
& XerAttributes::QUALIFIED
)
513 || (xerattrib
->element_
); // a global element is always qualified
514 list
= xerattrib
->list_
;
515 untagged
= xerattrib
->untagged_
;
516 ws
= xerattrib
->whitespace_
;
517 // only set TEXT if it has no TextToBeUsed (plain "text" for a bool)
518 text
= xerattrib
->num_text_
&& xerattrib
->text_
->prefix
== 0;
519 use_nil
= xerattrib
->useNil_
;
520 use_number
= xerattrib
->useNumber_
;
521 use_order
= xerattrib
->useOrder_
;
522 use_qname
= xerattrib
->useQName_
;
523 // In ASN.1, the use of a type identification attribute is optional
524 // (encoder's choice) for USE-UNION. However, TTCN-3 removes this choice:
525 // it is mandatory to use it when possible (valid choice for ASN.1 too).
526 use_type_attr
= xerattrib
->useType_
|| xerattrib
->useUnion_
;
528 if (xerattrib
->defaultValue_
) {
529 Type
*t
= xerattrib
->defaultValue_
->get_my_governor();
530 dfe_str
= xerattrib
->defaultValue_
->get_genname_own().c_str();
532 Code::init_cdef(&cdef
);
533 t
->generate_code_object(&cdef
, xerattrib
->defaultValue_
);
534 cdef
.init
= xerattrib
->defaultValue_
->generate_code_init
535 (cdef
.init
, xerattrib
->defaultValue_
->get_lhs_name().c_str());
536 Code::merge_cdef(target
, &cdef
);
537 Code::free_cdef(&cdef
);
541 // data needed for "anyElement from ..." and "anyElement except ..." encoding instructions
542 any_from
= xerattrib
->anyElement_
.type_
== NamespaceRestriction::FROM
;
543 any_except
= xerattrib
->anyElement_
.type_
== NamespaceRestriction::EXCEPT
;
544 nof_ns_uris
= xerattrib
->anyElement_
.nElements_
;
545 ns_uris
= xerattrib
->anyElement_
.uris_
;
548 // data needed for "anyAttributes from ..." and "anyAttributes except ..." encoding instructions
549 any_from
= xerattrib
->anyAttributes_
.type_
== NamespaceRestriction::FROM
;
550 any_except
= xerattrib
->anyAttributes_
.type_
== NamespaceRestriction::EXCEPT
;
551 nof_ns_uris
= xerattrib
->anyAttributes_
.nElements_
;
552 ns_uris
= xerattrib
->anyAttributes_
.uris_
;
555 else if (ownertype
== OT_COMP_FIELD
556 && parent_type
&& parent_type
->xerattrib
) {
557 //no xerattrib, this must be an element; apply element default
558 form_qualified
= (parent_type
->xerattrib
->form_
559 & XerAttributes::ELEMENT_DEFAULT_QUALIFIED
);
562 Type
*last
= get_type_refd_last();
563 has_1untag
= last
->is_secho() && last
->u
.secho
.has_single_charenc
; // does not come from xerattrib
565 /* If this is a string type whose grandparent is a record
566 * (containing a record-of (this)string) which has EMBED-VALUES,
567 * then reuse this string's any_element field in the XER descriptor
568 * to signal this (ANY-ELEMENT causes the tag to be omitted,
569 * which is what we want in EMBED-VALUES) */
570 if (parent_type
&& parent_type
->parent_type
) switch (last
->typetype
) {
572 case T_USTR
: // the TTCN equivalent of UTF8String
573 if ( T_SEQOF
== parent_type
->typetype
574 && (T_SEQ_T
== parent_type
->parent_type
->typetype
575 ||T_SEQ_A
== parent_type
->parent_type
->typetype
)
576 && parent_type
->parent_type
->xerattrib
) {
577 embed
|= (parent_type
->parent_type
->xerattrib
->embedValues_
);
583 size_t last_len
= 2 + last_s
.size(); // 2 for > \n
584 size_t bxer_len
= 2 + bxer_name
.size(); // 2 for > \n
586 if ((T_SEQOF
== last
->typetype
|| T_SETOF
== last
->typetype
) &&
587 T_ANYTYPE
!= last
->u
.seof
.ofType
->get_type_refd_last()->typetype
) {
588 // anytypes don't have XER descriptors
589 oftype_descr_name
= mprintf("&%s_xer_", last
->u
.seof
.ofType
->get_genname_typedescriptor(my_scope
).c_str());
592 // Generate a separate variable for the namespace URIs, if there are any
593 char* ns_uris_var
= 0;
594 if (ns_uris
&& nof_ns_uris
) {
595 ns_uris_var
= mputprintf(ns_uris_var
, "%s_ns_uris_", gennameown_str
);
596 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
597 "const char* %s[] = {", ns_uris_var
);
598 for (int idx
= 0; idx
< nof_ns_uris
; ++idx
) {
599 // The unqualified namespace is sometimes stored as an empty string and
600 // sometimes as a null pointer -> unify it, always store it as an empty string
601 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
602 "%s\"%s\"", (idx
!= 0) ? ", " : "", ns_uris
[idx
] ? ns_uris
[idx
] : "");
604 target
->source
.global_vars
= mputstrn(target
->source
.global_vars
, "};\n", 3);
607 // Generate the XER descriptor itself
608 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
609 "const XERdescriptor_t %s_xer_ = { {\"%s>\\n\", \"%s>\\n\"},"
610 " {%lu, %lu}, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s, WHITESPACE_%s, %c%s, "
611 "&%s, %ld, %u, %s, %s };\n",
613 bxer_name
.c_str(), last_s
.c_str(), // names
614 (unsigned long)bxer_len
, (unsigned long)last_len
, // lengths
615 (any_atr
? "ANY_ATTRIBUTES" : "0"),
616 (any_elem
? " |ANY_ELEMENT" : ""),
617 (atrib
? " |XER_ATTRIBUTE" : ""),
618 (base64
? " |BASE_64" : ""),
619 (decimal
? " |XER_DECIMAL" : ""),
620 (embed
? " |EMBED_VALUES" : ""),
621 (list
? " |XER_LIST" : ""),
622 (text
? " |XER_TEXT" : ""),
623 (untagged
? " |UNTAGGED" : ""),
624 (use_nil
? " |USE_NIL" : ""),
625 (use_number
? " |USE_NUMBER" : ""),
626 (use_order
? " |USE_ORDER" : ""),
627 (use_qname
? " |USE_QNAME" : ""),
628 (use_type_attr
? " |USE_TYPE_ATTR" : ""),
629 (has_1untag
? " |HAS_1UNTAGGED" : ""),
630 (form_qualified
? "" : " |FORM_UNQUALIFIED"),
631 (any_from
? " |ANY_FROM" : ""),
632 (any_except
? " |ANY_EXCEPT" : ""),
633 whitespace_action
[ws
],
634 (dfe_str
? '&' : ' '), (dfe_str
? dfe_str
: "NULL"),
638 (ns_uris_var
? ns_uris_var
: "NULL"),
639 (oftype_descr_name
? oftype_descr_name
: "NULL")
643 Free(oftype_descr_name
);
646 void Type::generate_code_rawdescriptor(output_struct
*target
)
648 const char *gennameown_str
= get_genname_own().c_str();
649 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
650 "extern const TTCN_RAWdescriptor_t %s_raw_;\n", gennameown_str
);
651 char *str
= mprintf("const TTCN_RAWdescriptor_t %s_raw_ = {",
653 str
= mputprintf(str
, "%d,", rawattrib
->fieldlength
);
654 if (rawattrib
->comp
== XDEFCOMPL
) str
= mputstr(str
, "SG_2COMPL,");
655 else if (rawattrib
->comp
== XDEFSIGNBIT
) str
= mputstr(str
, "SG_SG_BIT,");
656 else str
= mputstr(str
, "SG_NO,");
657 if (rawattrib
->byteorder
== XDEFLAST
) str
= mputstr(str
, "ORDER_MSB,");
658 else str
= mputstr(str
, "ORDER_LSB,");
659 if (rawattrib
->align
== XDEFLEFT
) str
= mputstr(str
, "ORDER_MSB,");
660 else str
= mputstr(str
, "ORDER_LSB,");
661 if (rawattrib
->bitorderinfield
== XDEFMSB
)
662 str
= mputstr(str
, "ORDER_MSB,");
663 else str
= mputstr(str
, "ORDER_LSB,");
664 if (rawattrib
->bitorderinoctet
== XDEFMSB
)
665 str
= mputstr(str
, "ORDER_MSB,");
666 else str
= mputstr(str
, "ORDER_LSB,");
667 if (rawattrib
->extension_bit
== XDEFYES
)
668 str
= mputstr(str
, "EXT_BIT_YES,");
669 else if (rawattrib
->extension_bit
== XDEFREVERSE
)
670 str
= mputstr(str
, "EXT_BIT_REVERSE,");
671 else str
= mputstr(str
, "EXT_BIT_NO,");
672 if (rawattrib
->hexorder
== XDEFHIGH
) str
= mputstr(str
, "ORDER_MSB,");
673 else str
= mputstr(str
, "ORDER_LSB,");
674 if (rawattrib
->fieldorder
== XDEFMSB
) str
= mputstr(str
, "ORDER_MSB,");
675 else str
= mputstr(str
, "ORDER_LSB,");
676 if (rawattrib
->topleveleind
) {
677 if (rawattrib
->toplevel
.bitorder
==XDEFLSB
)
678 str
= mputstr(str
, "TOP_BIT_LEFT,");
679 else str
= mputstr(str
, "TOP_BIT_RIGHT,");
680 } else str
= mputstr(str
, "TOP_BIT_INHERITED,");
681 str
= mputprintf(str
, "%d,", rawattrib
->padding
);
682 str
= mputprintf(str
, "%d,", rawattrib
->prepadding
);
683 str
= mputprintf(str
, "%d,", rawattrib
->ptroffset
);
684 str
= mputprintf(str
, "%d,", rawattrib
->unit
);
685 str
= mputprintf(str
, "%d,", rawattrib
->padding_pattern_length
);
686 if (rawattrib
->padding_pattern_length
> 0)
687 str
= mputprintf(str
, "%s,", my_scope
->get_scope_mod_gen()
688 ->add_padding_pattern(string(rawattrib
->padding_pattern
)).c_str());
689 else str
= mputstr(str
, "NULL,");
690 str
= mputprintf(str
, "%d};\n", rawattrib
->length_restrition
);
691 target
->source
.global_vars
= mputstr(target
->source
.global_vars
, str
);
695 void Type::generate_code_textdescriptor(output_struct
*target
)
697 const char *gennameown_str
= get_genname_own().c_str();
698 char *union_member_name
=NULL
;
699 Common::Module
*mymod
=my_scope
->get_scope_mod();
700 Type
*t
= get_type_refd_last();
701 switch (t
->typetype
) {
703 if (textattrib
->true_params
|| textattrib
->false_params
) {
704 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
705 "static const TTCN_TEXTdescriptor_bool %s_bool_ = {", gennameown_str
);
706 if (textattrib
->true_params
&&
707 textattrib
->true_params
->encode_token
) {
708 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
709 "&%s,", mymod
->add_charstring_literal(
710 string(textattrib
->true_params
->encode_token
)).c_str());
712 target
->source
.global_vars
=mputstr(target
->source
.global_vars
,
715 if (textattrib
->true_params
&&
716 textattrib
->true_params
->decode_token
) {
717 char *pstr
= make_posix_str_code(
718 textattrib
->true_params
->decode_token
,
719 textattrib
->true_params
->case_sensitive
);
720 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
721 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
723 } else if (textattrib
->true_params
&&
724 !textattrib
->true_params
->case_sensitive
) {
725 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
726 "&%s,", mymod
->add_matching_literal(
727 string("N^(true).*$")).c_str());
729 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
732 if (textattrib
->false_params
&&
733 textattrib
->false_params
->encode_token
) {
734 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
735 "&%s,",mymod
->add_charstring_literal(
736 string(textattrib
->false_params
->encode_token
)).c_str());
738 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
741 if (textattrib
->false_params
&&
742 textattrib
->false_params
->decode_token
) {
743 char *pstr
= make_posix_str_code(
744 textattrib
->false_params
->decode_token
,
745 textattrib
->false_params
->case_sensitive
);
746 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
747 "&%s};\n", mymod
->add_matching_literal(string(pstr
)).c_str());
749 } else if (textattrib
->false_params
&&
750 !textattrib
->false_params
->case_sensitive
) {
751 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
752 "&%s};\n", mymod
->add_matching_literal(
753 string("N^(false).*$")).c_str());
755 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
758 union_member_name
= mprintf("(TTCN_TEXTdescriptor_param_values*)"
759 "&%s_bool_", gennameown_str
);
763 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
764 "static const TTCN_TEXTdescriptor_enum %s_enum_[] = { ",
766 for (size_t i
= 0; i
< t
->u
.enums
.eis
->get_nof_eis(); i
++) {
767 if (i
> 0) target
->source
.global_vars
=
768 mputstr(target
->source
.global_vars
, ", ");
769 target
->source
.global_vars
=
770 mputstr(target
->source
.global_vars
, "{ ");
771 if (textattrib
->field_params
&& textattrib
->field_params
[i
] &&
772 textattrib
->field_params
[i
]->value
.encode_token
) {
773 // the encode token is present
774 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
775 "&%s, ", mymod
->add_charstring_literal(
776 string(textattrib
->field_params
[i
]->value
.encode_token
)).c_str());
778 // the encode token is not present: generate a NULL pointer and the
779 // RTE will substitute the enumerated value
780 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
783 // a pattern must be always present for decoding
784 const char *decode_token
;
786 if (textattrib
->field_params
&& textattrib
->field_params
[i
]) {
787 if (textattrib
->field_params
[i
]->value
.decode_token
) {
788 // the decode token is present
789 decode_token
= textattrib
->field_params
[i
]->value
.decode_token
;
791 // there is an attribute for the enumerated value,
792 // but the decode token is omitted
793 // use the value as decode token
794 decode_token
= t
->u
.enums
.eis
->get_ei_byIndex(i
)->get_name()
795 .get_dispname().c_str();
797 // take the case sensitivity from the attribute
798 case_sensitive
= textattrib
->field_params
[i
]->value
.case_sensitive
;
800 // there is no attribute for the enumerated value
801 // use the value as decode token
802 decode_token
= t
->u
.enums
.eis
->get_ei_byIndex(i
)->get_name()
803 .get_dispname().c_str();
804 // it is always case sensitive
805 case_sensitive
= true;
807 char *pstr
= make_posix_str_code(decode_token
, case_sensitive
);
808 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
809 " &%s }", mymod
->add_matching_literal(string(pstr
)).c_str());
812 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
814 union_member_name
= mprintf(
815 "(TTCN_TEXTdescriptor_param_values*)%s_enum_", gennameown_str
);
819 if(textattrib
->coding_params
.leading_zero
||
820 textattrib
->coding_params
.min_length
!=-1 ||
821 textattrib
->coding_params
.max_length
!=-1 ||
822 textattrib
->coding_params
.convert
!=0 ||
823 textattrib
->coding_params
.just
!=1 ||
824 textattrib
->decoding_params
.leading_zero
||
825 textattrib
->decoding_params
.min_length
!=-1 ||
826 textattrib
->decoding_params
.max_length
!=-1 ||
827 textattrib
->decoding_params
.convert
!=0 ||
828 textattrib
->decoding_params
.just
!=1 ){
829 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
830 "static const TTCN_TEXTdescriptor_param_values %s_par_ = {",
832 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
833 "{%s,%s,%i,%i,%i,%i},{%s,%s,%i,%i,%i,%i}};\n"
834 ,textattrib
->coding_params
.leading_zero
?"true":"false"
835 ,textattrib
->coding_params
.repeatable
?"true":"false"
836 ,textattrib
->coding_params
.min_length
837 ,textattrib
->coding_params
.max_length
838 ,textattrib
->coding_params
.convert
839 ,textattrib
->coding_params
.just
840 ,textattrib
->decoding_params
.leading_zero
?"true":"false"
841 ,textattrib
->decoding_params
.repeatable
?"true":"false"
842 ,textattrib
->decoding_params
.min_length
843 ,textattrib
->decoding_params
.max_length
844 ,textattrib
->decoding_params
.convert
845 ,textattrib
->decoding_params
.just
);
847 union_member_name
=mprintf("&%s_par_", gennameown_str
);
852 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
853 "static const TTCN_TEXTdescriptor_param_values %s_par_ = {",
855 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
856 "{%s,%s,%i,%i,%i,%i},{%s,%s,%i,%i,%i,%i}};\n"
857 ,textattrib
->coding_params
.leading_zero
?"true":"false"
858 ,textattrib
->coding_params
.repeatable
?"true":"false"
859 ,textattrib
->coding_params
.min_length
860 ,textattrib
->coding_params
.max_length
861 ,textattrib
->coding_params
.convert
862 ,textattrib
->coding_params
.just
863 ,textattrib
->decoding_params
.leading_zero
?"true":"false"
864 ,textattrib
->decoding_params
.repeatable
?"true":"false"
865 ,textattrib
->decoding_params
.min_length
866 ,textattrib
->decoding_params
.max_length
867 ,textattrib
->decoding_params
.convert
868 ,textattrib
->decoding_params
.just
);
870 union_member_name
=mprintf("&%s_par_", gennameown_str
);
876 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
877 "extern const TTCN_TEXTdescriptor_t %s_text_;\n", gennameown_str
);
878 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
879 "const TTCN_TEXTdescriptor_t %s_text_ = {", gennameown_str
);
881 if (textattrib
->begin_val
&& textattrib
->begin_val
->encode_token
) {
882 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
883 "&%s,", mymod
->add_charstring_literal(
884 string(textattrib
->begin_val
->encode_token
)).c_str());
886 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
889 if(textattrib
->begin_val
&& textattrib
->begin_val
->decode_token
){
890 char *pstr
= make_posix_str_code(
891 textattrib
->begin_val
->decode_token
,
892 textattrib
->begin_val
->case_sensitive
);
893 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
894 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
897 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
900 if (textattrib
->end_val
&& textattrib
->end_val
->encode_token
) {
901 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
902 "&%s,",mymod
->add_charstring_literal(
903 string(textattrib
->end_val
->encode_token
)).c_str());
905 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
908 if (textattrib
->end_val
&& textattrib
->end_val
->decode_token
) {
909 char *pstr
= make_posix_str_code(
910 textattrib
->end_val
->decode_token
,
911 textattrib
->end_val
->case_sensitive
);
912 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
913 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
916 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
920 if (textattrib
->separator_val
&&
921 textattrib
->separator_val
->encode_token
) {
922 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
923 "&%s,", mymod
->add_charstring_literal(
924 string(textattrib
->separator_val
->encode_token
)).c_str());
926 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
929 if(textattrib
->separator_val
&&
930 textattrib
->separator_val
->decode_token
) {
931 char *pstr
= make_posix_str_code(
932 textattrib
->separator_val
->decode_token
,
933 textattrib
->separator_val
->case_sensitive
);
934 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
935 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
938 target
->source
.global_vars
=mputstr(target
->source
.global_vars
,
942 if (textattrib
->decode_token
) {
943 char *pstr
= make_posix_str_code(textattrib
->decode_token
,
944 textattrib
->case_sensitive
);
945 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
946 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
949 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
953 if (union_member_name
) {
954 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
955 "{%s}};\n", union_member_name
);
956 Free(union_member_name
);
958 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
963 void Type::generate_code_jsondescriptor(output_struct
*target
)
965 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
966 "extern const TTCN_JSONdescriptor_t %s_json_;\n", get_genname_own().c_str());
968 if (NULL
== jsonattrib
) {
969 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
970 "const TTCN_JSONdescriptor_t %s_json_ = { false, NULL, false, NULL };\n"
971 , get_genname_own().c_str());
973 char* alias
= jsonattrib
->alias
? mputprintf(NULL
, "\"%s\"", jsonattrib
->alias
) : NULL
;
974 char* def_val
= jsonattrib
->default_value
?
975 mputprintf(NULL
, "\"%s\"", jsonattrib
->default_value
) : NULL
;
976 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
977 "const TTCN_JSONdescriptor_t %s_json_ = { %s, %s, %s, %s };\n"
978 , get_genname_own().c_str()
979 , jsonattrib
->omit_as_null
? "true" : "false"
980 , alias
? alias
: "NULL"
981 , jsonattrib
->as_value
? "true" : "false"
982 , def_val
? def_val
: "NULL");
989 void Type::generate_code_alias(output_struct
*target
)
991 if (!needs_alias()) return;
993 const string
& t_genname
= get_genname_value(my_scope
);
994 const char *refd_name
= t_genname
.c_str();
995 const char *own_name
= get_genname_own().c_str();
997 Type
*t_last
= get_type_refd_last();
998 switch (t_last
->typetype
) {
999 case T_PORT
: // only value class exists
1000 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1001 "typedef %s %s;\n", refd_name
, own_name
);
1003 case T_SIGNATURE
: // special classes (7 pcs.) exist
1004 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1005 "typedef %s_call %s_call;\n"
1006 "typedef %s_call_redirect %s_call_redirect;\n",
1007 refd_name
, own_name
, refd_name
, own_name
);
1008 if (!t_last
->is_nonblocking_signature()) {
1009 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1010 "typedef %s_reply %s_reply;\n"
1011 "typedef %s_reply_redirect %s_reply_redirect;\n",
1012 refd_name
, own_name
, refd_name
, own_name
);
1014 if (t_last
->get_signature_exceptions()) {
1015 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1016 "typedef %s_exception %s_exception;\n"
1017 "typedef %s_exception_template %s_exception_template;\n",
1018 refd_name
, own_name
, refd_name
, own_name
);
1020 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1021 "typedef %s_template %s_template;\n",
1022 refd_name
, own_name
);
1024 default: // value and template classes exist
1025 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1027 "// written by %s in " __FILE__
" at %d\n"
1030 "typedef %s_template %s_template;\n",
1032 __FUNCTION__
, __LINE__
,
1034 refd_name
, own_name
, refd_name
, own_name
);
1039 void Type::generate_code_Enum(output_struct
*target
)
1043 memset(&e_def
, 0, sizeof(e_def
));
1044 e_def
.name
= get_genname_own().c_str();
1045 e_def
.dispname
= get_fullname().c_str();
1046 e_def
.isASN1
= is_asn1();
1047 e_def
.nElements
= u
.enums
.eis
->get_nof_eis();
1048 e_def
.elements
= (enum_field
*)
1049 Malloc(e_def
.nElements
*sizeof(*e_def
.elements
));
1050 e_def
.firstUnused
= u
.enums
.first_unused
;
1051 e_def
.secondUnused
= u
.enums
.second_unused
;
1052 e_def
.hasText
= textattrib
!=NULL
;
1053 e_def
.hasRaw
= rawattrib
!=NULL
;
1054 e_def
.hasXer
= has_encoding(CT_XER
);
1055 e_def
.hasJson
= has_encoding(CT_JSON
);
1057 e_def
.xerUseNumber
= xerattrib
->useNumber_
;
1059 for (size_t i
= 0; i
< e_def
.nElements
; i
++) {
1060 EnumItem
*ei
= u
.enums
.eis
->get_ei_byIndex(i
);
1061 e_def
.elements
[i
].name
= ei
->get_name().get_name().c_str();
1062 e_def
.elements
[i
].dispname
= ei
->get_name().get_ttcnname().c_str();
1063 if (ei
->get_text().empty()) e_def
.elements
[i
].text
= 0;
1065 e_def
.xerText
= TRUE
;
1066 e_def
.elements
[i
].text
= ei
->get_text().c_str();
1068 e_def
.elements
[i
].value
= ei
->get_value()->get_val_Int()->get_val();
1071 defEnumClass(&e_def
, target
);
1072 defEnumTemplate(&e_def
, target
);
1074 Free(e_def
.elements
);
1077 void Type::generate_code_Choice(output_struct
*target
)
1081 memset(&sdef
, 0, sizeof(sdef
));
1082 sdef
.name
= get_genname_own().c_str();
1083 sdef
.dispname
=get_fullname().c_str();
1084 if (T_ANYTYPE
==typetype
) {
1085 if (0 == get_nof_comps()) {
1086 //return; // don't generate code for empty anytype
1087 // XXX what to do with empty anytype ?
1088 // Easy: make sure it doesn't happen by filling it from the AST!
1090 sdef
.kind
= ANYTYPE
;
1092 else sdef
.kind
= UNION
;
1093 sdef
.isASN1
= is_asn1();
1094 sdef
.hasText
= textattrib
!=NULL
;
1095 sdef
.hasXer
= has_encoding(CT_XER
);
1096 sdef
.hasJson
= has_encoding(CT_JSON
);
1097 sdef
.has_opentypes
= get_has_opentypes();
1098 sdef
.opentype_outermost
= get_is_opentype_outermost();
1099 sdef
.ot
= generate_code_ot(pool
);
1100 sdef
.nElements
= get_nof_comps();
1101 sdef
.elements
= (struct_field
*)
1102 Malloc(sdef
.nElements
*sizeof(*sdef
.elements
));
1103 memset(sdef
.elements
, 0, sdef
.nElements
*sizeof(*sdef
.elements
));
1104 sdef
.exerMaybeEmptyIndex
= -1;
1106 sdef
.jsonAsValue
= jsonattrib
->as_value
;
1108 for(size_t i
= 0; i
< sdef
.nElements
; i
++) {
1109 CompField
*cf
= get_comp_byIndex(i
);
1110 const Identifier
& id
= cf
->get_name();
1111 Type
*cftype
= cf
->get_type();
1112 sdef
.elements
[i
].type
= pool
.add(cftype
->get_genname_value(my_scope
));
1113 sdef
.elements
[i
].typedescrname
=
1114 pool
.add(cftype
->get_genname_typedescriptor(my_scope
));
1115 sdef
.elements
[i
].typegen
= pool
.add(cftype
->get_genname_xerdescriptor());
1116 sdef
.elements
[i
].name
= id
.get_name().c_str();
1117 sdef
.elements
[i
].dispname
= id
.get_ttcnname().c_str();
1119 if (cftype
->has_empty_xml()) sdef
.exerMaybeEmptyIndex
= i
;
1120 // This will overwrite lower values, which is what we want.
1122 if (sdef
.jsonAsValue
) {
1123 // Determine the JSON value type of each field to make decoding faster
1124 typetype_t tt
= cftype
->get_type_refd_last()->typetype
;
1127 sdef
.elements
[i
].jsonValueType
= JSON_NUMBER
;
1130 sdef
.elements
[i
].jsonValueType
= JSON_NUMBER
| JSON_STRING
;
1133 sdef
.elements
[i
].jsonValueType
= JSON_LITERAL
;
1142 sdef
.elements
[i
].jsonValueType
= JSON_STRING
;
1147 sdef
.elements
[i
].jsonValueType
= JSON_OBJECT
;
1151 sdef
.elements
[i
].jsonValueType
= JSON_ARRAY
;
1154 FATAL_ERROR("Type::generate_code_Choice - invalid field type %d", tt
);
1157 if (cftype
->jsonattrib
) {
1158 sdef
.elements
[i
].jsonAlias
= cftype
->jsonattrib
->alias
;
1159 if (sdef
.jsonAsValue
&& cftype
->jsonattrib
->as_value
) {
1160 // Override the JSON_OBJECT value given in the switch
1161 sdef
.elements
[i
].jsonValueType
= JSON_ANY_VALUE
;
1166 copy_rawAST_to_struct(rawattrib
,&(sdef
.raw
));
1169 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++){
1170 if(rawattrib
->taglist
.tag
[c
].nElements
)
1171 sdef
.raw
.taglist
.list
[c
].fields
=
1172 (rawAST_coding_field_list
*)
1173 Malloc(rawattrib
->taglist
.tag
[c
].nElements
1174 *sizeof(rawAST_coding_field_list
));
1175 else sdef
.raw
.taglist
.list
[c
].fields
=NULL
;
1176 sdef
.raw
.taglist
.list
[c
].nElements
=
1177 rawattrib
->taglist
.tag
[c
].nElements
;
1178 sdef
.raw
.taglist
.list
[c
].fieldName
=
1179 rawattrib
->taglist
.tag
[c
].fieldName
->get_name().c_str();
1180 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
1181 sdef
.raw
.taglist
.list
[c
].fieldnum
=get_comp_index_byName(*idf
);
1182 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
1183 rawAST_coding_field_list
* key
=
1184 sdef
.raw
.taglist
.list
[c
].fields
+a
;
1186 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->nElements
+1;
1187 key
->value
=rawattrib
->taglist
.tag
[c
].keyList
[a
].value
;
1189 key
->fields
=(rawAST_coding_fields
*)
1190 Malloc(key
->nElements
*sizeof(rawAST_coding_fields
));
1191 CompField
*cf
=get_comp_byIndex(sdef
.raw
.taglist
.list
[c
].fieldnum
);
1192 Type
*t
=cf
->get_type()->get_type_refd_last();
1194 key
->fields
[0].nthfield
= sdef
.raw
.taglist
.list
[c
].fieldnum
;
1195 key
->fields
[0].nthfieldname
=
1196 rawattrib
->taglist
.tag
[c
].fieldName
->get_name().c_str();
1197 key
->fields
[0].fieldtype
= UNION_FIELD
;
1198 key
->fields
[0].type
= pool
.add(t
->get_genname_value(my_scope
));
1199 key
->fields
[0].typedescr
=
1200 pool
.add(t
->get_genname_typedescriptor(my_scope
));
1202 for (int b
= 1; b
< key
->nElements
; b
++) {
1204 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
-1];
1205 size_t comp_index
= t
->get_comp_index_byName(*idf2
);
1206 CompField
*cf2
= t
->get_comp_byIndex(comp_index
);
1207 key
->fields
[b
].nthfield
= comp_index
;
1208 key
->fields
[b
].nthfieldname
= idf2
->get_name().c_str();
1209 if (t
->typetype
== T_CHOICE_T
)
1210 key
->fields
[b
].fieldtype
= UNION_FIELD
;
1211 else if (cf2
->get_is_optional()){
1212 key
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1213 }else key
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1214 Type
*field_type
= cf2
->get_type();
1215 key
->fields
[b
].type
=
1216 pool
.add(field_type
->get_genname_value(my_scope
));
1217 key
->fields
[b
].typedescr
=
1218 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1219 if (field_type
->typetype
== T_SEQ_T
&& field_type
->rawattrib
1220 && (field_type
->rawattrib
->pointerto
1221 || field_type
->rawattrib
->lengthto_num
))
1222 key
->start_pos
= -1;
1224 if(t
->typetype
!= T_CHOICE_T
&& t
->typetype
!= T_SET_T
){
1226 for(size_t i
= 0; i
< comp_index
&& key
->start_pos
>=0; i
++)
1228 t2
= t
->get_comp_byIndex(i
)->get_type();
1229 if(t2
->get_raw_length() >= 0){
1231 key
->start_pos
+= t2
->rawattrib
->padding
;
1232 key
->start_pos
+= t2
->get_raw_length();
1233 }else key
->start_pos
= -1;
1236 t
= field_type
->get_type_refd_last();
1240 } else sdef
.hasRaw
=false;
1242 Module
*my_module
= get_my_scope()->get_scope_mod();
1243 sdef
.xerHasNamespaces
= my_module
->get_nof_ns() != 0;
1244 const char *ns
, *prefix
;
1245 my_module
->get_controlns(ns
, prefix
);
1246 sdef
.control_ns_prefix
= prefix
;
1247 sdef
.xerUseUnion
= xerattrib
->useUnion_
;
1248 sdef
.xerUseTypeAttr
= xerattrib
->useType_
|| xerattrib
->useUnion_
;
1250 defUnionClass(&sdef
, target
);
1251 defUnionTemplate(&sdef
, target
);
1253 free_code_ot(sdef
.ot
);
1256 free_raw_attrib_struct(&sdef
.raw
);
1258 Free(sdef
.elements
);
1261 Opentype_t
*Type::generate_code_ot(stringpool
& pool
)
1263 using namespace Asn
;
1264 if(typetype
!=T_OPENTYPE
)
1266 if(!u
.secho
.my_tableconstraint
1267 || !u
.secho
.my_tableconstraint
->get_ans()) {
1268 DEBUG(1, "Opentype ObjectClassFieldType without"
1269 " ComponentRelationConstraint: `%s'",
1270 get_fullname().c_str());
1273 const AtNotations
*ans
=u
.secho
.my_tableconstraint
->get_ans();
1274 Opentype_t
*ot
=(Opentype_t
*)Malloc(sizeof(*ot
));
1275 ot
->anl
.nElements
= ans
->get_nof_ans();
1276 ot
->anl
.elements
= (AtNotation_t
*)
1277 Malloc(ot
->anl
.nElements
* sizeof(*ot
->anl
.elements
));
1278 for(size_t i
=0; i
<ans
->get_nof_ans(); i
++) {
1279 AtNotation
*an
=ans
->get_an_byIndex(i
);
1280 AtNotation_t
*an_t
= ot
->anl
.elements
+ i
;
1281 an_t
->dispname
= pool
.add(an
->get_dispname());
1282 an_t
->parent_level
=an
->get_levels();
1283 an_t
->parent_typename
=
1284 pool
.add(an
->get_firstcomp()->get_genname_value(my_scope
));
1286 pool
.add(an
->get_lastcomp()->get_genname_value(my_scope
));
1287 an_t
->sourcecode
=memptystr();
1288 FieldName
* cids
=an
->get_cids();
1289 Type
*t_type
=an
->get_firstcomp();
1290 for(size_t j
=0; j
<cids
->get_nof_fields(); j
++) {
1292 t_type
->get_comp_byName(*cids
->get_field_byIndex(j
));
1293 if(j
) an_t
->sourcecode
=mputstr(an_t
->sourcecode
, ".");
1294 an_t
->sourcecode
=mputprintf
1295 (an_t
->sourcecode
, "%s()",
1296 cf
->get_name().get_name().c_str());
1297 if(cf
->get_is_optional())
1298 an_t
->sourcecode
=mputstr(an_t
->sourcecode
, "()");
1299 t_type
=cf
->get_type();
1302 const Identifier
*oc_fieldname_t
1303 =u
.secho
.my_tableconstraint
->get_oc_fieldname();
1305 =u
.secho
.my_tableconstraint
->get_os()->get_refd_last()->get_objs();
1306 ot
->oal
.nElements
= objs
->get_nof_objs();
1307 ot
->oal
.elements
= (OpentypeAlternative_t
*)
1308 Malloc(ot
->oal
.nElements
* sizeof(*ot
->oal
.elements
));
1309 size_t nElements_missing
=0;
1310 Value
**val_prev
=(Value
**)
1311 Malloc(ans
->get_nof_ans()*sizeof(*val_prev
));
1312 boolean differs_from_prev
=true;
1313 for(size_t i
=0; i
<objs
->get_nof_objs(); i
++) {
1314 Obj_defn
*obj
=objs
->get_obj_byIndex(i
);
1315 if(!obj
->has_fs_withName_dflt(*oc_fieldname_t
)) {
1316 nElements_missing
++;
1319 OpentypeAlternative_t
*oa_t
= ot
->oal
.elements
+ i
- nElements_missing
;
1320 Type
*t_type
=dynamic_cast<Type
*>
1321 (obj
->get_setting_byName_dflt(*oc_fieldname_t
));
1323 const Identifier
& altname
= t_type
->get_otaltname(is_strange
);
1324 oa_t
->alt
= pool
.add(altname
.get_name());
1325 oa_t
->alt_dispname
= pool
.add(altname
.get_asnname());
1326 oa_t
->alt_typename
= pool
.add(t_type
->get_genname_value(my_scope
));
1327 oa_t
->alt_typedescrname
=
1328 pool
.add(t_type
->get_genname_typedescriptor(my_scope
));
1329 oa_t
->valuenames
=(const char**)Malloc
1330 (ans
->get_nof_ans()*sizeof(*oa_t
->valuenames
));
1331 oa_t
->const_valuenames
=(const char**)Malloc
1332 (ans
->get_nof_ans()*sizeof(*oa_t
->const_valuenames
));
1333 for(size_t j
=0; j
<ans
->get_nof_ans(); j
++) {
1334 AtNotation
*an
=ans
->get_an_byIndex(j
);
1335 const Identifier
*oc_fieldname_v
=an
->get_oc_fieldname();
1336 Value
*t_value
=dynamic_cast<Value
*>
1337 (obj
->get_setting_byName_dflt(*oc_fieldname_v
));
1338 oa_t
->valuenames
[j
] = pool
.add(t_value
->get_genname_own(my_scope
));
1339 if(!differs_from_prev
&& *val_prev
[j
]==*t_value
)
1340 oa_t
->const_valuenames
[j
]=0;
1342 oa_t
->const_valuenames
[j
] =
1343 pool
.add(t_value
->get_genname_own(my_scope
));
1344 differs_from_prev
=true;
1346 val_prev
[j
]=t_value
;
1348 differs_from_prev
=false;
1351 ot
->oal
.nElements
-= nElements_missing
;
1352 ot
->oal
.elements
= (OpentypeAlternative_t
*)
1353 Realloc(ot
->oal
.elements
,
1354 ot
->oal
.nElements
* sizeof(*ot
->oal
.elements
));
1358 void Type::free_code_ot(Opentype_t
* p_ot
)
1361 for (size_t i
= 0; i
< p_ot
->oal
.nElements
; i
++) {
1362 Free(p_ot
->oal
.elements
[i
].valuenames
);
1363 Free(p_ot
->oal
.elements
[i
].const_valuenames
);
1365 Free(p_ot
->oal
.elements
);
1366 for (size_t i
= 0; i
< p_ot
->anl
.nElements
; i
++)
1367 Free(p_ot
->anl
.elements
[i
].sourcecode
);
1368 Free(p_ot
->anl
.elements
);
1372 size_t Type::get_codegen_index(size_t index
)
1374 // This sorting is because of CER coding of SET types, see X.690 9.3.
1375 // see: Type::generate_code_Se()
1376 // TODO: maybe result should be cached into this type
1377 // ( inside u.secho as dynamic_array<size_t>* codegen_indexes ? )
1378 if (typetype
==T_SET_A
) {
1379 size_t nof_comps
= get_nof_comps();
1380 map
<Tag
, void> se_index_map
;
1381 for (size_t i
=0; i
<nof_comps
; i
++) {
1382 Tag
*tag
= get_comp_byIndex(i
)->get_type()->get_smallest_tag();
1383 se_index_map
.add(*tag
, (void*)i
); // hack: store size_t in void* to avoid Malloc()
1386 for(size_t i
=0; i
<nof_comps
; i
++) {
1387 if (se_index_map
.get_nth_elem(i
)==(void*)index
) {
1388 se_index_map
.clear();
1392 FATAL_ERROR("Type::get_codegen_index()");
1397 void Type::generate_code_Se(output_struct
*target
)
1401 Type
* last_field_type
= 0;
1402 memset(&sdef
, 0, sizeof(sdef
));
1403 sdef
.name
= get_genname_own().c_str();
1404 sdef
.dispname
= get_fullname().c_str();
1405 //printf("generate_code_Se(%s)\n", sdef.dispname);
1424 FATAL_ERROR("Type::generate_code_Se()");
1426 sdef
.hasText
= textattrib
!=NULL
;
1427 sdef
.nElements
= sdef
.totalElements
= get_nof_comps();
1428 sdef
.has_opentypes
= get_has_opentypes();
1429 sdef
.opentype_outermost
= get_is_opentype_outermost();
1431 sdef
.hasXer
= has_encoding(CT_XER
);
1432 sdef
.hasJson
= has_encoding(CT_JSON
);
1434 Module
*my_module
= get_my_scope()->get_scope_mod();
1435 sdef
.xerHasNamespaces
= my_module
->get_nof_ns() != 0;
1436 const char *ns
, *prefix
;
1437 my_module
->get_controlns(ns
, prefix
);
1438 sdef
.control_ns_prefix
= prefix
;
1439 sdef
.xerUntagged
= xerattrib
->untagged_
;
1440 sdef
.xerUntaggedOne
= u
.secho
.has_single_charenc
;
1441 sdef
.xerUseNilPossible
= use_nil_possible
;
1442 sdef
.xerEmbedValuesPossible
= embed_values_possible
;
1443 sdef
.xerUseOrderPossible
= use_order_possible
;
1444 if (xerattrib
->useOrder_
&& xerattrib
->useNil_
) {
1445 // We need information about the fields of the USE-NIL component
1446 const CompField
*cf
= get_comp_byIndex(sdef
.totalElements
-1);
1447 last_field_type
= cf
->get_type()->get_type_refd_last();
1448 sdef
.totalElements
+= last_field_type
->get_nof_comps();
1450 sdef
.xerUseQName
= xerattrib
->useQName_
;
1451 if (xerattrib
->useType_
|| xerattrib
->useUnion_
) {
1452 FATAL_ERROR("Type::generate_code_Se()"); // union only, not for record
1455 sdef
.elements
= (struct_field
*)
1456 Malloc(sdef
.totalElements
*sizeof(*sdef
.elements
));
1457 memset(sdef
.elements
, 0, sdef
.totalElements
* sizeof(*sdef
.elements
));
1459 /* This sorting is because of CER coding of SET types, see X.690
1461 vector
<CompField
> se_comps
;
1462 if(typetype
==T_SET_A
) {
1463 map
<Tag
, CompField
> se_comps_map
;
1464 for(size_t i
=0; i
<sdef
.nElements
; i
++) {
1465 CompField
* cf
=get_comp_byIndex(i
);
1466 Tag
*tag
= cf
->get_type()->get_smallest_tag();
1467 se_comps_map
.add(*tag
, cf
);
1470 for(size_t i
=0; i
<sdef
.nElements
; i
++)
1471 se_comps
.add(se_comps_map
.get_nth_elem(i
));
1472 se_comps_map
.clear();
1475 for(size_t i
=0; i
<sdef
.nElements
; i
++)
1476 se_comps
.add(get_comp_byIndex(i
));
1479 for(size_t i
= 0; i
< sdef
.nElements
; i
++) {
1480 struct_field
&cur
= sdef
.elements
[i
];
1481 CompField
*cf
= se_comps
[i
];
1482 const Identifier
& id
= cf
->get_name();
1483 Type
*type
= cf
->get_type();
1484 cur
.type
= pool
.add(type
->get_genname_value(my_scope
));
1485 cur
.typegen
= pool
.add(type
->get_genname_own());
1486 cur
.of_type
= type
->get_type_refd_last()->is_seof();
1488 pool
.add(type
->get_genname_typedescriptor(my_scope
));
1489 cur
.name
= id
.get_name().c_str();
1490 cur
.dispname
= id
.get_ttcnname().c_str();
1491 cur
.isOptional
= cf
->get_is_optional();
1492 cur
.isDefault
= cf
->has_default();
1493 cur
.optimizedMemAlloc
= cur
.of_type
&& (type
->get_optimize_attribute() == "memalloc");
1494 if (cur
.isDefault
) {
1495 Value
*defval
= cf
->get_defval();
1497 Code::init_cdef(&cdef
);
1498 type
->generate_code_object(&cdef
, defval
);
1499 cdef
.init
= defval
->generate_code_init
1500 (cdef
.init
, defval
->get_lhs_name().c_str());
1501 Code::merge_cdef(target
, &cdef
);
1502 Code::free_cdef(&cdef
);
1503 cur
.defvalname
= defval
->get_genname_own().c_str();
1506 if (type
->xerattrib
) {
1507 cur
.xerAttribute
= type
->xerattrib
->attribute_
;
1509 if (has_aa(type
->xerattrib
)) {
1510 cur
.xerAnyNum
= type
->xerattrib
->anyAttributes_
.nElements_
;
1511 cur
.xerAnyKind
= ANY_ATTRIB_BIT
|
1512 (type
->xerattrib
->anyAttributes_
.type_
== NamespaceRestriction::FROM
?
1513 ANY_FROM_BIT
: ANY_EXCEPT_BIT
);
1514 if (cur
.xerAnyNum
> 0)
1515 cur
.xerAnyUris
= (char**)Malloc(cur
.xerAnyNum
* sizeof(char*));
1516 for (size_t uu
=0; uu
<cur
.xerAnyNum
; ++uu
)
1517 cur
.xerAnyUris
[uu
] = type
->xerattrib
->anyAttributes_
.uris_
[uu
];
1519 else if(has_ae(type
->xerattrib
)) {
1520 cur
.xerAnyNum
= type
->xerattrib
->anyElement_
.nElements_
;
1521 cur
.xerAnyKind
= ANY_ELEM_BIT
|
1522 (type
->xerattrib
->anyElement_
.type_
== NamespaceRestriction::FROM
?
1523 ANY_FROM_BIT
: ANY_EXCEPT_BIT
);
1524 if (cur
.xerAnyNum
> 0)
1525 cur
.xerAnyUris
= (char**)Malloc(cur
.xerAnyNum
* sizeof(char*));
1526 for (size_t uu
=0; uu
<cur
.xerAnyNum
; ++uu
)
1527 cur
.xerAnyUris
[uu
] = type
->xerattrib
->anyElement_
.uris_
[uu
];
1530 if (type
->jsonattrib
) {
1531 cur
.jsonOmitAsNull
= type
->jsonattrib
->omit_as_null
;
1532 cur
.jsonAlias
= type
->jsonattrib
->alias
;
1533 cur
.jsonDefaultValue
= type
->jsonattrib
->default_value
;
1537 if (last_field_type
)
1538 for (size_t i
= sdef
.nElements
; i
< sdef
.totalElements
; i
++) {
1539 struct_field
&cur
= sdef
.elements
[i
];
1540 CompField
*cf
= last_field_type
->get_comp_byIndex(i
- sdef
.nElements
);
1541 const Identifier
& id
= cf
->get_name();
1542 Type
*type
= cf
->get_type();
1543 cur
.type
= pool
.add(type
->get_genname_value(my_scope
));
1544 cur
.typegen
= pool
.add(type
->get_genname_own());
1545 cur
.of_type
= type
->get_type_refd_last()->is_seof();
1547 pool
.add(type
->get_genname_typedescriptor(my_scope
));
1548 cur
.name
= id
.get_name().c_str();
1549 cur
.dispname
= id
.get_ttcnname().c_str();
1550 cur
.isOptional
= cf
->get_is_optional();
1555 copy_rawAST_to_struct(rawattrib
,&(sdef
.raw
));
1558 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++) {
1559 if(rawattrib
->taglist
.tag
[c
].nElements
)
1560 sdef
.raw
.taglist
.list
[c
].fields
=
1561 (rawAST_coding_field_list
*)
1562 Malloc(rawattrib
->taglist
.tag
[c
].nElements
1563 *sizeof(rawAST_coding_field_list
));
1564 else sdef
.raw
.taglist
.list
[c
].fields
=NULL
;
1565 sdef
.raw
.taglist
.list
[c
].nElements
=
1566 rawattrib
->taglist
.tag
[c
].nElements
;
1567 sdef
.raw
.taglist
.list
[c
].fieldName
=
1568 rawattrib
->taglist
.tag
[c
].fieldName
->get_name().c_str();
1569 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
1570 sdef
.raw
.taglist
.list
[c
].fieldnum
=get_comp_index_byName(*idf
);
1571 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
1572 rawAST_coding_field_list
* key
=
1573 sdef
.raw
.taglist
.list
[c
].fields
+a
;
1575 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->nElements
+1;
1576 key
->value
=rawattrib
->taglist
.tag
[c
].keyList
[a
].value
;
1578 key
->fields
=(rawAST_coding_fields
*)
1579 Malloc(key
->nElements
*sizeof(rawAST_coding_fields
));
1581 CompField
*cf
=get_comp_byIndex(sdef
.raw
.taglist
.list
[c
].fieldnum
);
1582 Type
*t
=cf
->get_type()->get_type_refd_last();
1584 key
->fields
[0].nthfield
= sdef
.raw
.taglist
.list
[c
].fieldnum
;
1585 key
->fields
[0].nthfieldname
=
1586 rawattrib
->taglist
.tag
[c
].fieldName
->get_name().c_str();
1587 if (cf
->get_is_optional())
1588 key
->fields
[0].fieldtype
= OPTIONAL_FIELD
;
1589 else key
->fields
[0].fieldtype
= MANDATORY_FIELD
;
1590 key
->fields
[0].type
= pool
.add(t
->get_genname_value(my_scope
));
1591 key
->fields
[0].typedescr
=
1592 pool
.add(t
->get_genname_typedescriptor(my_scope
));
1595 for (int b
= 1; b
< key
->nElements
; b
++) {
1597 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
-1];
1598 size_t comp_index
= t
->get_comp_index_byName(*idf2
);
1599 cf2
= t
->get_comp_byIndex(comp_index
);
1600 key
->fields
[b
].nthfield
= comp_index
;
1601 key
->fields
[b
].nthfieldname
= idf2
->get_name().c_str();
1602 if (t
->typetype
== T_CHOICE_T
)
1603 key
->fields
[b
].fieldtype
= UNION_FIELD
;
1604 else if (cf2
->get_is_optional())
1605 key
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1606 else key
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1607 Type
*field_type
= cf2
->get_type();
1608 key
->fields
[b
].type
=
1609 pool
.add(field_type
->get_genname_value(my_scope
));
1610 key
->fields
[b
].typedescr
=
1611 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1612 if (field_type
->typetype
== T_SEQ_T
&& field_type
->rawattrib
1613 && (field_type
->rawattrib
->pointerto
1614 || field_type
->rawattrib
->lengthto_num
))
1615 key
->start_pos
= -1;
1617 if(t
->typetype
!= T_CHOICE_T
&& t
->typetype
!= T_SET_T
){
1619 for(size_t i
= 0; i
< comp_index
&& key
->start_pos
>=0; i
++)
1621 t2
= t
->get_comp_byIndex(i
)->get_type();
1622 if(t2
->get_raw_length() >= 0){
1624 key
->start_pos
+= t2
->rawattrib
->padding
;
1625 key
->start_pos
+= t2
->get_raw_length();
1626 }else key
->start_pos
= -1;
1629 t
= field_type
->get_type_refd_last();
1633 // building presence list
1634 for(int a
=0;a
<rawattrib
->presence
.nElements
;a
++) {
1635 rawAST_coding_field_list
* presences
=sdef
.raw
.presence
.fields
+a
;
1636 presences
->nElements
=
1637 rawattrib
->presence
.keyList
[a
].keyField
->nElements
;
1638 presences
->value
=rawattrib
->presence
.keyList
[a
].value
;
1639 presences
->fields
=(rawAST_coding_fields
*)
1640 Malloc(presences
->nElements
*sizeof(rawAST_coding_fields
));
1642 for (int b
= 0; b
< presences
->nElements
; b
++) {
1643 Identifier
*idf
= rawattrib
->presence
.keyList
[a
].keyField
->names
[b
];
1644 size_t comp_index
= t
->get_comp_index_byName(*idf
);
1645 CompField
*cf
= t
->get_comp_byIndex(comp_index
);
1646 presences
->fields
[b
].nthfield
= comp_index
;
1647 presences
->fields
[b
].nthfieldname
= idf
->get_name().c_str();
1648 if (t
->typetype
== T_CHOICE_T
)
1649 presences
->fields
[b
].fieldtype
= UNION_FIELD
;
1650 else if (cf
->get_is_optional())
1651 presences
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1652 else presences
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1653 Type
*field_type
= cf
->get_type();
1654 presences
->fields
[b
].type
=
1655 pool
.add(field_type
->get_genname_value(my_scope
));
1656 presences
->fields
[b
].typedescr
=
1657 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1658 t
= field_type
->get_type_refd_last();
1661 for(int c
=0;c
<rawattrib
->ext_bit_goup_num
;c
++){
1662 Identifier
*idf
=rawattrib
->ext_bit_groups
[c
].from
;
1663 Identifier
*idf2
=rawattrib
->ext_bit_groups
[c
].to
;
1664 sdef
.raw
.ext_bit_groups
[c
].ext_bit
=rawattrib
->ext_bit_groups
[c
].ext_bit
;
1665 sdef
.raw
.ext_bit_groups
[c
].from
=(int)get_comp_index_byName(*idf
);
1666 sdef
.raw
.ext_bit_groups
[c
].to
=(int)get_comp_index_byName(*idf2
);
1668 for(size_t i
=0; i
<sdef
.totalElements
; i
++) {
1669 CompField
*cf
= get_comp_byIndex(i
);
1670 Type
*t_field
= cf
->get_type();
1671 Type
*t_field_last
= t_field
->get_type_refd_last();
1672 RawAST
*rawpar
= t_field
->rawattrib
;
1674 copy_rawAST_to_struct(rawpar
,&(sdef
.elements
[i
].raw
));
1675 for(int j
=0; j
<rawpar
->lengthto_num
;j
++){
1676 Identifier
*idf
=rawpar
->lengthto
[j
];
1677 sdef
.elements
[i
].raw
.lengthto
[j
]=get_comp_index_byName(*idf
);
1679 if (rawpar
->lengthto_num
&& rawpar
->lengthindex
) {
1680 Identifier
*idf
= rawpar
->lengthindex
->names
[0];
1681 size_t comp_index
= t_field_last
->get_comp_index_byName(*idf
);
1682 sdef
.elements
[i
].raw
.lengthindex
->nthfield
= comp_index
;
1683 sdef
.elements
[i
].raw
.lengthindex
->nthfieldname
=
1684 idf
->get_name().c_str();
1685 CompField
*cf2
= t_field_last
->get_comp_byIndex(comp_index
);
1686 Type
*t_field2
= cf2
->get_type();
1687 if (t_field2
->typetype
== T_CHOICE_T
)
1688 sdef
.elements
[i
].raw
.lengthindex
->fieldtype
= UNION_FIELD
;
1689 else if (cf2
->get_is_optional())
1690 sdef
.elements
[i
].raw
.lengthindex
->fieldtype
= OPTIONAL_FIELD
;
1691 else sdef
.elements
[i
].raw
.lengthindex
->fieldtype
= MANDATORY_FIELD
;
1692 sdef
.elements
[i
].raw
.lengthindex
->type
=
1693 pool
.add(t_field2
->get_genname_value(my_scope
));
1694 sdef
.elements
[i
].raw
.lengthindex
->typedescr
=
1695 pool
.add(t_field2
->get_genname_typedescriptor(my_scope
));
1697 if (rawpar
->lengthto_num
&& !rawpar
->lengthindex
&&
1698 t_field_last
->is_secho()) {
1699 int comp_num
=(int)t_field_last
->get_nof_comps();
1700 sdef
.elements
[i
].raw
.union_member_num
=comp_num
;
1701 sdef
.elements
[i
].raw
.member_name
=
1702 (const char **)Malloc((comp_num
+1)*sizeof(const char*));
1703 sdef
.elements
[i
].raw
.member_name
[0] =
1704 pool
.add(t_field_last
->get_genname_value(my_scope
));
1705 for(int m
=1;m
<comp_num
+1;m
++){
1706 CompField
*compf
=t_field_last
->get_comp_byIndex(m
-1);
1707 sdef
.elements
[i
].raw
.member_name
[m
]=
1708 compf
->get_name().get_name().c_str();
1711 if(rawpar
->pointerto
){
1712 Identifier
*idf
=rawpar
->pointerto
;
1713 sdef
.elements
[i
].raw
.pointerto
=get_comp_index_byName(*idf
);
1714 if(rawpar
->ptrbase
){
1715 Identifier
*idf2
=rawpar
->ptrbase
;
1716 sdef
.elements
[i
].raw
.pointerbase
=get_comp_index_byName(*idf2
);
1717 } else sdef
.elements
[i
].raw
.pointerbase
=i
;
1719 // building presence list
1720 for(int a
=0;a
<rawpar
->presence
.nElements
;a
++) {
1721 rawAST_coding_field_list
* presences
=
1722 sdef
.elements
[i
].raw
.presence
.fields
+a
;
1723 presences
->nElements
=
1724 rawpar
->presence
.keyList
[a
].keyField
->nElements
;
1725 presences
->value
=rawpar
->presence
.keyList
[a
].value
;
1726 presences
->fields
=(rawAST_coding_fields
*)
1727 Malloc(presences
->nElements
*sizeof(rawAST_coding_fields
));
1729 for (int b
= 0; b
< presences
->nElements
; b
++) {
1730 Identifier
*idf
= rawpar
->presence
.keyList
[a
].keyField
->names
[b
];
1731 size_t comp_index
= t
->get_comp_index_byName(*idf
);
1732 CompField
*cf2
= t
->get_comp_byIndex(comp_index
);
1733 presences
->fields
[b
].nthfield
= comp_index
;
1734 presences
->fields
[b
].nthfieldname
= idf
->get_name().c_str();
1735 if (t
->typetype
== T_CHOICE_T
)
1736 presences
->fields
[b
].fieldtype
= UNION_FIELD
;
1737 else if (cf2
->get_is_optional())
1738 presences
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1739 else presences
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1740 Type
*field_type
= cf2
->get_type();
1741 presences
->fields
[b
].type
=
1742 pool
.add(field_type
->get_genname_value(my_scope
));
1743 presences
->fields
[b
].typedescr
=
1744 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1745 t
= field_type
->get_type_refd_last();
1748 // building crosstaglist
1749 for(int c
=0;c
<rawpar
->crosstaglist
.nElements
;c
++){
1750 if(rawpar
->crosstaglist
.tag
[c
].nElements
)
1751 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fields
=
1752 (rawAST_coding_field_list
*)
1753 Malloc(rawpar
->crosstaglist
.tag
[c
].nElements
1754 *sizeof(rawAST_coding_field_list
));
1755 else sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fields
=NULL
;
1756 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].nElements
=
1757 rawpar
->crosstaglist
.tag
[c
].nElements
;
1758 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fieldName
=
1759 rawpar
->crosstaglist
.tag
[c
].fieldName
->get_name().c_str();
1760 Identifier
*idf
=rawpar
->crosstaglist
.tag
[c
].fieldName
;
1761 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fieldnum
=
1762 t_field_last
->get_comp_index_byName(*idf
);
1763 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fieldnum
=
1764 t_field_last
->get_comp_index_byName(*idf
);
1765 for(int a
=0;a
<rawpar
->crosstaglist
.tag
[c
].nElements
;a
++) {
1766 rawAST_coding_field_list
* key
=
1767 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fields
+a
;
1769 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->nElements
;
1770 key
->value
=rawpar
->crosstaglist
.tag
[c
].keyList
[a
].value
;
1771 key
->fields
=(rawAST_coding_fields
*)
1772 Malloc(key
->nElements
*sizeof(rawAST_coding_fields
));
1774 for (int b
= 0; b
< key
->nElements
; b
++) {
1776 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
1777 size_t comp_index
= t
->get_comp_index_byName(*idf2
);
1778 CompField
*cf2
= t
->get_comp_byIndex(comp_index
);
1779 key
->fields
[b
].nthfield
= comp_index
;
1780 key
->fields
[b
].nthfieldname
= idf2
->get_name().c_str();
1781 if (t
->typetype
== T_CHOICE_T
)
1782 key
->fields
[b
].fieldtype
= UNION_FIELD
;
1783 else if (cf2
->get_is_optional())
1784 key
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1785 else key
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1786 Type
*field_type
= cf2
->get_type();
1787 key
->fields
[b
].type
=
1788 pool
.add(field_type
->get_genname_value(my_scope
));
1789 key
->fields
[b
].typedescr
=
1790 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1791 t
= field_type
->get_type_refd_last();
1795 sdef
.elements
[i
].raw
.length
= t_field
->get_raw_length();
1796 sdef
.elements
[i
].hasRaw
=true;
1799 sdef
.elements
[i
].hasRaw
=false;
1804 for(size_t i
= 0; i
< sdef
.totalElements
; i
++) {
1805 sdef
.elements
[i
].hasRaw
=false;
1810 defRecordClass(&sdef
, target
);
1811 defRecordTemplate(&sdef
, target
);
1813 for(size_t i
= 0; i
< sdef
.totalElements
; i
++) {
1814 // free the array but not the strings
1815 if (sdef
.elements
[i
].xerAnyNum
> 0) Free(sdef
.elements
[i
].xerAnyUris
);
1819 free_raw_attrib_struct(&sdef
.raw
);
1820 for (size_t i
= 0; i
< sdef
.totalElements
; i
++) {
1821 if (sdef
.elements
[i
].hasRaw
) {
1822 free_raw_attrib_struct(&sdef
.elements
[i
].raw
);
1826 Free(sdef
.elements
);
1829 bool Type::is_untagged() const { return xerattrib
&& xerattrib
->untagged_
; }
1831 void Type::generate_code_SeOf(output_struct
*target
)
1833 const Type
*oftypelast
= u
.seof
.ofType
->get_type_refd_last();
1834 const string
& oftypename
= u
.seof
.ofType
->get_genname_value(my_scope
);
1835 boolean optimized_memalloc
= !use_runtime_2
&& get_optimize_attribute() == "memalloc";
1837 if (is_pregenerated()) {
1838 switch(oftypelast
->typetype
) {
1841 case T_TELETEXSTRING
:
1842 case T_VIDEOTEXSTRING
:
1843 case T_GRAPHICSTRING
:
1844 case T_GENERALSTRING
:
1845 case T_UNIVERSALSTRING
:
1847 case T_OBJECTDESCRIPTOR
:
1848 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1849 "typedef PreGenRecordOf::PREGEN__%s__OF__UNIVERSAL__CHARSTRING%s %s;\n"
1850 "typedef PreGenRecordOf::PREGEN__%s__OF__UNIVERSAL__CHARSTRING%s_template %s_template;\n",
1851 (typetype
== T_SEQOF
) ? "RECORD" : "SET",
1852 optimized_memalloc
? "__OPTIMIZED" : "", get_genname_own().c_str(),
1853 (typetype
== T_SEQOF
) ? "RECORD" : "SET",
1854 optimized_memalloc
? "__OPTIMIZED" : "", get_genname_own().c_str());
1857 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1858 "typedef PreGenRecordOf::PREGEN__%s__OF__%s%s %s;\n"
1859 "typedef PreGenRecordOf::PREGEN__%s__OF__%s%s_template %s_template;\n",
1860 (typetype
== T_SEQOF
) ? "RECORD" : "SET", oftypename
.c_str(),
1861 optimized_memalloc
? "__OPTIMIZED" : "", get_genname_own().c_str(),
1862 (typetype
== T_SEQOF
) ? "RECORD" : "SET", oftypename
.c_str(),
1863 optimized_memalloc
? "__OPTIMIZED" : "", get_genname_own().c_str());
1869 struct_of_def sofdef
;
1870 memset(&sofdef
, 0, sizeof(sofdef
));
1871 sofdef
.name
= get_genname_own().c_str();
1872 sofdef
.dispname
= get_fullname().c_str();
1873 sofdef
.kind
= typetype
== T_SEQOF
? RECORD_OF
: SET_OF
;
1874 sofdef
.isASN1
= is_asn1();
1875 sofdef
.hasText
= textattrib
!=NULL
;
1876 sofdef
.hasXer
= has_encoding(CT_XER
);
1877 sofdef
.hasJson
= has_encoding(CT_JSON
);
1879 //sofdef.xerList = xerattrib->list_;
1880 sofdef
.xerAttribute
= xerattrib
->attribute_
;
1882 // If a record of UTF8String, we need to prepare for ANY-ATTRIBUTES and
1884 sofdef
.xerAnyAttrElem
= oftypelast
->typetype
== T_USTR
1885 || oftypelast
->typetype
== T_UTF8STRING
;
1886 sofdef
.type
= oftypename
.c_str();
1887 sofdef
.has_opentypes
= get_has_opentypes();
1888 const string
& oftypedescrname
=
1889 u
.seof
.ofType
->get_genname_typedescriptor(my_scope
);
1890 sofdef
.oftypedescrname
= oftypedescrname
.c_str();
1892 if (xerattrib
&& xerattrib
->untagged_
1893 && ((u
.seof
.ofType
->xerattrib
&& has_ae(u
.seof
.ofType
->xerattrib
))
1894 || (xerattrib
&& has_ae(xerattrib
)))) {
1895 // An untagged record-of which has an embedded type with ANY-ELEMENT,
1896 // or itself has ANY-ELEMENT
1897 if (parent_type
&& parent_type
->typetype
== T_SEQ_T
) {
1898 /* The record-of needs to know the optional siblings following it,
1899 * to be able to stop consuming XML elements that belong
1900 * to the following fields. This is achieved by generating
1901 * a can_start() for the record-of which returns false for XML elements
1902 * that belong to those following fields. */
1903 size_t n_parent_comps
= parent_type
->get_nof_comps();
1904 boolean found_self
= false;
1905 /* Go through the fields of the parent; skip everything until we find
1906 * the field that is this record-of; then collect fields until
1907 * the first non-disappearing field. */
1908 for (size_t pc
= 0; pc
< n_parent_comps
; ++pc
) {
1909 CompField
*pcf
= parent_type
->get_comp_byIndex(pc
); //"ParentCompField"
1910 Type
*pcft
= pcf
->get_type();
1912 const Identifier
& cfid
= pcf
->get_name();
1913 sofdef
.followers
= (struct_field
*)Realloc(sofdef
.followers
,
1914 (++sofdef
.nFollowers
) * sizeof(struct_field
));
1915 sofdef
.followers
[sofdef
.nFollowers
-1].name
= pool
.add(cfid
.get_name());
1916 sofdef
.followers
[sofdef
.nFollowers
-1].type
=
1917 pool
.add(pcft
->get_genname_value(my_scope
));
1918 sofdef
.followers
[sofdef
.nFollowers
-1].typegen
=
1919 pool
.add(pcft
->get_genname_own());
1921 Type
*pcft_last
= pcft
->get_type_refd_last();
1922 if (pcf
->get_is_optional()
1923 || (pcft
->is_untagged() && pcft_last
->has_empty_xml()))
1924 {} // can disappear, continue
1927 else if (pcft
== this) found_self
= true;
1929 } // if parent is record
1932 switch (oftypelast
->typetype
) { // X.680/2002, Table 5 under 25.5
1933 // T_CHOICE_A and T_CHOICE_T do not set xmlValueList because choice types
1934 // already omit their own tag.
1936 case T_ENUM_A
: case T_ENUM_T
:
1938 sofdef
.xmlValueList
= TRUE
;
1942 sofdef
.xmlValueList
= FALSE
;
1947 copy_rawAST_to_struct(rawattrib
,&(sofdef
.raw
));
1949 } else sofdef
.hasRaw
=false;
1951 if (optimized_memalloc
) {
1952 defRecordOfClassMemAllocOptimized(&sofdef
, target
);
1954 defRecordOfClass(&sofdef
, target
);
1956 defRecordOfTemplate(&sofdef
, target
);
1958 if (sofdef
.nFollowers
) {
1959 Free(sofdef
.followers
);
1963 void Type::generate_code_Array(output_struct
*target
)
1965 if (!u
.array
.in_typedef
) return;
1966 const char *own_name
= get_genname_own().c_str();
1967 if (has_encoding(CT_JSON
)) {
1968 target
->header
.class_decls
= mputprintf(target
->header
.class_decls
,
1969 "class %s;\n", own_name
);
1970 target
->header
.class_defs
= mputprintf(target
->header
.class_defs
,
1971 "class %s : public %s {\n"
1972 "const TTCN_Typedescriptor_t* get_elem_descr() const;\n"
1975 u
.array
.dimension
->get_value_type(u
.array
.element_type
, my_scope
).c_str());
1976 target
->source
.class_defs
= mputprintf(target
->source
.class_defs
,
1977 "const TTCN_Typedescriptor_t* %s::get_elem_descr() const { return &%s_descr_; }\n\n",
1978 own_name
, u
.array
.element_type
->get_genname_typedescriptor(my_scope
).c_str());
1980 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1982 "// written by %s in " __FILE__
" at %d\n"
1986 __FUNCTION__
, __LINE__
,
1988 u
.array
.dimension
->get_value_type(u
.array
.element_type
, my_scope
).c_str(),
1991 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1992 "typedef %s %s_template;\n",
1993 u
.array
.dimension
->get_template_type(u
.array
.element_type
, my_scope
).c_str(),
1997 void Type::generate_code_Fat(output_struct
*target
)
2000 memset(&fdef
, 0, sizeof(fdef
));
2001 fdef
.name
= get_genname_own().c_str();
2002 fdef
.dispname
= get_fullname().c_str();
2005 if(u
.fatref
.return_type
)
2006 if(u
.fatref
.returns_template
)
2007 fdef
.return_type
= mcopystr(u
.fatref
.return_type
->
2008 get_genname_template(my_scope
).c_str());
2009 else fdef
.return_type
= mcopystr(u
.fatref
.return_type
->
2010 get_genname_value(my_scope
).c_str());
2011 else fdef
.return_type
= NULL
;
2012 fdef
.type
= FUNCTION
;
2015 fdef
.return_type
= NULL
;
2016 fdef
.type
= ALTSTEP
;
2019 fdef
.return_type
= NULL
;
2020 fdef
.type
= TESTCASE
;
2023 FATAL_ERROR("Type::generate_code_Fat()");
2025 fdef
.runs_on_self
= u
.fatref
.runs_on
.self
? TRUE
: FALSE
;
2026 fdef
.is_startable
= u
.fatref
.is_startable
;
2027 fdef
.formal_par_list
= u
.fatref
.fp_list
->generate_code(memptystr());
2028 u
.fatref
.fp_list
->generate_code_defval(target
);
2029 fdef
.actual_par_list
= u
.fatref
.fp_list
2030 ->generate_code_actual_parlist(memptystr(),"");
2031 if (typetype
== T_TESTCASE
) {
2032 if (u
.fatref
.fp_list
->get_nof_fps() > 0) {
2033 fdef
.formal_par_list
= mputstr(fdef
.formal_par_list
, ", ");
2034 fdef
.actual_par_list
= mputstr(fdef
.actual_par_list
, ", ");
2036 fdef
.formal_par_list
= mputstr(fdef
.formal_par_list
,
2037 "boolean has_timer, double timer_value");
2038 fdef
.actual_par_list
= mputstr(fdef
.actual_par_list
,
2039 "has_timer, timer_value");
2041 fdef
.nElements
= u
.fatref
.fp_list
->get_nof_fps();
2042 fdef
.parameters
= (const char**)
2043 Malloc(fdef
.nElements
* sizeof(*fdef
.parameters
));
2044 for(size_t i
= 0;i
< fdef
.nElements
; i
++) {
2045 fdef
.parameters
[i
] = u
.fatref
.fp_list
->get_fp_byIndex(i
)
2046 ->get_id().get_name().c_str();
2049 defFunctionrefClass(&fdef
, target
);
2050 defFunctionrefTemplate(&fdef
, target
);
2051 Free(fdef
.return_type
);
2052 Free(fdef
.formal_par_list
);
2053 Free(fdef
.actual_par_list
);
2054 Free(fdef
.parameters
);
2057 void Type::generate_code_Signature(output_struct
*target
)
2061 memset(&sdef
, 0, sizeof(sdef
));
2062 sdef
.name
= get_genname_own().c_str();
2063 sdef
.dispname
= get_fullname().c_str();
2064 if (u
.signature
.return_type
) sdef
.return_type
=
2065 pool
.add(u
.signature
.return_type
->get_genname_value(my_scope
));
2066 else sdef
.return_type
= NULL
;
2067 if (u
.signature
.parameters
) {
2068 sdef
.parameters
.nElements
= u
.signature
.parameters
->get_nof_params();
2069 sdef
.parameters
.elements
= (signature_par
*)
2070 Malloc(sdef
.parameters
.nElements
* sizeof(*sdef
.parameters
.elements
));
2071 for (size_t i
= 0; i
< sdef
.parameters
.nElements
; i
++) {
2072 SignatureParam
*param
= u
.signature
.parameters
->get_param_byIndex(i
);
2073 switch (param
->get_direction()) {
2074 case SignatureParam::PARAM_IN
:
2075 sdef
.parameters
.elements
[i
].direction
= PAR_IN
;
2077 case SignatureParam::PARAM_OUT
:
2078 sdef
.parameters
.elements
[i
].direction
= PAR_OUT
;
2080 case SignatureParam::PARAM_INOUT
:
2081 sdef
.parameters
.elements
[i
].direction
= PAR_INOUT
;
2084 FATAL_ERROR("Type::generate_code_Signature()");
2086 sdef
.parameters
.elements
[i
].type
=
2087 pool
.add(param
->get_type()->get_genname_value(my_scope
));
2088 sdef
.parameters
.elements
[i
].name
= param
->get_id().get_name().c_str();
2089 sdef
.parameters
.elements
[i
].dispname
=
2090 param
->get_id().get_ttcnname().c_str();
2093 sdef
.parameters
.nElements
= 0;
2094 sdef
.parameters
.elements
= NULL
;
2096 sdef
.is_noblock
= u
.signature
.no_block
;
2097 if (u
.signature
.exceptions
) {
2098 sdef
.exceptions
.nElements
= u
.signature
.exceptions
->get_nof_types();
2099 sdef
.exceptions
.elements
= (signature_exception
*)
2100 Malloc(sdef
.exceptions
.nElements
* sizeof(*sdef
.exceptions
.elements
));
2101 for (size_t i
= 0; i
< sdef
.exceptions
.nElements
; i
++) {
2102 Type
*type
= u
.signature
.exceptions
->get_type_byIndex(i
);
2103 sdef
.exceptions
.elements
[i
].name
=
2104 pool
.add(type
->get_genname_value(my_scope
));
2105 sdef
.exceptions
.elements
[i
].dispname
= pool
.add(type
->get_typename());
2106 sdef
.exceptions
.elements
[i
].altname
= pool
.add(type
->get_genname_altname());
2109 sdef
.exceptions
.nElements
= 0;
2110 sdef
.exceptions
.elements
= NULL
;
2112 defSignatureClasses(&sdef
, target
);
2113 Free(sdef
.parameters
.elements
);
2114 Free(sdef
.exceptions
.elements
);
2117 bool Type::needs_alias()
2119 /** The decision is actually based on the fullname of the type. If it
2120 * contains two or more dot (.) characters false is returned.
2121 * The following attributes cannot be used for the decision:
2122 * - parent_type, my_scope: types within ASN.1 object classes, objects
2123 * look the same as top-level aliased types, but they do not need alias. */
2124 const string
& full_name
= get_fullname();
2125 size_t fullname_len
= full_name
.size();
2126 size_t first_dot
= full_name
.find('.', 0);
2127 if (first_dot
>= fullname_len
) return true; // no dots
2128 else if (full_name
.find('.', first_dot
+ 1) < fullname_len
) return false;
2133 void Type::generate_code_done(output_struct
*target
)
2135 const string
& t_genname
= get_genname_value(my_scope
);
2136 const char *genname_str
= t_genname
.c_str();
2137 const string
& dispname
= get_typename();
2138 const char *dispname_str
= dispname
.c_str();
2139 target
->header
.function_prototypes
= mputprintf
2140 (target
->header
.function_prototypes
,
2141 "extern alt_status done(const COMPONENT& component_reference, "
2142 "const %s_template& value_template, %s *value_ptr);\n",
2143 genname_str
, genname_str
);
2144 target
->source
.function_bodies
= mputprintf
2145 (target
->source
.function_bodies
,
2146 "alt_status done(const COMPONENT& component_reference, "
2147 "const %s_template& value_template, %s *value_ptr)\n"
2149 "if (!component_reference.is_bound()) "
2150 "TTCN_error(\"Performing a done operation on an unbound component "
2152 "Text_Buf *text_buf;\n"
2153 "alt_status ret_val = TTCN_Runtime::component_done("
2154 "(component)component_reference, \"%s\", text_buf);\n"
2155 "if (ret_val == ALT_YES) {\n"
2156 "%s return_value;\n"
2157 "return_value.decode_text(*text_buf);\n"
2158 "if (value_template.match(return_value)) {\n"
2159 "if (value_ptr != NULL) *value_ptr = return_value;\n"
2160 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
2161 "TTCN_Logger::log_event_str(\"PTC with component reference \");\n"
2162 "component_reference.log();\n"
2163 "TTCN_Logger::log_event_str(\" is done. Return value: %s : \");\n"
2164 "return_value.log();\n"
2165 "TTCN_Logger::end_event();\n"
2168 "if (TTCN_Logger::log_this_event(TTCN_Logger::MATCHING_DONE)) {\n"
2169 "TTCN_Logger::begin_event(TTCN_Logger::MATCHING_DONE);\n"
2170 "TTCN_Logger::log_event_str(\"Done operation with type %s on"
2171 " component reference \");\n"
2172 "component_reference.log();\n"
2173 "TTCN_Logger::log_event_str(\" failed: Return value does not match "
2174 "the template: \");\n"
2175 "value_template.log_match(return_value);\n"
2176 "TTCN_Logger::end_event();\n"
2180 "} else return ret_val;\n"
2182 genname_str
, genname_str
, dispname_str
, genname_str
, dispname_str
,
2186 bool Type::ispresent_anyvalue_embedded_field(Type
* t
,
2187 Ttcn::FieldOrArrayRefs
*subrefs
, size_t begin_index
)
2189 if (!subrefs
) return true;
2190 size_t nof_refs
= subrefs
->get_nof_refs();
2191 for (size_t i
= begin_index
; i
< nof_refs
; i
++) {
2192 t
= t
->get_type_refd_last();
2193 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
2194 switch (ref
->get_type()) {
2195 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
2196 CompField
* cf
= t
->get_comp_byName(*ref
->get_id());
2197 switch (t
->typetype
) {
2207 if (cf
->get_is_optional()) return false;
2210 FATAL_ERROR("Type::ispresent_anyvalue_embedded_field()");
2214 case Ttcn::FieldOrArrayRef::ARRAY_REF
:
2215 switch (t
->typetype
) {
2218 return false; // (the existence of a record of element is optional)
2220 t
= t
->u
.array
.element_type
;
2223 return true; // string types
2227 FATAL_ERROR("Type::ispresent_anyvalue_embedded_field()");
2233 void Type::generate_code_ispresentbound(expression_struct
*expr
,
2234 Ttcn::FieldOrArrayRefs
*subrefs
, Common::Module
* module
,
2235 const string
& global_id
, const string
& external_id
, const bool is_template
,
2238 if (!subrefs
) return;
2242 bool next_o
; // next is optional value
2243 size_t nof_refs
= subrefs
->get_nof_refs();
2244 subrefs
->clear_string_element_ref();
2245 char *tmp_generalid_str
= mcopystr(external_id
.c_str());
2246 expstring_t closing_brackets
= memptystr(); //The closing parts collected
2247 for (size_t i
= 0; i
< nof_refs
; i
++) {
2248 t
= t
->get_type_refd_last();
2249 // stop immediately if current type t is erroneous
2250 // (e.g. because of circular reference)
2251 if (t
->typetype
== T_ERROR
) return;
2254 bool anyval_ret_val
= true;
2256 anyval_ret_val
= ispresent_anyvalue_embedded_field(t
, subrefs
, i
);
2258 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2259 expr
->expr
= mputprintf(expr
->expr
,
2260 "switch (%s.get_selection()) {\n"
2261 "case UNINITIALIZED_TEMPLATE:\n"
2267 "case SPECIFIC_VALUE: {\n",
2268 tmp_generalid_str
, global_id
.c_str(), global_id
.c_str(),
2269 anyval_ret_val
? "true" : "false");
2271 expstring_t closing_brackets_switch
= mprintf(
2279 global_id
.c_str(), closing_brackets
);
2280 Free(closing_brackets
);
2281 closing_brackets
= closing_brackets_switch
;
2284 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
2285 switch (ref
->get_type()) {
2286 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
2287 const Identifier
& id
= *ref
->get_id();
2288 CompField
* cf
= t
->get_comp_byName(id
);
2289 next_t
= cf
->get_type();
2290 next_o
= !is_template
&& cf
->get_is_optional();
2292 switch (t
->typetype
) {
2296 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2297 expr
->expr
= mputprintf(expr
->expr
,
2298 "%s = %s.ischosen(%s::ALT_%s);\n", global_id
.c_str(),
2300 t
->get_genname_value(module
).c_str(),
2301 id
.get_name().c_str());
2302 expr
->expr
= mputstr(expr
->expr
, "}\n");
2303 // intentionally missing break
2311 FATAL_ERROR("Type::generate_code_isbound()");
2315 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2316 expstring_t closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2317 Free(closing_brackets
);
2318 closing_brackets
= closing_brackets2
;
2320 const string
& tmp_id
= module
->get_temporary_id();
2321 const char *tmp_id_str
= tmp_id
.c_str();
2322 expr
->expr
= mputprintf(expr
->expr
,
2323 "const OPTIONAL<%s%s>& %s = %s.%s();\n",
2324 next_t
->get_genname_value(module
).c_str(),
2325 is_template
?"_template":"", tmp_id_str
, tmp_generalid_str
,
2326 id
.get_name().c_str());
2328 if (i
==(nof_refs
-1)) {
2329 // we are at the end of the reference chain
2330 expr
->expr
= mputprintf(expr
->expr
,
2331 "switch (%s.get_selection()) {\n"
2332 "case OPTIONAL_UNBOUND:\n"
2335 "case OPTIONAL_OMIT:\n"
2339 tmp_id_str
, global_id
.c_str(),global_id
.c_str(),
2340 isbound
? "true" : "false");
2341 Free(tmp_generalid_str
);
2342 tmp_generalid_str
= mcopystr(tmp_id_str
);
2344 expr
->expr
= mputstr(expr
->expr
, "{\n");
2345 const string
& tmp_id2
= module
->get_temporary_id();
2346 const char *tmp_id2_str
= tmp_id2
.c_str();
2347 expr
->expr
= mputprintf(expr
->expr
,
2348 "const %s%s& %s = (const %s%s&) %s;\n",
2349 next_t
->get_genname_value(module
).c_str(),
2350 is_template
?"_template":"", tmp_id2_str
,
2351 next_t
->get_genname_value(module
).c_str(),
2352 is_template
?"_template":"", tmp_id_str
);
2354 expr
->expr
= mputprintf(expr
->expr
,
2355 "%s = %s.%s();\n", global_id
.c_str(),
2356 tmp_id2_str
, isbound
? "is_bound" : "is_present");
2357 Free(tmp_generalid_str
);
2358 tmp_generalid_str
= mcopystr(tmp_id2_str
);
2360 expr
->expr
= mputprintf(expr
->expr
,
2364 expr
->expr
= mputprintf(expr
->expr
,
2365 "switch (%s.get_selection()) {\n"
2366 "case OPTIONAL_UNBOUND:\n"
2367 "case OPTIONAL_OMIT:\n"
2373 tmp_id_str
, global_id
.c_str());
2374 Free(tmp_generalid_str
);
2375 tmp_generalid_str
= mcopystr(tmp_id_str
);
2377 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2378 closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2379 Free(closing_brackets
);
2380 closing_brackets
= closing_brackets2
;
2382 const string
& tmp_id2
= module
->get_temporary_id();
2383 const char *tmp_id2_str
= tmp_id2
.c_str();
2384 expr
->expr
= mputprintf(expr
->expr
,
2385 "const %s%s& %s = (const %s%s&) %s;\n",
2386 next_t
->get_genname_value(module
).c_str(),
2387 is_template
?"_template":"", tmp_id2_str
,
2388 next_t
->get_genname_value(module
).c_str(),
2389 is_template
?"_template":"", tmp_id_str
);
2391 expr
->expr
= mputprintf(expr
->expr
,
2392 "%s = %s.is_bound();\n", global_id
.c_str(),
2394 Free(tmp_generalid_str
);
2395 tmp_generalid_str
= mcopystr(tmp_id2_str
);
2398 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2399 expstring_t closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2400 Free(closing_brackets
);
2401 closing_brackets
= closing_brackets2
;
2403 const string
& tmp_id
= module
->get_temporary_id();
2404 const char *tmp_id_str
= tmp_id
.c_str();
2405 expr
->expr
= mputprintf(expr
->expr
,
2406 "const %s%s& %s = %s.%s();\n",
2407 next_t
->get_genname_value(module
).c_str(),
2408 is_template
?"_template":"", tmp_id_str
, tmp_generalid_str
,
2409 id
.get_name().c_str());
2411 expr
->expr
= mputprintf(expr
->expr
,
2412 "%s = %s.%s();\n", global_id
.c_str(),
2413 tmp_id_str
, isbound
||(i
!=(nof_refs
-1)) ? "is_bound" : "is_present");
2414 Free(tmp_generalid_str
);
2415 tmp_generalid_str
= mcopystr(tmp_id_str
);
2420 case Ttcn::FieldOrArrayRef::ARRAY_REF
: {
2421 Type
*embedded_type
= 0;
2422 bool is_string
= true;
2423 bool is_string_element
= false;
2424 switch (t
->typetype
) {
2427 embedded_type
= t
->u
.seof
.ofType
;
2431 embedded_type
= t
->u
.array
.element_type
;
2441 case T_NUMERICSTRING
:
2442 case T_PRINTABLESTRING
:
2443 case T_TELETEXSTRING
:
2444 case T_VIDEOTEXSTRING
:
2446 case T_GRAPHICSTRING
:
2447 case T_VISIBLESTRING
:
2448 case T_GENERALSTRING
:
2449 case T_UNIVERSALSTRING
:
2452 case T_GENERALIZEDTIME
:
2453 case T_OBJECTDESCRIPTOR
:
2454 if (subrefs
->refers_to_string_element()) {
2455 FATAL_ERROR("Type::generate_code_isbound()");
2457 subrefs
->set_string_element_ref();
2458 // string elements have the same type as the string itself
2460 is_string_element
= true;
2464 FATAL_ERROR("Type::generate_code_isbound()");
2467 next_t
= embedded_type
;
2469 // check the index value
2470 Value
*index_value
= ref
->get_val();
2471 Value
*v_last
= index_value
->get_value_refd_last();
2473 const string
& tmp_index_id
= module
->get_temporary_id();
2474 const char *tmp_index_id_str
= tmp_index_id
.c_str();
2475 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2477 expstring_t closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2478 Free(closing_brackets
);
2479 closing_brackets
= closing_brackets2
;
2481 expr
->expr
= mputprintf(expr
->expr
, "const int %s = ", tmp_index_id_str
);
2482 v_last
->generate_code_expr_mandatory(expr
);
2483 expr
->expr
= mputstr(expr
->expr
, ";\n");
2484 expr
->expr
= mputprintf(expr
->expr
, "%s = (%s >= 0) && (%s.%s > %s);\n",
2485 global_id
.c_str(), tmp_index_id_str
, tmp_generalid_str
,
2486 is_string
? "lengthof()": ( is_template
? "n_elem()" : "size_of()" ),
2488 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2490 closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2491 Free(closing_brackets
);
2492 closing_brackets
= closing_brackets2
;
2494 const string
& tmp_id
= module
->get_temporary_id();
2495 const char *tmp_id_str
= tmp_id
.c_str();
2497 if (is_string_element
) {
2498 expr
->expr
= mputprintf(expr
->expr
,
2499 "%s = %s[%s].%s();\n", global_id
.c_str(),
2500 tmp_generalid_str
, tmp_index_id_str
,
2501 isbound
||(i
!=(nof_refs
-1)) ? "is_bound" : "is_present");
2504 expr
->expr
= mputprintf(expr
->expr
,
2505 "const %s& %s = %s[%s];\n",
2506 next_t
->get_genname_template(module
).c_str(),
2507 tmp_id_str
, tmp_generalid_str
,
2510 expr
->expr
= mputprintf(expr
->expr
,
2511 "const %s%s& %s = %s[%s];\n",
2512 next_t
->get_genname_value(module
).c_str(),
2513 is_template
?"_template":"", tmp_id_str
, tmp_generalid_str
,
2517 expr
->expr
= mputprintf(expr
->expr
,
2518 "%s = %s.%s();\n", global_id
.c_str(), tmp_id_str
,
2519 isbound
||(i
!=(nof_refs
-1)) ? "is_bound" : "is_present");
2522 Free(tmp_generalid_str
);
2523 tmp_generalid_str
= mcopystr(tmp_id_str
);
2525 // change t to the embedded type
2529 FATAL_ERROR("Type::generate_code_isbound(): invalid reference type");
2533 Free(tmp_generalid_str
);
2534 expr
->expr
= mputstr(expr
->expr
, closing_brackets
);
2535 Free(closing_brackets
);
2538 string
Type::get_optimize_attribute()
2542 vector
<SingleWithAttrib
> const &real_attribs
2543 = w_attrib_path
->get_real_attrib();
2544 for (size_t i
= 0; i
< real_attribs
.size(); i
++) {
2545 SingleWithAttrib
* temp_single
= real_attribs
[i
];
2546 if (temp_single
->get_attribKeyword()
2547 == SingleWithAttrib::AT_EXTENSION
2548 && (!temp_single
->get_attribQualifiers()
2549 || (temp_single
->get_attribQualifiers()
2550 ->get_nof_qualifiers() == 0)))
2552 const string
& spec
= temp_single
->get_attribSpec().get_spec();
2553 // TODO: use a real parser to allow whitespaces, etc.
2554 if (spec
.find("optimize:")==0 && spec
.size()>9)
2556 string spec_optimize_for_what
= spec
.substr(9);
2557 return spec_optimize_for_what
;
2565 string
Type::get_sourcefile_attribute()
2569 vector
<SingleWithAttrib
> const &real_attribs
2570 = w_attrib_path
->get_real_attrib();
2572 for (size_t i
= 0; i
< real_attribs
.size(); i
++) {
2573 SingleWithAttrib
* temp_single
= real_attribs
[i
];
2574 if (temp_single
->get_attribKeyword()
2575 == SingleWithAttrib::AT_EXTENSION
2576 && (!temp_single
->get_attribQualifiers()
2577 || (temp_single
->get_attribQualifiers()
2578 ->get_nof_qualifiers() == 0)))
2580 const string
& spec
= temp_single
->get_attribSpec().get_spec();
2581 if (spec
.find("sourcefile:")==0 && spec
.size()>11)
2583 string spec_filename
= spec
.substr(11);
2584 // TODO: check if string can be a valid filename
2585 return spec_filename
;
2593 bool Type::has_done_attribute()
2597 vector
<SingleWithAttrib
> const &real_attribs
2598 = w_attrib_path
->get_real_attrib();
2600 for (size_t i
= 0; i
< real_attribs
.size(); i
++) {
2601 SingleWithAttrib
* temp_single
= real_attribs
[i
];
2602 if (temp_single
->get_attribKeyword()
2603 == SingleWithAttrib::AT_EXTENSION
2604 && (!temp_single
->get_attribQualifiers()
2605 || (temp_single
->get_attribQualifiers()
2606 ->get_nof_qualifiers() == 0))
2607 && temp_single
->get_attribSpec().get_spec() == "done")
2616 void Type::generate_code_object(const_def
*cdef
, Scope
*p_scope
,
2617 const string
& name
, const char *prefix
, bool is_template
)
2620 if (is_template
) type_name
= get_genname_template(p_scope
);
2621 else type_name
= get_genname_value(p_scope
);
2622 const char *name_str
= name
.c_str();
2623 const char *type_name_str
= type_name
.c_str();
2625 cdef
->decl
= mputprintf(cdef
->decl
, "extern const %s& %s;\n",
2626 type_name_str
, name_str
);
2627 cdef
->def
= mputprintf(cdef
->def
, "static %s %s%s;\n"
2628 "const %s& %s = %s%s;\n", type_name_str
, prefix
, name_str
,
2629 type_name_str
, name_str
, prefix
, name_str
);
2631 cdef
->decl
= mputprintf(cdef
->decl
, "extern %s %s;\n",
2632 type_name_str
, name_str
);
2633 cdef
->def
= mputprintf(cdef
->def
, "%s %s;\n",
2634 type_name_str
, name_str
);
2638 void Type::generate_code_object(const_def
*cdef
, GovernedSimple
*p_setting
)
2640 bool is_template
= false;
2641 switch (p_setting
->get_st()) {
2648 FATAL_ERROR("Type::generate_code_object()");
2650 if (p_setting
->get_err_descr()) {
2651 cdef
->def
= p_setting
->get_err_descr()->generate_code_str(cdef
->def
,
2652 p_setting
->get_genname_prefix() + p_setting
->get_genname_own());
2654 generate_code_object(cdef
, p_setting
->get_my_scope(),
2655 p_setting
->get_genname_own(), p_setting
->get_genname_prefix(),
2659 void Type::generate_json_schema(JSON_Tokenizer
& json
, bool embedded
, bool as_value
)
2661 // add a new property for the type if it has its own definition
2663 json
.put_next_token(JSON_TOKEN_NAME
, get_dispname().c_str());
2666 // create an object containing the type's schema
2667 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2669 // if this is a field of a record/set/union with an alias, the field's
2670 // original name must be stored ("originalName" property), it also needs to be
2671 // stored if this is a field of a union with the "as value" coding instruction
2672 if (ownertype
== OT_COMP_FIELD
) {
2673 CompField
* cf
= static_cast<CompField
*>(owner
);
2674 if (as_value
|| (cf
->get_type()->jsonattrib
!= NULL
2675 && cf
->get_type()->jsonattrib
->alias
!= NULL
)) {
2676 json
.put_next_token(JSON_TOKEN_NAME
, "originalName");
2677 char* field_str
= mprintf("\"%s\"", cf
->get_name().get_ttcnname().c_str());
2678 json
.put_next_token(JSON_TOKEN_STRING
, field_str
);
2682 // if the parent is a union with the "as value" coding instruction AND the field
2683 // has an alias, then the alias needs to be stored as well ("unusedAlias" property)
2684 if (as_value
&& cf
->get_type()->jsonattrib
!= NULL
2685 && cf
->get_type()->jsonattrib
->alias
!= NULL
) {
2686 json
.put_next_token(JSON_TOKEN_NAME
, "unusedAlias");
2687 char* alias_str
= mprintf("\"%s\"", cf
->get_type()->jsonattrib
->alias
);
2688 json
.put_next_token(JSON_TOKEN_STRING
, alias_str
);
2693 // get the type at the end of the reference chain
2694 Type
* last
= get_type_refd_last();
2696 // if the type has its own definition and it's embedded in another type, then
2697 // its schema already exists, only add a reference to it
2698 // exception: instances of ASN.1 parameterized types, always embed their schemas
2699 if (embedded
&& (!is_ref() || !get_type_refd()->pard_type_instance
) &&
2700 (last
->ownertype
== OT_TYPE_DEF
/* TTCN-3 type definition */
2701 || last
->ownertype
== OT_TYPE_ASS
/* ASN.1 type assignment */ )) {
2702 json
.put_next_token(JSON_TOKEN_NAME
, "$ref");
2703 char* ref_str
= mprintf("\"#/definitions/%s/%s\"",
2704 last
->my_scope
->get_scope_mod()->get_modid().get_ttcnname().c_str(),
2705 (is_ref() && last
->pard_type_instance
) ? get_type_refd()->get_dispname().c_str() : last
->get_dispname().c_str());
2706 json
.put_next_token(JSON_TOKEN_STRING
, ref_str
);
2709 // generate the schema for the referenced type
2710 switch (last
->typetype
) {
2712 // use the JSON boolean type
2713 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2714 json
.put_next_token(JSON_TOKEN_STRING
, "\"boolean\"");
2718 // use the JSON integer type
2719 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2720 json
.put_next_token(JSON_TOKEN_STRING
, "\"integer\"");
2723 // any of: JSON number or the special values as strings (in an enum)
2724 json
.put_next_token(JSON_TOKEN_NAME
, "anyOf");
2725 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2726 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2727 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2728 json
.put_next_token(JSON_TOKEN_STRING
, "\"number\"");
2729 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2730 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2731 json
.put_next_token(JSON_TOKEN_NAME
, "enum");
2732 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2733 json
.put_next_token(JSON_TOKEN_STRING
, "\"not_a_number\"");
2734 json
.put_next_token(JSON_TOKEN_STRING
, "\"infinity\"");
2735 json
.put_next_token(JSON_TOKEN_STRING
, "\"-infinity\"");
2736 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2737 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2738 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2745 // use the JSON string type and add a pattern to only allow bits or hex digits
2746 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2747 json
.put_next_token(JSON_TOKEN_STRING
, "\"string\"");
2748 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2749 json
.put_next_token(JSON_TOKEN_STRING
,
2750 (last
->typetype
== T_OSTR
|| last
->typetype
== T_ANY
) ? "\"octetstring\"" :
2751 ((last
->typetype
== T_HSTR
) ? "\"hexstring\"" : "\"bitstring\""));
2752 json
.put_next_token(JSON_TOKEN_NAME
, "pattern");
2753 json
.put_next_token(JSON_TOKEN_STRING
,
2754 (last
->typetype
== T_OSTR
|| last
->typetype
== T_ANY
) ? "\"^([0-9A-Fa-f][0-9A-Fa-f])*$\"" :
2755 ((last
->typetype
== T_HSTR
) ? "\"^[0-9A-Fa-f]*$\"" : "\"^[01]*$\""));
2758 case T_NUMERICSTRING
:
2759 case T_PRINTABLESTRING
:
2761 case T_VISIBLESTRING
:
2762 // use the JSON string type and add a "subType" property to distinguish it from
2763 // universal charstring types
2764 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2765 json
.put_next_token(JSON_TOKEN_STRING
, "\"string\"");
2766 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2767 json
.put_next_token(JSON_TOKEN_STRING
, "\"charstring\"");
2770 case T_GENERALSTRING
:
2771 case T_UNIVERSALSTRING
:
2774 case T_GRAPHICSTRING
:
2775 case T_TELETEXSTRING
:
2776 case T_VIDEOTEXSTRING
:
2777 // use the JSON string type and add a "subType" property to distinguish it from
2779 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2780 json
.put_next_token(JSON_TOKEN_STRING
, "\"string\"");
2781 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2782 json
.put_next_token(JSON_TOKEN_STRING
, "\"universal charstring\"");
2786 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2787 json
.put_next_token(JSON_TOKEN_STRING
, "\"string\"");
2788 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2789 json
.put_next_token(JSON_TOKEN_STRING
, "\"objid\"");
2790 json
.put_next_token(JSON_TOKEN_NAME
, "pattern");
2791 json
.put_next_token(JSON_TOKEN_STRING
, "\"^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$\"");
2794 // enumerate the possible values
2795 json
.put_next_token(JSON_TOKEN_NAME
, "enum");
2796 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2797 json
.put_next_token(JSON_TOKEN_STRING
, "\"none\"");
2798 json
.put_next_token(JSON_TOKEN_STRING
, "\"pass\"");
2799 json
.put_next_token(JSON_TOKEN_STRING
, "\"inconc\"");
2800 json
.put_next_token(JSON_TOKEN_STRING
, "\"fail\"");
2801 json
.put_next_token(JSON_TOKEN_STRING
, "\"error\"");
2802 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2806 // enumerate the possible values
2807 json
.put_next_token(JSON_TOKEN_NAME
, "enum");
2808 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2809 for (size_t i
= 0; i
< last
->u
.enums
.eis
->get_nof_eis(); ++i
) {
2810 char* enum_str
= mprintf("\"%s\"", last
->get_ei_byIndex(i
)->get_name().get_ttcnname().c_str());
2811 json
.put_next_token(JSON_TOKEN_STRING
, enum_str
);
2814 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2815 // list the numeric values for the enumerated items
2816 json
.put_next_token(JSON_TOKEN_NAME
, "numericValues");
2817 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2818 for (size_t i
= 0; i
< last
->u
.enums
.eis
->get_nof_eis(); ++i
) {
2819 char* num_val_str
= mprintf("%lli", last
->get_ei_byIndex(i
)->get_value()->get_val_Int()->get_val());
2820 json
.put_next_token(JSON_TOKEN_NUMBER
, num_val_str
);
2823 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2826 // use the JSON null value for the ASN.1 NULL type
2827 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2828 json
.put_next_token(JSON_TOKEN_STRING
, "\"null\"");
2833 last
->generate_json_schema_array(json
);
2839 last
->generate_json_schema_record(json
);
2845 last
->generate_json_schema_union(json
);
2848 FATAL_ERROR("Type::generate_json_schema");
2852 // insert default value (if any)
2853 if (jsonattrib
!= NULL
&& jsonattrib
->default_value
!= NULL
) {
2854 json
.put_next_token(JSON_TOKEN_NAME
, "default");
2855 switch (last
->typetype
) {
2857 json
.put_next_token((jsonattrib
->default_value
[0] == 't') ?
2858 JSON_TOKEN_LITERAL_TRUE
: JSON_TOKEN_LITERAL_FALSE
);
2862 if (jsonattrib
->default_value
[0] != 'n' && jsonattrib
->default_value
[0] != 'i'
2863 && jsonattrib
->default_value
[1] != 'i') {
2864 json
.put_next_token(JSON_TOKEN_NUMBER
, jsonattrib
->default_value
);
2867 // no break, insert the special float values as strings
2875 char* default_str
= mprintf("\"%s\"", jsonattrib
->default_value
);
2876 json
.put_next_token(JSON_TOKEN_STRING
, default_str
);
2880 FATAL_ERROR("Type::generate_json_schema");
2884 // end of type's schema
2885 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2888 void Type::generate_json_schema_array(JSON_Tokenizer
& json
)
2890 // use the JSON array type
2891 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2892 json
.put_next_token(JSON_TOKEN_STRING
, "\"array\"");
2894 if (typetype
!= T_ARRAY
) {
2895 // use the "subType" property to distinguish 'record of' from 'set of'
2896 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2897 json
.put_next_token(JSON_TOKEN_STRING
, (typetype
== T_SEQOF
) ?
2898 "\"record of\"" : "\"set of\"");
2900 // set the number of elements for arrays
2901 char* size_str
= mprintf("%lu", get_nof_comps());
2902 json
.put_next_token(JSON_TOKEN_NAME
, "minItems");
2903 json
.put_next_token(JSON_TOKEN_NUMBER
, size_str
);
2904 json
.put_next_token(JSON_TOKEN_NAME
, "maxItems");
2905 json
.put_next_token(JSON_TOKEN_NUMBER
, size_str
);
2909 // set the element type
2910 json
.put_next_token(JSON_TOKEN_NAME
, "items");
2912 // pass the tokenizer to the elements' type object to insert its schema
2913 get_ofType()->generate_json_schema(json
, true, false);
2916 void Type::generate_json_schema_record(JSON_Tokenizer
& json
)
2918 // use the JSON object type
2919 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2920 json
.put_next_token(JSON_TOKEN_STRING
, "\"object\"");
2922 // use the "subType" property to distinguish records from sets
2923 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2924 json
.put_next_token(JSON_TOKEN_STRING
, (typetype
== T_SEQ_T
|| typetype
== T_SEQ_A
) ?
2925 "\"record\"" : "\"set\"");
2928 json
.put_next_token(JSON_TOKEN_NAME
, "properties");
2929 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2930 size_t field_count
= get_nof_comps();
2931 bool has_non_optional
= false;
2932 for (size_t i
= 0; i
< field_count
; ++i
) {
2933 Type
* field
= get_comp_byIndex(i
)->get_type();
2935 // use the field's alias if it has one
2936 json
.put_next_token(JSON_TOKEN_NAME
,
2937 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
2938 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_ttcnname().c_str());
2940 // optional fields can also get the JSON null value
2941 if (get_comp_byIndex(i
)->get_is_optional()) {
2942 // special case: ASN NULL type, since it uses the JSON literal "null" as a value
2943 if (T_NULL
!= field
->get_type_refd_last()->typetype
) {
2944 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2945 json
.put_next_token(JSON_TOKEN_NAME
, "anyOf");
2946 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2947 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2948 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2949 json
.put_next_token(JSON_TOKEN_STRING
, "\"null\"");
2950 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2952 } else if (!has_non_optional
) {
2953 has_non_optional
= true;
2956 // pass the tokenizer to the field's type to insert its schema
2957 field
->generate_json_schema(json
, true, false);
2959 // for optional fields: specify the presence of the "omit as null" coding instruction
2960 // and close structures
2961 if (get_comp_byIndex(i
)->get_is_optional() &&
2962 T_NULL
!= field
->get_type_refd_last()->typetype
) {
2963 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2964 json
.put_next_token(JSON_TOKEN_NAME
, "omitAsNull");
2965 json
.put_next_token((field
->jsonattrib
!= NULL
&& field
->jsonattrib
->omit_as_null
) ?
2966 JSON_TOKEN_LITERAL_TRUE
: JSON_TOKEN_LITERAL_FALSE
);
2967 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2971 // end of properties
2972 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2974 // do not accept additional fields
2975 json
.put_next_token(JSON_TOKEN_NAME
, "additionalProperties");
2976 json
.put_next_token(JSON_TOKEN_LITERAL_FALSE
);
2978 // set the field order
2979 if (field_count
> 1) {
2980 json
.put_next_token(JSON_TOKEN_NAME
, "fieldOrder");
2981 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2982 for (size_t i
= 0; i
< field_count
; ++i
) {
2983 Type
* field
= get_comp_byIndex(i
)->get_type();
2984 // use the field's alias if it has one
2985 char* field_str
= mprintf("\"%s\"",
2986 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
2987 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_ttcnname().c_str());
2988 json
.put_next_token(JSON_TOKEN_STRING
, field_str
);
2991 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2994 // set the required (non-optional) fields
2995 if (has_non_optional
) {
2996 json
.put_next_token(JSON_TOKEN_NAME
, "required");
2997 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2998 for (size_t i
= 0; i
< field_count
; ++i
) {
2999 if (!get_comp_byIndex(i
)->get_is_optional()) {
3000 Type
* field
= get_comp_byIndex(i
)->get_type();
3001 // use the field's alias if it has one
3002 char* field_str
= mprintf("\"%s\"",
3003 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
3004 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_ttcnname().c_str());
3005 json
.put_next_token(JSON_TOKEN_STRING
, field_str
);
3009 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
3013 void Type::generate_json_schema_union(JSON_Tokenizer
& json
)
3015 // use an "anyOf" structure containing the union's alternatives
3016 json
.put_next_token(JSON_TOKEN_NAME
, "anyOf");
3017 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
3019 for (size_t i
= 0; i
< get_nof_comps(); ++i
) {
3020 Type
* field
= get_comp_byIndex(i
)->get_type();
3022 if (jsonattrib
!= NULL
&& jsonattrib
->as_value
) {
3023 // only add the alternative's schema
3024 field
->generate_json_schema(json
, true, true);
3026 // use a JSON object with one key-value pair for each alternative
3027 // the schema is the same as a record's with one field
3028 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
3030 json
.put_next_token(JSON_TOKEN_NAME
, "type");
3031 json
.put_next_token(JSON_TOKEN_STRING
, "\"object\"");
3033 json
.put_next_token(JSON_TOKEN_NAME
, "properties");
3034 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
3036 // use the alternative's alias if it has one
3037 json
.put_next_token(JSON_TOKEN_NAME
,
3038 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
3039 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_ttcnname().c_str());
3041 // let the alternative's type insert its schema
3042 field
->generate_json_schema(json
, true, false);
3044 // continue the schema for the record with one field
3045 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
3047 json
.put_next_token(JSON_TOKEN_NAME
, "additionalProperties");
3048 json
.put_next_token(JSON_TOKEN_LITERAL_FALSE
);
3050 // the one field is non-optional
3051 json
.put_next_token(JSON_TOKEN_NAME
, "required");
3052 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
3054 // use the alternative's alias here as well
3055 char* field_str
= mprintf("\"%s\"",
3056 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
3057 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_ttcnname().c_str());
3058 json
.put_next_token(JSON_TOKEN_STRING
, field_str
);
3061 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
3063 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
3067 // close the "anyOf" array
3068 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
3071 void Type::generate_json_schema_ref(JSON_Tokenizer
& json
)
3073 // start the object containing the reference
3074 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
3076 // insert the reference
3077 json
.put_next_token(JSON_TOKEN_NAME
, "$ref");
3078 char* ref_str
= mprintf("\"#/definitions/%s/%s\"",
3079 my_scope
->get_scope_mod()->get_modid().get_ttcnname().c_str(),
3080 get_dispname().c_str());
3081 json
.put_next_token(JSON_TOKEN_STRING
, ref_str
);
3084 // the object will be closed later, as it may contain other properties
3088 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3090 } // namespace Common