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
246 force_xer
= has_encoding(CT_XER
); // && (is_ref() || (xerattrib && !xerattrib->empty()));
250 } // switch(ownertype)
254 const string
& gennameown
= get_genname_own();
255 const char *gennameown_str
= gennameown
.c_str();
256 const string
& gennametypedescriptor
= get_genname_typedescriptor(my_scope
);
257 //printf("generate_code_typedescriptor(%s)\n", gennameown_str);
259 // FIXME: force_xer should be elminated. if a type needs a descriptor,
260 // it should say so via get_genname_typedescriptor()
262 /* genname{type,ber,raw,text,xer}descriptor == gennameown is true if
263 * the type needs its own {type,ber,raw,text,xer}descriptor
264 * and can't use the descriptor of one of the built-in types.
266 if (gennametypedescriptor
== gennameown
268 // the type has its own type descriptor
269 bool generate_ber
= has_encoding(CT_BER
) && enable_ber();
270 const string
& gennameberdescriptor
= get_genname_berdescriptor();
271 if (generate_ber
&& gennameberdescriptor
== gennameown
)
272 generate_code_berdescriptor(target
);
274 bool generate_raw
= has_encoding(CT_RAW
) && enable_raw();
275 const string
& gennamerawdescriptor
= get_genname_rawdescriptor();
276 if (generate_raw
&& gennamerawdescriptor
== gennameown
)
277 generate_code_rawdescriptor(target
);
279 bool generate_text
= has_encoding(CT_TEXT
) && enable_text();
280 const string
& gennametextdescriptor
= get_genname_textdescriptor();
281 if (generate_text
&& gennametextdescriptor
== gennameown
)
282 generate_code_textdescriptor(target
);
284 bool generate_xer
= has_encoding(CT_XER
) && enable_xer();
285 const string
& gennamexerdescriptor
= get_genname_xerdescriptor();
286 if (generate_xer
&& gennamexerdescriptor
== gennameown
)
287 generate_code_xerdescriptor(target
);
288 else target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
289 "// No XER for %s\n", gennamexerdescriptor
.c_str());
291 const string
& gennamejsondescriptor
= get_genname_jsondescriptor();
292 bool generate_json
= has_encoding(CT_JSON
) && enable_json() &&
293 gennamejsondescriptor
== gennameown
;
295 generate_code_jsondescriptor(target
);
298 // the type descriptor must be always exported.
299 // embedded (possibly unnamed) types can be referenced from other modules
300 // using field/array sub-references
301 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
302 "extern const TTCN_Typedescriptor_t %s_descr_;\n", gennameown_str
);
303 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
304 "const TTCN_Typedescriptor_t %s_descr_ = { \"%s\", ", gennameown_str
,
305 get_fullname().c_str());
308 target
->source
.global_vars
=mputprintf
309 (target
->source
.global_vars
,
310 "&%s_ber_, ", gennameberdescriptor
.c_str());
312 target
->source
.global_vars
=mputstr
313 (target
->source
.global_vars
, "NULL, ");
316 target
->source
.global_vars
=mputprintf
317 (target
->source
.global_vars
,
318 "&%s_raw_, ", gennamerawdescriptor
.c_str());
320 target
->source
.global_vars
=mputstr
321 (target
->source
.global_vars
, "NULL, ");
324 target
->source
.global_vars
=mputprintf
325 (target
->source
.global_vars
,
326 "&%s_text_, ", gennametextdescriptor
.c_str());
328 target
->source
.global_vars
=mputstr
329 (target
->source
.global_vars
, "NULL, ");
332 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
333 "&%s_xer_, ", gennamexerdescriptor
.c_str());
335 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
339 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
340 "&%s_json_, ", gennamejsondescriptor
.c_str());
342 switch(get_type_refd_last()->typetype
) {
354 case T_NUMERICSTRING
:
355 case T_PRINTABLESTRING
:
356 case T_TELETEXSTRING
:
357 case T_VIDEOTEXSTRING
:
359 case T_GRAPHICSTRING
:
360 case T_VISIBLESTRING
:
361 case T_GENERALSTRING
:
362 case T_UNIVERSALSTRING
:
365 // use predefined JSON descriptors instead of null pointers for basic types
366 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
367 "&%s_json_, ", gennamejsondescriptor
.c_str());
370 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
375 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
376 "TTCN_Typedescriptor_t::%s };\n"
380 , get_genname_typedescr_asnbasetype());
382 // the type uses the type descriptor of another type
384 // we need to generate an aliased type descriptor only if the type is
385 // directly accessible by the user
386 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
387 "extern const TTCN_Typedescriptor_t& %s_descr_;\n", gennameown_str
);
388 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
389 "const TTCN_Typedescriptor_t& %s_descr_ = %s_descr_;\n",
390 gennameown_str
, gennametypedescriptor
.c_str());
393 /* In general, we avoid generating a XER descriptor for
394 * "artificial" types. */
396 if (ownertype
==OT_REF_SPEC
) {
397 // A XER descriptor without a TTCN descriptor to own it
398 generate_code_xerdescriptor(target
);
402 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
403 "// %s_xer_ elided\n", gennameown_str
);
405 target
->source
.global_vars
= mputprintf( target
->source
.global_vars
,
406 "// %s_descr_ not needed, use %s_descr_\n",
407 gennameown_str
, gennametypedescriptor
.c_str());
409 } // if(needs_alias())
410 } // if (gennameown == gennametypedescriptor)
413 void Type::generate_code_berdescriptor(output_struct
*target
)
415 const char *gennameown_str
= get_genname_own().c_str();
416 char *str
= mprintf("static const ASN_Tag_t %s_tag_[] = { ",
418 Tags
*joinedtags
= build_tags_joined();
419 size_t tagarraysize
= joinedtags
->get_nof_tags();
420 for (size_t i
= 0; i
< tagarraysize
; i
++) {
421 if (i
> 0) str
= mputstr(str
, ", ");
422 Tag
*t_tag
= joinedtags
->get_tag_byIndex(i
);
423 str
= mputprintf(str
, "{ %s, %su }", t_tag
->get_tagclass_str(),
424 Int2string(t_tag
->get_tagvalue()).c_str());
427 str
= mputstr(str
, "};\n");
428 target
->source
.global_vars
= mputstr(target
->source
.global_vars
, str
);
430 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
431 "extern const ASN_BERdescriptor_t %s_ber_;\n", gennameown_str
);
432 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
433 "const ASN_BERdescriptor_t %s_ber_ = { %luu, %s_tag_ };\n",
434 gennameown_str
, (unsigned long)tagarraysize
, gennameown_str
);
437 static const char* whitespace_action
[3] = {"PRESERVE", "REPLACE", "COLLAPSE"};
439 extern void change_name(string
&name
, XerAttributes::NameChange change
);
440 // implemented in Type_chk.cc
442 void Type::generate_code_xerdescriptor(output_struct
* target
)
444 const char *gennameown_str
= get_genname_own().c_str();
445 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
446 "extern const XERdescriptor_t %s_xer_;\n", gennameown_str
);
451 string full_s
= ot
->get_fullname();
452 size_t dot_pos
= full_s
.rfind('.');
453 if (full_s
.size() == dot_pos
) dot_pos
= 0;
454 last_s
= full_s
.substr(dot_pos
+1); // FIXME: may be better to use replace(pos, n, s)
456 if ('&'==last_s
[0] // object class field ?
457 ||'<'==last_s
[0]) { // <oftype> and the like
459 ot
= ot
->get_type_refd();
460 /* Fetch the referenced type and use that. Do not use
461 * get_type_refd_last() here. In case of a record-of user-defined type:
462 * <ttcn>type integer MyInt; type record of MyInt MyRecof;</ttcn>
463 * we want "MyInt" and not "integer" */
466 else { // probably a built-in type, punt with the C++ class name
467 last_s
= ot
->get_genname_value(0);
474 // Name for basic XER which ignores all the EXER fanciness
475 string
bxer_name(last_s
);
478 //fprintf(stderr, "%2d gno='%s'\tfn='%s'\n", typetype, gennameown_str, last_s.c_str());
479 int atrib
=0, any_atr
=0, any_elem
=0, base64
=0, decimal
=0, embed
=0, list
=0,
480 text
=0, untagged
=0, use_nil
=0, use_number
=0, use_order
=0, use_qname
=0,
481 use_type_attr
=0, ws
=0, has_1untag
=0, form_qualified
=0, any_from
=0,
482 any_except
=0, nof_ns_uris
=0;
483 const char* dfe_str
= 0;
486 change_name(last_s
, xerattrib
->name_
);
488 if (xerattrib
->namespace_
.uri
&& xerattrib
->namespace_
.prefix
) {
489 ns_index
= my_scope
->get_scope_mod()->get_ns_index(
490 xerattrib
->namespace_
.prefix
);
491 // This is known to have succeeded
494 any_atr
= has_aa(xerattrib
);
495 any_elem
= has_ae(xerattrib
);
496 atrib
= xerattrib
->attribute_
;
497 base64
= xerattrib
->base64_
;
498 decimal
= xerattrib
->decimal_
;
499 embed
= xerattrib
->embedValues_
;
500 form_qualified
= (xerattrib
->form_
& XerAttributes::QUALIFIED
)
501 || (xerattrib
->element_
); // a global element is always qualified
502 list
= xerattrib
->list_
;
503 untagged
= xerattrib
->untagged_
;
504 ws
= xerattrib
->whitespace_
;
505 // only set TEXT if it has no TextToBeUsed (plain "text" for a bool)
506 text
= xerattrib
->num_text_
&& xerattrib
->text_
->prefix
== 0;
507 use_nil
= xerattrib
->useNil_
;
508 use_number
= xerattrib
->useNumber_
;
509 use_order
= xerattrib
->useOrder_
;
510 use_qname
= xerattrib
->useQName_
;
511 // In ASN.1, the use of a type identification attribute is optional
512 // (encoder's choice) for USE-UNION. However, TTCN-3 removes this choice:
513 // it is mandatory to use it when possible (valid choice for ASN.1 too).
514 use_type_attr
= xerattrib
->useType_
|| xerattrib
->useUnion_
;
516 if (xerattrib
->defaultValue_
) {
517 Type
*t
= xerattrib
->defaultValue_
->get_my_governor();
518 dfe_str
= xerattrib
->defaultValue_
->get_genname_own().c_str();
520 Code::init_cdef(&cdef
);
521 t
->generate_code_object(&cdef
, xerattrib
->defaultValue_
);
522 cdef
.init
= xerattrib
->defaultValue_
->generate_code_init
523 (cdef
.init
, xerattrib
->defaultValue_
->get_lhs_name().c_str());
524 Code::merge_cdef(target
, &cdef
);
525 Code::free_cdef(&cdef
);
529 // data needed for "anyElement from ..." and "anyElement except ..." encoding instructions
530 any_from
= xerattrib
->anyElement_
.type_
== NamespaceRestriction::FROM
;
531 any_except
= xerattrib
->anyElement_
.type_
== NamespaceRestriction::EXCEPT
;
532 nof_ns_uris
= xerattrib
->anyElement_
.nElements_
;
533 ns_uris
= xerattrib
->anyElement_
.uris_
;
536 // data needed for "anyAttributes from ..." and "anyAttributes except ..." encoding instructions
537 any_from
= xerattrib
->anyAttributes_
.type_
== NamespaceRestriction::FROM
;
538 any_except
= xerattrib
->anyAttributes_
.type_
== NamespaceRestriction::EXCEPT
;
539 nof_ns_uris
= xerattrib
->anyAttributes_
.nElements_
;
540 ns_uris
= xerattrib
->anyAttributes_
.uris_
;
543 else if (ownertype
== OT_COMP_FIELD
544 && parent_type
&& parent_type
->xerattrib
) {
545 //no xerattrib, this must be an element; apply element default
546 form_qualified
= (parent_type
->xerattrib
->form_
547 & XerAttributes::ELEMENT_DEFAULT_QUALIFIED
);
550 Type
*last
= get_type_refd_last();
551 has_1untag
= last
->is_secho() && last
->u
.secho
.has_single_charenc
; // does not come from xerattrib
553 /* If this is a string type whose grandparent is a record
554 * (containing a record-of (this)string) which has EMBED-VALUES,
555 * then reuse this string's any_element field in the XER descriptor
556 * to signal this (ANY-ELEMENT causes the tag to be omitted,
557 * which is what we want in EMBED-VALUES) */
558 if (parent_type
&& parent_type
->parent_type
) switch (last
->typetype
) {
560 case T_USTR
: // the TTCN equivalent of UTF8String
561 if ( T_SEQOF
== parent_type
->typetype
562 && (T_SEQ_T
== parent_type
->parent_type
->typetype
563 ||T_SEQ_A
== parent_type
->parent_type
->typetype
)
564 && parent_type
->parent_type
->xerattrib
) {
565 embed
|= (parent_type
->parent_type
->xerattrib
->embedValues_
);
571 size_t last_len
= 2 + last_s
.size(); // 2 for > \n
572 size_t bxer_len
= 2 + bxer_name
.size(); // 2 for > \n
574 // Generate a separate variable for the namespace URIs, if there are any
575 char* ns_uris_var
= 0;
576 if (ns_uris
&& nof_ns_uris
) {
577 ns_uris_var
= mputprintf(ns_uris_var
, "%s_ns_uris_", gennameown_str
);
578 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
579 "const char* %s[] = {", ns_uris_var
);
580 for (int idx
= 0; idx
< nof_ns_uris
; ++idx
) {
581 // The unqualified namespace is sometimes stored as an empty string and
582 // sometimes as a null pointer -> unify it, always store it as an empty string
583 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
584 "%s\"%s\"", (idx
!= 0) ? ", " : "", ns_uris
[idx
] ? ns_uris
[idx
] : "");
586 target
->source
.global_vars
= mputstrn(target
->source
.global_vars
, "};\n", 3);
589 // Generate the XER descriptor itself
590 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
591 "const XERdescriptor_t %s_xer_ = { {\"%s>\\n\", \"%s>\\n\"},"
592 " {%lu, %lu}, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s, WHITESPACE_%s, %c%s, "
593 "&%s, %ld, %u, %s };\n",
595 bxer_name
.c_str(), last_s
.c_str(), // names
596 (unsigned long)bxer_len
, (unsigned long)last_len
, // lengths
597 (any_atr
? "ANY_ATTRIBUTES" : "0"),
598 (any_elem
? " |ANY_ELEMENT" : ""),
599 (atrib
? " |XER_ATTRIBUTE" : ""),
600 (base64
? " |BASE_64" : ""),
601 (decimal
? " |XER_DECIMAL" : ""),
602 (embed
? " |EMBED_VALUES" : ""),
603 (list
? " |XER_LIST" : ""),
604 (text
? " |XER_TEXT" : ""),
605 (untagged
? " |UNTAGGED" : ""),
606 (use_nil
? " |USE_NIL" : ""),
607 (use_number
? " |USE_NUMBER" : ""),
608 (use_order
? " |USE_ORDER" : ""),
609 (use_qname
? " |USE_QNAME" : ""),
610 (use_type_attr
? " |USE_TYPE_ATTR" : ""),
611 (has_1untag
? " |HAS_1UNTAGGED" : ""),
612 (form_qualified
? "" : " |FORM_UNQUALIFIED"),
613 (any_from
? " |ANY_FROM" : ""),
614 (any_except
? " |ANY_EXCEPT" : ""),
615 whitespace_action
[ws
],
616 (dfe_str
? '&' : ' '), (dfe_str
? dfe_str
: "NULL"),
620 (ns_uris_var
? ns_uris_var
: "NULL")
626 void Type::generate_code_rawdescriptor(output_struct
*target
)
628 const char *gennameown_str
= get_genname_own().c_str();
629 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
630 "extern const TTCN_RAWdescriptor_t %s_raw_;\n", gennameown_str
);
631 char *str
= mprintf("const TTCN_RAWdescriptor_t %s_raw_ = {",
633 str
= mputprintf(str
, "%d,", rawattrib
->fieldlength
);
634 if (rawattrib
->comp
== XDEFCOMPL
) str
= mputstr(str
, "SG_2COMPL,");
635 else if (rawattrib
->comp
== XDEFSIGNBIT
) str
= mputstr(str
, "SG_SG_BIT,");
636 else str
= mputstr(str
, "SG_NO,");
637 if (rawattrib
->byteorder
== XDEFLAST
) str
= mputstr(str
, "ORDER_MSB,");
638 else str
= mputstr(str
, "ORDER_LSB,");
639 if (rawattrib
->align
== XDEFLEFT
) str
= mputstr(str
, "ORDER_MSB,");
640 else str
= mputstr(str
, "ORDER_LSB,");
641 if (rawattrib
->bitorderinfield
== XDEFMSB
)
642 str
= mputstr(str
, "ORDER_MSB,");
643 else str
= mputstr(str
, "ORDER_LSB,");
644 if (rawattrib
->bitorderinoctet
== XDEFMSB
)
645 str
= mputstr(str
, "ORDER_MSB,");
646 else str
= mputstr(str
, "ORDER_LSB,");
647 if (rawattrib
->extension_bit
== XDEFYES
)
648 str
= mputstr(str
, "EXT_BIT_YES,");
649 else if (rawattrib
->extension_bit
== XDEFREVERSE
)
650 str
= mputstr(str
, "EXT_BIT_REVERSE,");
651 else str
= mputstr(str
, "EXT_BIT_NO,");
652 if (rawattrib
->hexorder
== XDEFHIGH
) str
= mputstr(str
, "ORDER_MSB,");
653 else str
= mputstr(str
, "ORDER_LSB,");
654 if (rawattrib
->fieldorder
== XDEFMSB
) str
= mputstr(str
, "ORDER_MSB,");
655 else str
= mputstr(str
, "ORDER_LSB,");
656 if (rawattrib
->topleveleind
) {
657 if (rawattrib
->toplevel
.bitorder
==XDEFLSB
)
658 str
= mputstr(str
, "TOP_BIT_LEFT,");
659 else str
= mputstr(str
, "TOP_BIT_RIGHT,");
660 } else str
= mputstr(str
, "TOP_BIT_INHERITED,");
661 str
= mputprintf(str
, "%d,", rawattrib
->padding
);
662 str
= mputprintf(str
, "%d,", rawattrib
->prepadding
);
663 str
= mputprintf(str
, "%d,", rawattrib
->ptroffset
);
664 str
= mputprintf(str
, "%d,", rawattrib
->unit
);
665 str
= mputprintf(str
, "%d,", rawattrib
->padding_pattern_length
);
666 if (rawattrib
->padding_pattern_length
> 0)
667 str
= mputprintf(str
, "%s,", my_scope
->get_scope_mod_gen()
668 ->add_padding_pattern(string(rawattrib
->padding_pattern
)).c_str());
669 else str
= mputstr(str
, "NULL,");
670 str
= mputprintf(str
, "%d};\n", rawattrib
->length_restrition
);
671 target
->source
.global_vars
= mputstr(target
->source
.global_vars
, str
);
675 void Type::generate_code_textdescriptor(output_struct
*target
)
677 const char *gennameown_str
= get_genname_own().c_str();
678 char *union_member_name
=NULL
;
679 Common::Module
*mymod
=my_scope
->get_scope_mod();
680 Type
*t
= get_type_refd_last();
681 switch (t
->typetype
) {
683 if (textattrib
->true_params
|| textattrib
->false_params
) {
684 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
685 "static const TTCN_TEXTdescriptor_bool %s_bool_ = {", gennameown_str
);
686 if (textattrib
->true_params
&&
687 textattrib
->true_params
->encode_token
) {
688 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
689 "&%s,", mymod
->add_charstring_literal(
690 string(textattrib
->true_params
->encode_token
)).c_str());
692 target
->source
.global_vars
=mputstr(target
->source
.global_vars
,
695 if (textattrib
->true_params
&&
696 textattrib
->true_params
->decode_token
) {
697 char *pstr
= make_posix_str_code(
698 textattrib
->true_params
->decode_token
,
699 textattrib
->true_params
->case_sensitive
);
700 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
701 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
703 } else if (textattrib
->true_params
&&
704 !textattrib
->true_params
->case_sensitive
) {
705 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
706 "&%s,", mymod
->add_matching_literal(
707 string("N^(true).*$")).c_str());
709 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
712 if (textattrib
->false_params
&&
713 textattrib
->false_params
->encode_token
) {
714 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
715 "&%s,",mymod
->add_charstring_literal(
716 string(textattrib
->false_params
->encode_token
)).c_str());
718 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
721 if (textattrib
->false_params
&&
722 textattrib
->false_params
->decode_token
) {
723 char *pstr
= make_posix_str_code(
724 textattrib
->false_params
->decode_token
,
725 textattrib
->false_params
->case_sensitive
);
726 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
727 "&%s};\n", mymod
->add_matching_literal(string(pstr
)).c_str());
729 } else if (textattrib
->false_params
&&
730 !textattrib
->false_params
->case_sensitive
) {
731 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
732 "&%s};\n", mymod
->add_matching_literal(
733 string("N^(false).*$")).c_str());
735 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
738 union_member_name
= mprintf("(TTCN_TEXTdescriptor_param_values*)"
739 "&%s_bool_", gennameown_str
);
743 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
744 "static const TTCN_TEXTdescriptor_enum %s_enum_[] = { ",
746 for (size_t i
= 0; i
< t
->u
.enums
.eis
->get_nof_eis(); i
++) {
747 if (i
> 0) target
->source
.global_vars
=
748 mputstr(target
->source
.global_vars
, ", ");
749 target
->source
.global_vars
=
750 mputstr(target
->source
.global_vars
, "{ ");
751 if (textattrib
->field_params
&& textattrib
->field_params
[i
] &&
752 textattrib
->field_params
[i
]->value
.encode_token
) {
753 // the encode token is present
754 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
755 "&%s, ", mymod
->add_charstring_literal(
756 string(textattrib
->field_params
[i
]->value
.encode_token
)).c_str());
758 // the encode token is not present: generate a NULL pointer and the
759 // RTE will substitute the enumerated value
760 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
763 // a pattern must be always present for decoding
764 const char *decode_token
;
766 if (textattrib
->field_params
&& textattrib
->field_params
[i
]) {
767 if (textattrib
->field_params
[i
]->value
.decode_token
) {
768 // the decode token is present
769 decode_token
= textattrib
->field_params
[i
]->value
.decode_token
;
771 // there is an attribute for the enumerated value,
772 // but the decode token is omitted
773 // use the value as decode token
774 decode_token
= t
->u
.enums
.eis
->get_ei_byIndex(i
)->get_name()
775 .get_dispname().c_str();
777 // take the case sensitivity from the attribute
778 case_sensitive
= textattrib
->field_params
[i
]->value
.case_sensitive
;
780 // there is no attribute for the enumerated value
781 // use the value as decode token
782 decode_token
= t
->u
.enums
.eis
->get_ei_byIndex(i
)->get_name()
783 .get_dispname().c_str();
784 // it is always case sensitive
785 case_sensitive
= true;
787 char *pstr
= make_posix_str_code(decode_token
, case_sensitive
);
788 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
789 " &%s }", mymod
->add_matching_literal(string(pstr
)).c_str());
792 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
794 union_member_name
= mprintf(
795 "(TTCN_TEXTdescriptor_param_values*)%s_enum_", gennameown_str
);
799 if(textattrib
->coding_params
.leading_zero
||
800 textattrib
->coding_params
.min_length
!=-1 ||
801 textattrib
->coding_params
.max_length
!=-1 ||
802 textattrib
->coding_params
.convert
!=0 ||
803 textattrib
->coding_params
.just
!=1 ||
804 textattrib
->decoding_params
.leading_zero
||
805 textattrib
->decoding_params
.min_length
!=-1 ||
806 textattrib
->decoding_params
.max_length
!=-1 ||
807 textattrib
->decoding_params
.convert
!=0 ||
808 textattrib
->decoding_params
.just
!=1 ){
809 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
810 "static const TTCN_TEXTdescriptor_param_values %s_par_ = {",
812 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
813 "{%s,%s,%i,%i,%i,%i},{%s,%s,%i,%i,%i,%i}};\n"
814 ,textattrib
->coding_params
.leading_zero
?"true":"false"
815 ,textattrib
->coding_params
.repeatable
?"true":"false"
816 ,textattrib
->coding_params
.min_length
817 ,textattrib
->coding_params
.max_length
818 ,textattrib
->coding_params
.convert
819 ,textattrib
->coding_params
.just
820 ,textattrib
->decoding_params
.leading_zero
?"true":"false"
821 ,textattrib
->decoding_params
.repeatable
?"true":"false"
822 ,textattrib
->decoding_params
.min_length
823 ,textattrib
->decoding_params
.max_length
824 ,textattrib
->decoding_params
.convert
825 ,textattrib
->decoding_params
.just
);
827 union_member_name
=mprintf("&%s_par_", gennameown_str
);
832 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
833 "static const TTCN_TEXTdescriptor_param_values %s_par_ = {",
835 target
->source
.global_vars
=mputprintf(target
->source
.global_vars
,
836 "{%s,%s,%i,%i,%i,%i},{%s,%s,%i,%i,%i,%i}};\n"
837 ,textattrib
->coding_params
.leading_zero
?"true":"false"
838 ,textattrib
->coding_params
.repeatable
?"true":"false"
839 ,textattrib
->coding_params
.min_length
840 ,textattrib
->coding_params
.max_length
841 ,textattrib
->coding_params
.convert
842 ,textattrib
->coding_params
.just
843 ,textattrib
->decoding_params
.leading_zero
?"true":"false"
844 ,textattrib
->decoding_params
.repeatable
?"true":"false"
845 ,textattrib
->decoding_params
.min_length
846 ,textattrib
->decoding_params
.max_length
847 ,textattrib
->decoding_params
.convert
848 ,textattrib
->decoding_params
.just
);
850 union_member_name
=mprintf("&%s_par_", gennameown_str
);
856 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
857 "extern const TTCN_TEXTdescriptor_t %s_text_;\n", gennameown_str
);
858 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
859 "const TTCN_TEXTdescriptor_t %s_text_ = {", gennameown_str
);
861 if (textattrib
->begin_val
&& textattrib
->begin_val
->encode_token
) {
862 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
863 "&%s,", mymod
->add_charstring_literal(
864 string(textattrib
->begin_val
->encode_token
)).c_str());
866 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
869 if(textattrib
->begin_val
&& textattrib
->begin_val
->decode_token
){
870 char *pstr
= make_posix_str_code(
871 textattrib
->begin_val
->decode_token
,
872 textattrib
->begin_val
->case_sensitive
);
873 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
874 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
877 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
880 if (textattrib
->end_val
&& textattrib
->end_val
->encode_token
) {
881 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
882 "&%s,",mymod
->add_charstring_literal(
883 string(textattrib
->end_val
->encode_token
)).c_str());
885 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
888 if (textattrib
->end_val
&& textattrib
->end_val
->decode_token
) {
889 char *pstr
= make_posix_str_code(
890 textattrib
->end_val
->decode_token
,
891 textattrib
->end_val
->case_sensitive
);
892 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
893 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
896 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
900 if (textattrib
->separator_val
&&
901 textattrib
->separator_val
->encode_token
) {
902 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
903 "&%s,", mymod
->add_charstring_literal(
904 string(textattrib
->separator_val
->encode_token
)).c_str());
906 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
909 if(textattrib
->separator_val
&&
910 textattrib
->separator_val
->decode_token
) {
911 char *pstr
= make_posix_str_code(
912 textattrib
->separator_val
->decode_token
,
913 textattrib
->separator_val
->case_sensitive
);
914 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
915 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
918 target
->source
.global_vars
=mputstr(target
->source
.global_vars
,
922 if (textattrib
->decode_token
) {
923 char *pstr
= make_posix_str_code(textattrib
->decode_token
,
924 textattrib
->case_sensitive
);
925 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
926 "&%s,", mymod
->add_matching_literal(string(pstr
)).c_str());
929 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
933 if (union_member_name
) {
934 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
935 "{%s}};\n", union_member_name
);
936 Free(union_member_name
);
938 target
->source
.global_vars
= mputstr(target
->source
.global_vars
,
943 void Type::generate_code_jsondescriptor(output_struct
*target
)
945 target
->header
.global_vars
= mputprintf(target
->header
.global_vars
,
946 "extern const TTCN_JSONdescriptor_t %s_json_;\n", get_genname_own().c_str());
948 if (NULL
== jsonattrib
) {
949 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
950 "const TTCN_JSONdescriptor_t %s_json_ = { false, NULL, false, NULL };\n"
951 , get_genname_own().c_str());
953 char* alias
= jsonattrib
->alias
? mputprintf(NULL
, "\"%s\"", jsonattrib
->alias
) : NULL
;
954 char* def_val
= jsonattrib
->default_value
?
955 mputprintf(NULL
, "\"%s\"", jsonattrib
->default_value
) : NULL
;
956 target
->source
.global_vars
= mputprintf(target
->source
.global_vars
,
957 "const TTCN_JSONdescriptor_t %s_json_ = { %s, %s, %s, %s };\n"
958 , get_genname_own().c_str()
959 , jsonattrib
->omit_as_null
? "true" : "false"
960 , alias
? alias
: "NULL"
961 , jsonattrib
->as_value
? "true" : "false"
962 , def_val
? def_val
: "NULL");
969 void Type::generate_code_alias(output_struct
*target
)
971 if (!needs_alias()) return;
973 const string
& t_genname
= get_genname_value(my_scope
);
974 const char *refd_name
= t_genname
.c_str();
975 const char *own_name
= get_genname_own().c_str();
977 Type
*t_last
= get_type_refd_last();
978 switch (t_last
->typetype
) {
979 case T_PORT
: // only value class exists
980 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
981 "typedef %s %s;\n", refd_name
, own_name
);
983 case T_SIGNATURE
: // special classes (7 pcs.) exist
984 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
985 "typedef %s_call %s_call;\n"
986 "typedef %s_call_redirect %s_call_redirect;\n",
987 refd_name
, own_name
, refd_name
, own_name
);
988 if (!t_last
->is_nonblocking_signature()) {
989 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
990 "typedef %s_reply %s_reply;\n"
991 "typedef %s_reply_redirect %s_reply_redirect;\n",
992 refd_name
, own_name
, refd_name
, own_name
);
994 if (t_last
->get_signature_exceptions()) {
995 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
996 "typedef %s_exception %s_exception;\n"
997 "typedef %s_exception_template %s_exception_template;\n",
998 refd_name
, own_name
, refd_name
, own_name
);
1000 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1001 "typedef %s_template %s_template;\n",
1002 refd_name
, own_name
);
1004 default: // value and template classes exist
1005 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1007 "// written by %s in " __FILE__
" at %d\n"
1010 "typedef %s_template %s_template;\n",
1012 __FUNCTION__
, __LINE__
,
1014 refd_name
, own_name
, refd_name
, own_name
);
1019 void Type::generate_code_Enum(output_struct
*target
)
1023 memset(&e_def
, 0, sizeof(e_def
));
1024 e_def
.name
= get_genname_own().c_str();
1025 e_def
.dispname
= get_fullname().c_str();
1026 e_def
.isASN1
= is_asn1();
1027 e_def
.nElements
= u
.enums
.eis
->get_nof_eis();
1028 e_def
.elements
= (enum_field
*)
1029 Malloc(e_def
.nElements
*sizeof(*e_def
.elements
));
1030 e_def
.firstUnused
= u
.enums
.first_unused
;
1031 e_def
.secondUnused
= u
.enums
.second_unused
;
1032 e_def
.hasText
= textattrib
!=NULL
;
1033 e_def
.hasRaw
= rawattrib
!=NULL
;
1034 e_def
.hasXer
= has_encoding(CT_XER
);
1035 e_def
.hasJson
= has_encoding(CT_JSON
);
1037 e_def
.xerUseNumber
= xerattrib
->useNumber_
;
1039 for (size_t i
= 0; i
< e_def
.nElements
; i
++) {
1040 EnumItem
*ei
= u
.enums
.eis
->get_ei_byIndex(i
);
1041 e_def
.elements
[i
].name
= ei
->get_name().get_name().c_str();
1042 e_def
.elements
[i
].dispname
= ei
->get_name().get_ttcnname().c_str();
1043 if (ei
->get_text().empty()) e_def
.elements
[i
].text
= 0;
1045 e_def
.xerText
= TRUE
;
1046 e_def
.elements
[i
].text
= ei
->get_text().c_str();
1048 e_def
.elements
[i
].value
= ei
->get_value()->get_val_Int()->get_val();
1051 defEnumClass(&e_def
, target
);
1052 defEnumTemplate(&e_def
, target
);
1054 Free(e_def
.elements
);
1057 void Type::generate_code_Choice(output_struct
*target
)
1061 memset(&sdef
, 0, sizeof(sdef
));
1062 sdef
.name
= get_genname_own().c_str();
1063 sdef
.dispname
=get_fullname().c_str();
1064 if (T_ANYTYPE
==typetype
) {
1065 if (0 == get_nof_comps()) {
1066 //return; // don't generate code for empty anytype
1067 // XXX what to do with empty anytype ?
1068 // Easy: make sure it doesn't happen by filling it from the AST!
1070 sdef
.kind
= ANYTYPE
;
1072 else sdef
.kind
= UNION
;
1073 sdef
.isASN1
= is_asn1();
1074 sdef
.hasText
= textattrib
!=NULL
;
1075 sdef
.hasXer
= has_encoding(CT_XER
);
1076 sdef
.hasJson
= has_encoding(CT_JSON
);
1077 sdef
.has_opentypes
= get_has_opentypes();
1078 sdef
.opentype_outermost
= get_is_opentype_outermost();
1079 sdef
.ot
= generate_code_ot(pool
);
1080 sdef
.nElements
= get_nof_comps();
1081 sdef
.elements
= (struct_field
*)
1082 Malloc(sdef
.nElements
*sizeof(*sdef
.elements
));
1083 memset(sdef
.elements
, 0, sdef
.nElements
*sizeof(*sdef
.elements
));
1084 sdef
.exerMaybeEmptyIndex
= -1;
1086 sdef
.jsonAsValue
= jsonattrib
->as_value
;
1088 for(size_t i
= 0; i
< sdef
.nElements
; i
++) {
1089 CompField
*cf
= get_comp_byIndex(i
);
1090 const Identifier
& id
= cf
->get_name();
1091 Type
*cftype
= cf
->get_type();
1092 sdef
.elements
[i
].type
= pool
.add(cftype
->get_genname_value(my_scope
));
1093 sdef
.elements
[i
].typedescrname
=
1094 pool
.add(cftype
->get_genname_typedescriptor(my_scope
));
1095 sdef
.elements
[i
].typegen
= pool
.add(cftype
->get_genname_xerdescriptor());
1096 sdef
.elements
[i
].name
= id
.get_name().c_str();
1097 sdef
.elements
[i
].dispname
= id
.get_ttcnname().c_str();
1099 if (cftype
->has_empty_xml()) sdef
.exerMaybeEmptyIndex
= i
;
1100 // This will overwrite lower values, which is what we want.
1102 if (sdef
.jsonAsValue
) {
1103 // Determine the JSON value type of each field to make decoding faster
1104 typetype_t tt
= cftype
->get_type_refd_last()->typetype
;
1107 sdef
.elements
[i
].jsonValueType
= JSON_NUMBER
;
1110 sdef
.elements
[i
].jsonValueType
= JSON_NUMBER
| JSON_STRING
;
1113 sdef
.elements
[i
].jsonValueType
= JSON_LITERAL
;
1122 sdef
.elements
[i
].jsonValueType
= JSON_STRING
;
1127 sdef
.elements
[i
].jsonValueType
= JSON_OBJECT
;
1131 sdef
.elements
[i
].jsonValueType
= JSON_ARRAY
;
1134 FATAL_ERROR("Type::generate_code_Choice - invalid field type %d", tt
);
1137 if (cftype
->jsonattrib
) {
1138 sdef
.elements
[i
].jsonAlias
= cftype
->jsonattrib
->alias
;
1139 if (sdef
.jsonAsValue
&& cftype
->jsonattrib
->as_value
) {
1140 // Override the JSON_OBJECT value given in the switch
1141 sdef
.elements
[i
].jsonValueType
= JSON_ANY_VALUE
;
1146 copy_rawAST_to_struct(rawattrib
,&(sdef
.raw
));
1149 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++){
1150 if(rawattrib
->taglist
.tag
[c
].nElements
)
1151 sdef
.raw
.taglist
.list
[c
].fields
=
1152 (rawAST_coding_field_list
*)
1153 Malloc(rawattrib
->taglist
.tag
[c
].nElements
1154 *sizeof(rawAST_coding_field_list
));
1155 else sdef
.raw
.taglist
.list
[c
].fields
=NULL
;
1156 sdef
.raw
.taglist
.list
[c
].nElements
=
1157 rawattrib
->taglist
.tag
[c
].nElements
;
1158 sdef
.raw
.taglist
.list
[c
].fieldName
=
1159 rawattrib
->taglist
.tag
[c
].fieldName
->get_name().c_str();
1160 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
1161 sdef
.raw
.taglist
.list
[c
].fieldnum
=get_comp_index_byName(*idf
);
1162 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
1163 rawAST_coding_field_list
* key
=
1164 sdef
.raw
.taglist
.list
[c
].fields
+a
;
1166 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->nElements
+1;
1167 key
->value
=rawattrib
->taglist
.tag
[c
].keyList
[a
].value
;
1169 key
->fields
=(rawAST_coding_fields
*)
1170 Malloc(key
->nElements
*sizeof(rawAST_coding_fields
));
1171 CompField
*cf
=get_comp_byIndex(sdef
.raw
.taglist
.list
[c
].fieldnum
);
1172 Type
*t
=cf
->get_type()->get_type_refd_last();
1174 key
->fields
[0].nthfield
= sdef
.raw
.taglist
.list
[c
].fieldnum
;
1175 key
->fields
[0].nthfieldname
=
1176 rawattrib
->taglist
.tag
[c
].fieldName
->get_name().c_str();
1177 key
->fields
[0].fieldtype
= UNION_FIELD
;
1178 key
->fields
[0].type
= pool
.add(t
->get_genname_value(my_scope
));
1179 key
->fields
[0].typedescr
=
1180 pool
.add(t
->get_genname_typedescriptor(my_scope
));
1182 for (int b
= 1; b
< key
->nElements
; b
++) {
1184 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
-1];
1185 size_t comp_index
= t
->get_comp_index_byName(*idf2
);
1186 CompField
*cf2
= t
->get_comp_byIndex(comp_index
);
1187 key
->fields
[b
].nthfield
= comp_index
;
1188 key
->fields
[b
].nthfieldname
= idf2
->get_name().c_str();
1189 if (t
->typetype
== T_CHOICE_T
)
1190 key
->fields
[b
].fieldtype
= UNION_FIELD
;
1191 else if (cf2
->get_is_optional()){
1192 key
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1193 }else key
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1194 Type
*field_type
= cf2
->get_type();
1195 key
->fields
[b
].type
=
1196 pool
.add(field_type
->get_genname_value(my_scope
));
1197 key
->fields
[b
].typedescr
=
1198 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1199 if (field_type
->typetype
== T_SEQ_T
&& field_type
->rawattrib
1200 && (field_type
->rawattrib
->pointerto
1201 || field_type
->rawattrib
->lengthto_num
))
1202 key
->start_pos
= -1;
1204 if(t
->typetype
!= T_CHOICE_T
&& t
->typetype
!= T_SET_T
){
1206 for(size_t i
= 0; i
< comp_index
&& key
->start_pos
>=0; i
++)
1208 t2
= t
->get_comp_byIndex(i
)->get_type();
1209 if(t2
->get_raw_length() >= 0){
1211 key
->start_pos
+= t2
->rawattrib
->padding
;
1212 key
->start_pos
+= t2
->get_raw_length();
1213 }else key
->start_pos
= -1;
1216 t
= field_type
->get_type_refd_last();
1220 } else sdef
.hasRaw
=false;
1222 Module
*my_module
= get_my_scope()->get_scope_mod();
1223 sdef
.xerHasNamespaces
= my_module
->get_nof_ns() != 0;
1224 const char *ns
, *prefix
;
1225 my_module
->get_controlns(ns
, prefix
);
1226 sdef
.control_ns_prefix
= prefix
;
1227 sdef
.xerUseUnion
= xerattrib
->useUnion_
;
1228 sdef
.xerUseTypeAttr
= xerattrib
->useType_
|| xerattrib
->useUnion_
;
1230 defUnionClass(&sdef
, target
);
1231 defUnionTemplate(&sdef
, target
);
1233 free_code_ot(sdef
.ot
);
1236 free_raw_attrib_struct(&sdef
.raw
);
1238 Free(sdef
.elements
);
1241 Opentype_t
*Type::generate_code_ot(stringpool
& pool
)
1243 using namespace Asn
;
1244 if(typetype
!=T_OPENTYPE
)
1246 if(!u
.secho
.my_tableconstraint
1247 || !u
.secho
.my_tableconstraint
->get_ans()) {
1248 DEBUG(1, "Opentype ObjectClassFieldType without"
1249 " ComponentRelationConstraint: `%s'",
1250 get_fullname().c_str());
1253 const AtNotations
*ans
=u
.secho
.my_tableconstraint
->get_ans();
1254 Opentype_t
*ot
=(Opentype_t
*)Malloc(sizeof(*ot
));
1255 ot
->anl
.nElements
= ans
->get_nof_ans();
1256 ot
->anl
.elements
= (AtNotation_t
*)
1257 Malloc(ot
->anl
.nElements
* sizeof(*ot
->anl
.elements
));
1258 for(size_t i
=0; i
<ans
->get_nof_ans(); i
++) {
1259 AtNotation
*an
=ans
->get_an_byIndex(i
);
1260 AtNotation_t
*an_t
= ot
->anl
.elements
+ i
;
1261 an_t
->dispname
= pool
.add(an
->get_dispname());
1262 an_t
->parent_level
=an
->get_levels();
1263 an_t
->parent_typename
=
1264 pool
.add(an
->get_firstcomp()->get_genname_value(my_scope
));
1266 pool
.add(an
->get_lastcomp()->get_genname_value(my_scope
));
1267 an_t
->sourcecode
=memptystr();
1268 FieldName
* cids
=an
->get_cids();
1269 Type
*t_type
=an
->get_firstcomp();
1270 for(size_t j
=0; j
<cids
->get_nof_fields(); j
++) {
1272 t_type
->get_comp_byName(*cids
->get_field_byIndex(j
));
1273 if(j
) an_t
->sourcecode
=mputstr(an_t
->sourcecode
, ".");
1274 an_t
->sourcecode
=mputprintf
1275 (an_t
->sourcecode
, "%s()",
1276 cf
->get_name().get_name().c_str());
1277 if(cf
->get_is_optional())
1278 an_t
->sourcecode
=mputstr(an_t
->sourcecode
, "()");
1279 t_type
=cf
->get_type();
1282 const Identifier
*oc_fieldname_t
1283 =u
.secho
.my_tableconstraint
->get_oc_fieldname();
1285 =u
.secho
.my_tableconstraint
->get_os()->get_refd_last()->get_objs();
1286 ot
->oal
.nElements
= objs
->get_nof_objs();
1287 ot
->oal
.elements
= (OpentypeAlternative_t
*)
1288 Malloc(ot
->oal
.nElements
* sizeof(*ot
->oal
.elements
));
1289 size_t nElements_missing
=0;
1290 Value
**val_prev
=(Value
**)
1291 Malloc(ans
->get_nof_ans()*sizeof(*val_prev
));
1292 boolean differs_from_prev
=true;
1293 for(size_t i
=0; i
<objs
->get_nof_objs(); i
++) {
1294 Obj_defn
*obj
=objs
->get_obj_byIndex(i
);
1295 if(!obj
->has_fs_withName_dflt(*oc_fieldname_t
)) {
1296 nElements_missing
++;
1299 OpentypeAlternative_t
*oa_t
= ot
->oal
.elements
+ i
- nElements_missing
;
1300 Type
*t_type
=dynamic_cast<Type
*>
1301 (obj
->get_setting_byName_dflt(*oc_fieldname_t
));
1303 const Identifier
& altname
= t_type
->get_otaltname(is_strange
);
1304 oa_t
->alt
= pool
.add(altname
.get_name());
1305 oa_t
->alt_dispname
= pool
.add(altname
.get_asnname());
1306 oa_t
->alt_typename
= pool
.add(t_type
->get_genname_value(my_scope
));
1307 oa_t
->alt_typedescrname
=
1308 pool
.add(t_type
->get_genname_typedescriptor(my_scope
));
1309 oa_t
->valuenames
=(const char**)Malloc
1310 (ans
->get_nof_ans()*sizeof(*oa_t
->valuenames
));
1311 oa_t
->const_valuenames
=(const char**)Malloc
1312 (ans
->get_nof_ans()*sizeof(*oa_t
->const_valuenames
));
1313 for(size_t j
=0; j
<ans
->get_nof_ans(); j
++) {
1314 AtNotation
*an
=ans
->get_an_byIndex(j
);
1315 const Identifier
*oc_fieldname_v
=an
->get_oc_fieldname();
1316 Value
*t_value
=dynamic_cast<Value
*>
1317 (obj
->get_setting_byName_dflt(*oc_fieldname_v
));
1318 oa_t
->valuenames
[j
] = pool
.add(t_value
->get_genname_own(my_scope
));
1319 if(!differs_from_prev
&& *val_prev
[j
]==*t_value
)
1320 oa_t
->const_valuenames
[j
]=0;
1322 oa_t
->const_valuenames
[j
] =
1323 pool
.add(t_value
->get_genname_own(my_scope
));
1324 differs_from_prev
=true;
1326 val_prev
[j
]=t_value
;
1328 differs_from_prev
=false;
1331 ot
->oal
.nElements
-= nElements_missing
;
1332 ot
->oal
.elements
= (OpentypeAlternative_t
*)
1333 Realloc(ot
->oal
.elements
,
1334 ot
->oal
.nElements
* sizeof(*ot
->oal
.elements
));
1338 void Type::free_code_ot(Opentype_t
* p_ot
)
1341 for (size_t i
= 0; i
< p_ot
->oal
.nElements
; i
++) {
1342 Free(p_ot
->oal
.elements
[i
].valuenames
);
1343 Free(p_ot
->oal
.elements
[i
].const_valuenames
);
1345 Free(p_ot
->oal
.elements
);
1346 for (size_t i
= 0; i
< p_ot
->anl
.nElements
; i
++)
1347 Free(p_ot
->anl
.elements
[i
].sourcecode
);
1348 Free(p_ot
->anl
.elements
);
1352 size_t Type::get_codegen_index(size_t index
)
1354 // This sorting is because of CER coding of SET types, see X.690 9.3.
1355 // see: Type::generate_code_Se()
1356 // TODO: maybe result should be cached into this type
1357 // ( inside u.secho as dynamic_array<size_t>* codegen_indexes ? )
1358 if (typetype
==T_SET_A
) {
1359 size_t nof_comps
= get_nof_comps();
1360 map
<Tag
, void> se_index_map
;
1361 for (size_t i
=0; i
<nof_comps
; i
++) {
1362 Tag
*tag
= get_comp_byIndex(i
)->get_type()->get_smallest_tag();
1363 se_index_map
.add(*tag
, (void*)i
); // hack: store size_t in void* to avoid Malloc()
1366 for(size_t i
=0; i
<nof_comps
; i
++) {
1367 if (se_index_map
.get_nth_elem(i
)==(void*)index
) {
1368 se_index_map
.clear();
1372 FATAL_ERROR("Type::get_codegen_index()");
1377 void Type::generate_code_Se(output_struct
*target
)
1381 Type
* last_field_type
= 0;
1382 memset(&sdef
, 0, sizeof(sdef
));
1383 sdef
.name
= get_genname_own().c_str();
1384 sdef
.dispname
= get_fullname().c_str();
1385 //printf("generate_code_Se(%s)\n", sdef.dispname);
1404 FATAL_ERROR("Type::generate_code_Se()");
1406 sdef
.hasText
= textattrib
!=NULL
;
1407 sdef
.nElements
= sdef
.totalElements
= get_nof_comps();
1408 sdef
.has_opentypes
= get_has_opentypes();
1409 sdef
.opentype_outermost
= get_is_opentype_outermost();
1411 sdef
.hasXer
= has_encoding(CT_XER
);
1412 sdef
.hasJson
= has_encoding(CT_JSON
);
1414 Module
*my_module
= get_my_scope()->get_scope_mod();
1415 sdef
.xerHasNamespaces
= my_module
->get_nof_ns() != 0;
1416 const char *ns
, *prefix
;
1417 my_module
->get_controlns(ns
, prefix
);
1418 sdef
.control_ns_prefix
= prefix
;
1419 sdef
.xerUntagged
= xerattrib
->untagged_
;
1420 sdef
.xerUntaggedOne
= u
.secho
.has_single_charenc
;
1421 sdef
.xerUseNilPossible
= use_nil_possible
;
1422 sdef
.xerEmbedValuesPossible
= embed_values_possible
;
1423 sdef
.xerUseOrderPossible
= use_order_possible
;
1424 if (xerattrib
->useOrder_
&& xerattrib
->useNil_
) {
1425 // We need information about the fields of the USE-NIL component
1426 const CompField
*cf
= get_comp_byIndex(sdef
.totalElements
-1);
1427 last_field_type
= cf
->get_type()->get_type_refd_last();
1428 sdef
.totalElements
+= last_field_type
->get_nof_comps();
1430 sdef
.xerUseQName
= xerattrib
->useQName_
;
1431 if (xerattrib
->useType_
|| xerattrib
->useUnion_
) {
1432 FATAL_ERROR("Type::generate_code_Se()"); // union only, not for record
1435 sdef
.elements
= (struct_field
*)
1436 Malloc(sdef
.totalElements
*sizeof(*sdef
.elements
));
1437 memset(sdef
.elements
, 0, sdef
.totalElements
* sizeof(*sdef
.elements
));
1439 /* This sorting is because of CER coding of SET types, see X.690
1441 vector
<CompField
> se_comps
;
1442 if(typetype
==T_SET_A
) {
1443 map
<Tag
, CompField
> se_comps_map
;
1444 for(size_t i
=0; i
<sdef
.nElements
; i
++) {
1445 CompField
* cf
=get_comp_byIndex(i
);
1446 Tag
*tag
= cf
->get_type()->get_smallest_tag();
1447 se_comps_map
.add(*tag
, cf
);
1450 for(size_t i
=0; i
<sdef
.nElements
; i
++)
1451 se_comps
.add(se_comps_map
.get_nth_elem(i
));
1452 se_comps_map
.clear();
1455 for(size_t i
=0; i
<sdef
.nElements
; i
++)
1456 se_comps
.add(get_comp_byIndex(i
));
1459 for(size_t i
= 0; i
< sdef
.nElements
; i
++) {
1460 struct_field
&cur
= sdef
.elements
[i
];
1461 CompField
*cf
= se_comps
[i
];
1462 const Identifier
& id
= cf
->get_name();
1463 Type
*type
= cf
->get_type();
1464 cur
.type
= pool
.add(type
->get_genname_value(my_scope
));
1465 cur
.typegen
= pool
.add(type
->get_genname_own());
1466 cur
.of_type
= type
->get_type_refd_last()->is_seof();
1468 pool
.add(type
->get_genname_typedescriptor(my_scope
));
1469 cur
.name
= id
.get_name().c_str();
1470 cur
.dispname
= id
.get_ttcnname().c_str();
1471 cur
.isOptional
= cf
->get_is_optional();
1472 cur
.isDefault
= cf
->has_default();
1473 if (cur
.isDefault
) {
1474 Value
*defval
= cf
->get_defval();
1476 Code::init_cdef(&cdef
);
1477 type
->generate_code_object(&cdef
, defval
);
1478 cdef
.init
= defval
->generate_code_init
1479 (cdef
.init
, defval
->get_lhs_name().c_str());
1480 Code::merge_cdef(target
, &cdef
);
1481 Code::free_cdef(&cdef
);
1482 cur
.defvalname
= defval
->get_genname_own().c_str();
1485 if (type
->xerattrib
) {
1486 cur
.xerAttribute
= type
->xerattrib
->attribute_
;
1488 if (has_aa(type
->xerattrib
)) {
1489 cur
.xerAnyNum
= type
->xerattrib
->anyAttributes_
.nElements_
;
1490 cur
.xerAnyKind
= ANY_ATTRIB_BIT
|
1491 (type
->xerattrib
->anyAttributes_
.type_
== NamespaceRestriction::FROM
?
1492 ANY_FROM_BIT
: ANY_EXCEPT_BIT
);
1493 if (cur
.xerAnyNum
> 0)
1494 cur
.xerAnyUris
= (char**)Malloc(cur
.xerAnyNum
* sizeof(char*));
1495 for (size_t uu
=0; uu
<cur
.xerAnyNum
; ++uu
)
1496 cur
.xerAnyUris
[uu
] = type
->xerattrib
->anyAttributes_
.uris_
[uu
];
1498 else if(has_ae(type
->xerattrib
)) {
1499 cur
.xerAnyNum
= type
->xerattrib
->anyElement_
.nElements_
;
1500 cur
.xerAnyKind
= ANY_ELEM_BIT
|
1501 (type
->xerattrib
->anyElement_
.type_
== NamespaceRestriction::FROM
?
1502 ANY_FROM_BIT
: ANY_EXCEPT_BIT
);
1503 if (cur
.xerAnyNum
> 0)
1504 cur
.xerAnyUris
= (char**)Malloc(cur
.xerAnyNum
* sizeof(char*));
1505 for (size_t uu
=0; uu
<cur
.xerAnyNum
; ++uu
)
1506 cur
.xerAnyUris
[uu
] = type
->xerattrib
->anyElement_
.uris_
[uu
];
1509 if (type
->jsonattrib
) {
1510 cur
.jsonOmitAsNull
= type
->jsonattrib
->omit_as_null
;
1511 cur
.jsonAlias
= type
->jsonattrib
->alias
;
1512 cur
.jsonDefaultValue
= type
->jsonattrib
->default_value
;
1516 if (last_field_type
)
1517 for (size_t i
= sdef
.nElements
; i
< sdef
.totalElements
; i
++) {
1518 struct_field
&cur
= sdef
.elements
[i
];
1519 CompField
*cf
= last_field_type
->get_comp_byIndex(i
- sdef
.nElements
);
1520 const Identifier
& id
= cf
->get_name();
1521 Type
*type
= cf
->get_type();
1522 cur
.type
= pool
.add(type
->get_genname_value(my_scope
));
1523 cur
.typegen
= pool
.add(type
->get_genname_own());
1524 cur
.of_type
= type
->get_type_refd_last()->is_seof();
1526 pool
.add(type
->get_genname_typedescriptor(my_scope
));
1527 cur
.name
= id
.get_name().c_str();
1528 cur
.dispname
= id
.get_ttcnname().c_str();
1529 cur
.isOptional
= cf
->get_is_optional();
1534 copy_rawAST_to_struct(rawattrib
,&(sdef
.raw
));
1537 for(int c
=0;c
<rawattrib
->taglist
.nElements
;c
++) {
1538 if(rawattrib
->taglist
.tag
[c
].nElements
)
1539 sdef
.raw
.taglist
.list
[c
].fields
=
1540 (rawAST_coding_field_list
*)
1541 Malloc(rawattrib
->taglist
.tag
[c
].nElements
1542 *sizeof(rawAST_coding_field_list
));
1543 else sdef
.raw
.taglist
.list
[c
].fields
=NULL
;
1544 sdef
.raw
.taglist
.list
[c
].nElements
=
1545 rawattrib
->taglist
.tag
[c
].nElements
;
1546 sdef
.raw
.taglist
.list
[c
].fieldName
=
1547 rawattrib
->taglist
.tag
[c
].fieldName
->get_name().c_str();
1548 Identifier
*idf
=rawattrib
->taglist
.tag
[c
].fieldName
;
1549 sdef
.raw
.taglist
.list
[c
].fieldnum
=get_comp_index_byName(*idf
);
1550 for(int a
=0;a
<rawattrib
->taglist
.tag
[c
].nElements
;a
++){
1551 rawAST_coding_field_list
* key
=
1552 sdef
.raw
.taglist
.list
[c
].fields
+a
;
1554 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->nElements
+1;
1555 key
->value
=rawattrib
->taglist
.tag
[c
].keyList
[a
].value
;
1557 key
->fields
=(rawAST_coding_fields
*)
1558 Malloc(key
->nElements
*sizeof(rawAST_coding_fields
));
1560 CompField
*cf
=get_comp_byIndex(sdef
.raw
.taglist
.list
[c
].fieldnum
);
1561 Type
*t
=cf
->get_type()->get_type_refd_last();
1563 key
->fields
[0].nthfield
= sdef
.raw
.taglist
.list
[c
].fieldnum
;
1564 key
->fields
[0].nthfieldname
=
1565 rawattrib
->taglist
.tag
[c
].fieldName
->get_name().c_str();
1566 if (cf
->get_is_optional())
1567 key
->fields
[0].fieldtype
= OPTIONAL_FIELD
;
1568 else key
->fields
[0].fieldtype
= MANDATORY_FIELD
;
1569 key
->fields
[0].type
= pool
.add(t
->get_genname_value(my_scope
));
1570 key
->fields
[0].typedescr
=
1571 pool
.add(t
->get_genname_typedescriptor(my_scope
));
1574 for (int b
= 1; b
< key
->nElements
; b
++) {
1576 rawattrib
->taglist
.tag
[c
].keyList
[a
].keyField
->names
[b
-1];
1577 size_t comp_index
= t
->get_comp_index_byName(*idf2
);
1578 cf2
= t
->get_comp_byIndex(comp_index
);
1579 key
->fields
[b
].nthfield
= comp_index
;
1580 key
->fields
[b
].nthfieldname
= idf2
->get_name().c_str();
1581 if (t
->typetype
== T_CHOICE_T
)
1582 key
->fields
[b
].fieldtype
= UNION_FIELD
;
1583 else if (cf2
->get_is_optional())
1584 key
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1585 else key
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1586 Type
*field_type
= cf2
->get_type();
1587 key
->fields
[b
].type
=
1588 pool
.add(field_type
->get_genname_value(my_scope
));
1589 key
->fields
[b
].typedescr
=
1590 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1591 if (field_type
->typetype
== T_SEQ_T
&& field_type
->rawattrib
1592 && (field_type
->rawattrib
->pointerto
1593 || field_type
->rawattrib
->lengthto_num
))
1594 key
->start_pos
= -1;
1596 if(t
->typetype
!= T_CHOICE_T
&& t
->typetype
!= T_SET_T
){
1598 for(size_t i
= 0; i
< comp_index
&& key
->start_pos
>=0; i
++)
1600 t2
= t
->get_comp_byIndex(i
)->get_type();
1601 if(t2
->get_raw_length() >= 0){
1603 key
->start_pos
+= t2
->rawattrib
->padding
;
1604 key
->start_pos
+= t2
->get_raw_length();
1605 }else key
->start_pos
= -1;
1608 t
= field_type
->get_type_refd_last();
1612 // building presence list
1613 for(int a
=0;a
<rawattrib
->presence
.nElements
;a
++) {
1614 rawAST_coding_field_list
* presences
=sdef
.raw
.presence
.fields
+a
;
1615 presences
->nElements
=
1616 rawattrib
->presence
.keyList
[a
].keyField
->nElements
;
1617 presences
->value
=rawattrib
->presence
.keyList
[a
].value
;
1618 presences
->fields
=(rawAST_coding_fields
*)
1619 Malloc(presences
->nElements
*sizeof(rawAST_coding_fields
));
1621 for (int b
= 0; b
< presences
->nElements
; b
++) {
1622 Identifier
*idf
= rawattrib
->presence
.keyList
[a
].keyField
->names
[b
];
1623 size_t comp_index
= t
->get_comp_index_byName(*idf
);
1624 CompField
*cf
= t
->get_comp_byIndex(comp_index
);
1625 presences
->fields
[b
].nthfield
= comp_index
;
1626 presences
->fields
[b
].nthfieldname
= idf
->get_name().c_str();
1627 if (t
->typetype
== T_CHOICE_T
)
1628 presences
->fields
[b
].fieldtype
= UNION_FIELD
;
1629 else if (cf
->get_is_optional())
1630 presences
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1631 else presences
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1632 Type
*field_type
= cf
->get_type();
1633 presences
->fields
[b
].type
=
1634 pool
.add(field_type
->get_genname_value(my_scope
));
1635 presences
->fields
[b
].typedescr
=
1636 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1637 t
= field_type
->get_type_refd_last();
1640 for(int c
=0;c
<rawattrib
->ext_bit_goup_num
;c
++){
1641 Identifier
*idf
=rawattrib
->ext_bit_groups
[c
].from
;
1642 Identifier
*idf2
=rawattrib
->ext_bit_groups
[c
].to
;
1643 sdef
.raw
.ext_bit_groups
[c
].ext_bit
=rawattrib
->ext_bit_groups
[c
].ext_bit
;
1644 sdef
.raw
.ext_bit_groups
[c
].from
=(int)get_comp_index_byName(*idf
);
1645 sdef
.raw
.ext_bit_groups
[c
].to
=(int)get_comp_index_byName(*idf2
);
1647 for(size_t i
=0; i
<sdef
.totalElements
; i
++) {
1648 CompField
*cf
= get_comp_byIndex(i
);
1649 Type
*t_field
= cf
->get_type();
1650 Type
*t_field_last
= t_field
->get_type_refd_last();
1651 RawAST
*rawpar
= t_field
->rawattrib
;
1653 copy_rawAST_to_struct(rawpar
,&(sdef
.elements
[i
].raw
));
1654 for(int j
=0; j
<rawpar
->lengthto_num
;j
++){
1655 Identifier
*idf
=rawpar
->lengthto
[j
];
1656 sdef
.elements
[i
].raw
.lengthto
[j
]=get_comp_index_byName(*idf
);
1658 if (rawpar
->lengthto_num
&& rawpar
->lengthindex
) {
1659 Identifier
*idf
= rawpar
->lengthindex
->names
[0];
1660 size_t comp_index
= t_field_last
->get_comp_index_byName(*idf
);
1661 sdef
.elements
[i
].raw
.lengthindex
->nthfield
= comp_index
;
1662 sdef
.elements
[i
].raw
.lengthindex
->nthfieldname
=
1663 idf
->get_name().c_str();
1664 CompField
*cf2
= t_field_last
->get_comp_byIndex(comp_index
);
1665 Type
*t_field2
= cf2
->get_type();
1666 if (t_field2
->typetype
== T_CHOICE_T
)
1667 sdef
.elements
[i
].raw
.lengthindex
->fieldtype
= UNION_FIELD
;
1668 else if (cf2
->get_is_optional())
1669 sdef
.elements
[i
].raw
.lengthindex
->fieldtype
= OPTIONAL_FIELD
;
1670 else sdef
.elements
[i
].raw
.lengthindex
->fieldtype
= MANDATORY_FIELD
;
1671 sdef
.elements
[i
].raw
.lengthindex
->type
=
1672 pool
.add(t_field2
->get_genname_value(my_scope
));
1673 sdef
.elements
[i
].raw
.lengthindex
->typedescr
=
1674 pool
.add(t_field2
->get_genname_typedescriptor(my_scope
));
1676 if (rawpar
->lengthto_num
&& !rawpar
->lengthindex
&&
1677 t_field_last
->is_secho()) {
1678 int comp_num
=(int)t_field_last
->get_nof_comps();
1679 sdef
.elements
[i
].raw
.union_member_num
=comp_num
;
1680 sdef
.elements
[i
].raw
.member_name
=
1681 (const char **)Malloc((comp_num
+1)*sizeof(const char*));
1682 sdef
.elements
[i
].raw
.member_name
[0] =
1683 pool
.add(t_field_last
->get_genname_value(my_scope
));
1684 for(int m
=1;m
<comp_num
+1;m
++){
1685 CompField
*compf
=t_field_last
->get_comp_byIndex(m
-1);
1686 sdef
.elements
[i
].raw
.member_name
[m
]=
1687 compf
->get_name().get_name().c_str();
1690 if(rawpar
->pointerto
){
1691 Identifier
*idf
=rawpar
->pointerto
;
1692 sdef
.elements
[i
].raw
.pointerto
=get_comp_index_byName(*idf
);
1693 if(rawpar
->ptrbase
){
1694 Identifier
*idf2
=rawpar
->ptrbase
;
1695 sdef
.elements
[i
].raw
.pointerbase
=get_comp_index_byName(*idf2
);
1696 } else sdef
.elements
[i
].raw
.pointerbase
=i
;
1698 // building presence list
1699 for(int a
=0;a
<rawpar
->presence
.nElements
;a
++) {
1700 rawAST_coding_field_list
* presences
=
1701 sdef
.elements
[i
].raw
.presence
.fields
+a
;
1702 presences
->nElements
=
1703 rawpar
->presence
.keyList
[a
].keyField
->nElements
;
1704 presences
->value
=rawpar
->presence
.keyList
[a
].value
;
1705 presences
->fields
=(rawAST_coding_fields
*)
1706 Malloc(presences
->nElements
*sizeof(rawAST_coding_fields
));
1708 for (int b
= 0; b
< presences
->nElements
; b
++) {
1709 Identifier
*idf
= rawpar
->presence
.keyList
[a
].keyField
->names
[b
];
1710 size_t comp_index
= t
->get_comp_index_byName(*idf
);
1711 CompField
*cf2
= t
->get_comp_byIndex(comp_index
);
1712 presences
->fields
[b
].nthfield
= comp_index
;
1713 presences
->fields
[b
].nthfieldname
= idf
->get_name().c_str();
1714 if (t
->typetype
== T_CHOICE_T
)
1715 presences
->fields
[b
].fieldtype
= UNION_FIELD
;
1716 else if (cf2
->get_is_optional())
1717 presences
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1718 else presences
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1719 Type
*field_type
= cf2
->get_type();
1720 presences
->fields
[b
].type
=
1721 pool
.add(field_type
->get_genname_value(my_scope
));
1722 presences
->fields
[b
].typedescr
=
1723 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1724 t
= field_type
->get_type_refd_last();
1727 // building crosstaglist
1728 for(int c
=0;c
<rawpar
->crosstaglist
.nElements
;c
++){
1729 if(rawpar
->crosstaglist
.tag
[c
].nElements
)
1730 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fields
=
1731 (rawAST_coding_field_list
*)
1732 Malloc(rawpar
->crosstaglist
.tag
[c
].nElements
1733 *sizeof(rawAST_coding_field_list
));
1734 else sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fields
=NULL
;
1735 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].nElements
=
1736 rawpar
->crosstaglist
.tag
[c
].nElements
;
1737 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fieldName
=
1738 rawpar
->crosstaglist
.tag
[c
].fieldName
->get_name().c_str();
1739 Identifier
*idf
=rawpar
->crosstaglist
.tag
[c
].fieldName
;
1740 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fieldnum
=
1741 t_field_last
->get_comp_index_byName(*idf
);
1742 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fieldnum
=
1743 t_field_last
->get_comp_index_byName(*idf
);
1744 for(int a
=0;a
<rawpar
->crosstaglist
.tag
[c
].nElements
;a
++) {
1745 rawAST_coding_field_list
* key
=
1746 sdef
.elements
[i
].raw
.crosstaglist
.list
[c
].fields
+a
;
1748 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->nElements
;
1749 key
->value
=rawpar
->crosstaglist
.tag
[c
].keyList
[a
].value
;
1750 key
->fields
=(rawAST_coding_fields
*)
1751 Malloc(key
->nElements
*sizeof(rawAST_coding_fields
));
1753 for (int b
= 0; b
< key
->nElements
; b
++) {
1755 rawpar
->crosstaglist
.tag
[c
].keyList
[a
].keyField
->names
[b
];
1756 size_t comp_index
= t
->get_comp_index_byName(*idf2
);
1757 CompField
*cf2
= t
->get_comp_byIndex(comp_index
);
1758 key
->fields
[b
].nthfield
= comp_index
;
1759 key
->fields
[b
].nthfieldname
= idf2
->get_name().c_str();
1760 if (t
->typetype
== T_CHOICE_T
)
1761 key
->fields
[b
].fieldtype
= UNION_FIELD
;
1762 else if (cf2
->get_is_optional())
1763 key
->fields
[b
].fieldtype
= OPTIONAL_FIELD
;
1764 else key
->fields
[b
].fieldtype
= MANDATORY_FIELD
;
1765 Type
*field_type
= cf2
->get_type();
1766 key
->fields
[b
].type
=
1767 pool
.add(field_type
->get_genname_value(my_scope
));
1768 key
->fields
[b
].typedescr
=
1769 pool
.add(field_type
->get_genname_typedescriptor(my_scope
));
1770 t
= field_type
->get_type_refd_last();
1774 sdef
.elements
[i
].raw
.length
= t_field
->get_raw_length();
1775 sdef
.elements
[i
].hasRaw
=true;
1778 sdef
.elements
[i
].hasRaw
=false;
1783 for(size_t i
= 0; i
< sdef
.totalElements
; i
++) {
1784 sdef
.elements
[i
].hasRaw
=false;
1789 defRecordClass(&sdef
, target
);
1790 defRecordTemplate(&sdef
, target
);
1792 for(size_t i
= 0; i
< sdef
.totalElements
; i
++) {
1793 // free the array but not the strings
1794 if (sdef
.elements
[i
].xerAnyNum
> 0) Free(sdef
.elements
[i
].xerAnyUris
);
1798 free_raw_attrib_struct(&sdef
.raw
);
1799 for (size_t i
= 0; i
< sdef
.totalElements
; i
++) {
1800 if (sdef
.elements
[i
].hasRaw
) {
1801 free_raw_attrib_struct(&sdef
.elements
[i
].raw
);
1805 Free(sdef
.elements
);
1808 bool Type::is_untagged() const { return xerattrib
&& xerattrib
->untagged_
; }
1810 void Type::generate_code_SeOf(output_struct
*target
)
1813 struct_of_def sofdef
;
1814 memset(&sofdef
, 0, sizeof(sofdef
));
1815 sofdef
.name
= get_genname_own().c_str();
1816 sofdef
.dispname
= get_fullname().c_str();
1817 sofdef
.kind
= typetype
== T_SEQOF
? RECORD_OF
: SET_OF
;
1818 sofdef
.isASN1
= is_asn1();
1819 sofdef
.hasText
= textattrib
!=NULL
;
1820 sofdef
.hasXer
= has_encoding(CT_XER
);
1821 sofdef
.hasJson
= has_encoding(CT_JSON
);
1823 //sofdef.xerList = xerattrib->list_;
1824 sofdef
.xerAttribute
= xerattrib
->attribute_
;
1826 // If a record of UTF8String, we need to prepare for ANY-ATTRIBUTES and
1828 const Type
*oftypelast
= u
.seof
.ofType
->get_type_refd_last();
1829 sofdef
.xerAnyAttrElem
= oftypelast
->typetype
== T_USTR
1830 || oftypelast
->typetype
== T_UTF8STRING
;
1831 const string
& oftypename
= u
.seof
.ofType
->get_genname_value(my_scope
);
1832 sofdef
.type
= oftypename
.c_str();
1833 sofdef
.has_opentypes
= get_has_opentypes();
1834 const string
& oftypedescrname
=
1835 u
.seof
.ofType
->get_genname_typedescriptor(my_scope
);
1836 sofdef
.oftypedescrname
= oftypedescrname
.c_str();
1838 if (xerattrib
&& xerattrib
->untagged_
1839 && ((u
.seof
.ofType
->xerattrib
&& has_ae(u
.seof
.ofType
->xerattrib
))
1840 || (xerattrib
&& has_ae(xerattrib
)))) {
1841 // An untagged record-of which has an embedded type with ANY-ELEMENT,
1842 // or itself has ANY-ELEMENT
1843 if (parent_type
&& parent_type
->typetype
== T_SEQ_T
) {
1844 /* The record-of needs to know the optional siblings following it,
1845 * to be able to stop consuming XML elements that belong
1846 * to the following fields. This is achieved by generating
1847 * a can_start() for the record-of which returns false for XML elements
1848 * that belong to those following fields. */
1849 size_t n_parent_comps
= parent_type
->get_nof_comps();
1850 boolean found_self
= false;
1851 /* Go through the fields of the parent; skip everything until we find
1852 * the field that is this record-of; then collect fields until
1853 * the first non-disappearing field. */
1854 for (size_t pc
= 0; pc
< n_parent_comps
; ++pc
) {
1855 CompField
*pcf
= parent_type
->get_comp_byIndex(pc
); //"ParentCompField"
1856 Type
*pcft
= pcf
->get_type();
1858 const Identifier
& cfid
= pcf
->get_name();
1859 sofdef
.followers
= (struct_field
*)Realloc(sofdef
.followers
,
1860 (++sofdef
.nFollowers
) * sizeof(struct_field
));
1861 sofdef
.followers
[sofdef
.nFollowers
-1].name
= pool
.add(cfid
.get_name());
1862 sofdef
.followers
[sofdef
.nFollowers
-1].type
=
1863 pool
.add(pcft
->get_genname_value(my_scope
));
1864 sofdef
.followers
[sofdef
.nFollowers
-1].typegen
=
1865 pool
.add(pcft
->get_genname_own());
1867 Type
*pcft_last
= pcft
->get_type_refd_last();
1868 if (pcf
->get_is_optional()
1869 || (pcft
->is_untagged() && pcft_last
->has_empty_xml()))
1870 {} // can disappear, continue
1873 else if (pcft
== this) found_self
= true;
1875 } // if parent is record
1878 switch (oftypelast
->typetype
) { // X.680/2002, Table 5 under 25.5
1879 // T_CHOICE_A and T_CHOICE_T do not set xmlValueList because choice types
1880 // already omit their own tag.
1882 case T_ENUM_A
: case T_ENUM_T
:
1884 sofdef
.xmlValueList
= TRUE
;
1888 sofdef
.xmlValueList
= FALSE
;
1893 copy_rawAST_to_struct(rawattrib
,&(sofdef
.raw
));
1895 } else sofdef
.hasRaw
=false;
1897 if (!use_runtime_2
&& get_optimize_attribute()=="memalloc") {
1898 defRecordOfClassMemAllocOptimized(&sofdef
, target
);
1900 defRecordOfClass(&sofdef
, target
);
1902 defRecordOfTemplate(&sofdef
, target
);
1904 if (sofdef
.nFollowers
) {
1905 Free(sofdef
.followers
);
1909 void Type::generate_code_Array(output_struct
*target
)
1911 if (!u
.array
.in_typedef
) return;
1912 const char *own_name
= get_genname_own().c_str();
1913 if (has_encoding(CT_JSON
)) {
1914 target
->header
.class_decls
= mputprintf(target
->header
.class_decls
,
1915 "class %s;\n", own_name
);
1916 target
->header
.class_defs
= mputprintf(target
->header
.class_defs
,
1917 "class %s : public %s {\n"
1918 "const TTCN_Typedescriptor_t* get_elem_descr() const;\n"
1921 u
.array
.dimension
->get_value_type(u
.array
.element_type
, my_scope
).c_str());
1922 target
->source
.class_defs
= mputprintf(target
->source
.class_defs
,
1923 "const TTCN_Typedescriptor_t* %s::get_elem_descr() const { return &%s_descr_; }\n\n",
1924 own_name
, u
.array
.element_type
->get_genname_typedescriptor(my_scope
).c_str());
1926 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1928 "// written by %s in " __FILE__
" at %d\n"
1932 __FUNCTION__
, __LINE__
,
1934 u
.array
.dimension
->get_value_type(u
.array
.element_type
, my_scope
).c_str(),
1937 target
->header
.typedefs
= mputprintf(target
->header
.typedefs
,
1938 "typedef %s %s_template;\n",
1939 u
.array
.dimension
->get_template_type(u
.array
.element_type
, my_scope
).c_str(),
1943 void Type::generate_code_Fat(output_struct
*target
)
1946 memset(&fdef
, 0, sizeof(fdef
));
1947 fdef
.name
= get_genname_own().c_str();
1948 fdef
.dispname
= get_fullname().c_str();
1951 if(u
.fatref
.return_type
)
1952 if(u
.fatref
.returns_template
)
1953 fdef
.return_type
= mcopystr(u
.fatref
.return_type
->
1954 get_genname_template(my_scope
).c_str());
1955 else fdef
.return_type
= mcopystr(u
.fatref
.return_type
->
1956 get_genname_value(my_scope
).c_str());
1957 else fdef
.return_type
= NULL
;
1958 fdef
.type
= FUNCTION
;
1961 fdef
.return_type
= NULL
;
1962 fdef
.type
= ALTSTEP
;
1965 fdef
.return_type
= NULL
;
1966 fdef
.type
= TESTCASE
;
1969 FATAL_ERROR("Type::generate_code_Fat()");
1971 fdef
.runs_on_self
= u
.fatref
.runs_on
.self
? TRUE
: FALSE
;
1972 fdef
.is_startable
= u
.fatref
.is_startable
;
1973 fdef
.formal_par_list
= u
.fatref
.fp_list
->generate_code(memptystr());
1974 u
.fatref
.fp_list
->generate_code_defval(target
);
1975 fdef
.actual_par_list
= u
.fatref
.fp_list
1976 ->generate_code_actual_parlist(memptystr(),"");
1977 if (typetype
== T_TESTCASE
) {
1978 if (u
.fatref
.fp_list
->get_nof_fps() > 0) {
1979 fdef
.formal_par_list
= mputstr(fdef
.formal_par_list
, ", ");
1980 fdef
.actual_par_list
= mputstr(fdef
.actual_par_list
, ", ");
1982 fdef
.formal_par_list
= mputstr(fdef
.formal_par_list
,
1983 "boolean has_timer, double timer_value");
1984 fdef
.actual_par_list
= mputstr(fdef
.actual_par_list
,
1985 "has_timer, timer_value");
1987 fdef
.nElements
= u
.fatref
.fp_list
->get_nof_fps();
1988 fdef
.parameters
= (const char**)
1989 Malloc(fdef
.nElements
* sizeof(*fdef
.parameters
));
1990 for(size_t i
= 0;i
< fdef
.nElements
; i
++) {
1991 fdef
.parameters
[i
] = u
.fatref
.fp_list
->get_fp_byIndex(i
)
1992 ->get_id().get_name().c_str();
1995 defFunctionrefClass(&fdef
, target
);
1996 defFunctionrefTemplate(&fdef
, target
);
1997 Free(fdef
.return_type
);
1998 Free(fdef
.formal_par_list
);
1999 Free(fdef
.actual_par_list
);
2000 Free(fdef
.parameters
);
2003 void Type::generate_code_Signature(output_struct
*target
)
2007 memset(&sdef
, 0, sizeof(sdef
));
2008 sdef
.name
= get_genname_own().c_str();
2009 sdef
.dispname
= get_fullname().c_str();
2010 if (u
.signature
.return_type
) sdef
.return_type
=
2011 pool
.add(u
.signature
.return_type
->get_genname_value(my_scope
));
2012 else sdef
.return_type
= NULL
;
2013 if (u
.signature
.parameters
) {
2014 sdef
.parameters
.nElements
= u
.signature
.parameters
->get_nof_params();
2015 sdef
.parameters
.elements
= (signature_par
*)
2016 Malloc(sdef
.parameters
.nElements
* sizeof(*sdef
.parameters
.elements
));
2017 for (size_t i
= 0; i
< sdef
.parameters
.nElements
; i
++) {
2018 SignatureParam
*param
= u
.signature
.parameters
->get_param_byIndex(i
);
2019 switch (param
->get_direction()) {
2020 case SignatureParam::PARAM_IN
:
2021 sdef
.parameters
.elements
[i
].direction
= PAR_IN
;
2023 case SignatureParam::PARAM_OUT
:
2024 sdef
.parameters
.elements
[i
].direction
= PAR_OUT
;
2026 case SignatureParam::PARAM_INOUT
:
2027 sdef
.parameters
.elements
[i
].direction
= PAR_INOUT
;
2030 FATAL_ERROR("Type::generate_code_Signature()");
2032 sdef
.parameters
.elements
[i
].type
=
2033 pool
.add(param
->get_type()->get_genname_value(my_scope
));
2034 sdef
.parameters
.elements
[i
].name
= param
->get_id().get_name().c_str();
2035 sdef
.parameters
.elements
[i
].dispname
=
2036 param
->get_id().get_ttcnname().c_str();
2039 sdef
.parameters
.nElements
= 0;
2040 sdef
.parameters
.elements
= NULL
;
2042 sdef
.is_noblock
= u
.signature
.no_block
;
2043 if (u
.signature
.exceptions
) {
2044 sdef
.exceptions
.nElements
= u
.signature
.exceptions
->get_nof_types();
2045 sdef
.exceptions
.elements
= (signature_exception
*)
2046 Malloc(sdef
.exceptions
.nElements
* sizeof(*sdef
.exceptions
.elements
));
2047 for (size_t i
= 0; i
< sdef
.exceptions
.nElements
; i
++) {
2048 Type
*type
= u
.signature
.exceptions
->get_type_byIndex(i
);
2049 sdef
.exceptions
.elements
[i
].name
=
2050 pool
.add(type
->get_genname_value(my_scope
));
2051 sdef
.exceptions
.elements
[i
].dispname
= pool
.add(type
->get_typename());
2052 sdef
.exceptions
.elements
[i
].altname
= pool
.add(type
->get_genname_altname());
2055 sdef
.exceptions
.nElements
= 0;
2056 sdef
.exceptions
.elements
= NULL
;
2058 defSignatureClasses(&sdef
, target
);
2059 Free(sdef
.parameters
.elements
);
2060 Free(sdef
.exceptions
.elements
);
2063 bool Type::needs_alias()
2065 /** The decision is actually based on the fullname of the type. If it
2066 * contains two or more dot (.) characters false is returned.
2067 * The following attributes cannot be used for the decision:
2068 * - parent_type, my_scope: types within ASN.1 object classes, objects
2069 * look the same as top-level aliased types, but they do not need alias. */
2070 const string
& full_name
= get_fullname();
2071 size_t fullname_len
= full_name
.size();
2072 size_t first_dot
= full_name
.find('.', 0);
2073 if (first_dot
>= fullname_len
) return true; // no dots
2074 else if (full_name
.find('.', first_dot
+ 1) < fullname_len
) return false;
2079 void Type::generate_code_done(output_struct
*target
)
2081 const string
& t_genname
= get_genname_value(my_scope
);
2082 const char *genname_str
= t_genname
.c_str();
2083 const string
& dispname
= get_typename();
2084 const char *dispname_str
= dispname
.c_str();
2085 target
->header
.function_prototypes
= mputprintf
2086 (target
->header
.function_prototypes
,
2087 "extern alt_status done(const COMPONENT& component_reference, "
2088 "const %s_template& value_template, %s *value_ptr);\n",
2089 genname_str
, genname_str
);
2090 target
->source
.function_bodies
= mputprintf
2091 (target
->source
.function_bodies
,
2092 "alt_status done(const COMPONENT& component_reference, "
2093 "const %s_template& value_template, %s *value_ptr)\n"
2095 "if (!component_reference.is_bound()) "
2096 "TTCN_error(\"Performing a done operation on an unbound component "
2098 "Text_Buf *text_buf;\n"
2099 "alt_status ret_val = TTCN_Runtime::component_done("
2100 "(component)component_reference, \"%s\", text_buf);\n"
2101 "if (ret_val == ALT_YES) {\n"
2102 "%s return_value;\n"
2103 "return_value.decode_text(*text_buf);\n"
2104 "if (value_template.match(return_value)) {\n"
2105 "if (value_ptr != NULL) *value_ptr = return_value;\n"
2106 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
2107 "TTCN_Logger::log_event_str(\"PTC with component reference \");\n"
2108 "component_reference.log();\n"
2109 "TTCN_Logger::log_event_str(\" is done. Return value: %s : \");\n"
2110 "return_value.log();\n"
2111 "TTCN_Logger::end_event();\n"
2114 "if (TTCN_Logger::log_this_event(TTCN_Logger::MATCHING_DONE)) {\n"
2115 "TTCN_Logger::begin_event(TTCN_Logger::MATCHING_DONE);\n"
2116 "TTCN_Logger::log_event_str(\"Done operation with type %s on"
2117 " component reference \");\n"
2118 "component_reference.log();\n"
2119 "TTCN_Logger::log_event_str(\" failed: Return value does not match "
2120 "the template: \");\n"
2121 "value_template.log_match(return_value);\n"
2122 "TTCN_Logger::end_event();\n"
2126 "} else return ret_val;\n"
2128 genname_str
, genname_str
, dispname_str
, genname_str
, dispname_str
,
2132 bool Type::ispresent_anyvalue_embedded_field(Type
* t
,
2133 Ttcn::FieldOrArrayRefs
*subrefs
, size_t begin_index
)
2135 if (!subrefs
) return true;
2136 size_t nof_refs
= subrefs
->get_nof_refs();
2137 for (size_t i
= begin_index
; i
< nof_refs
; i
++) {
2138 t
= t
->get_type_refd_last();
2139 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
2140 switch (ref
->get_type()) {
2141 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
2142 CompField
* cf
= t
->get_comp_byName(*ref
->get_id());
2143 switch (t
->typetype
) {
2153 if (cf
->get_is_optional()) return false;
2156 FATAL_ERROR("Type::ispresent_anyvalue_embedded_field()");
2160 case Ttcn::FieldOrArrayRef::ARRAY_REF
:
2161 switch (t
->typetype
) {
2164 return false; // (the existence of a record of element is optional)
2166 t
= t
->u
.array
.element_type
;
2169 return true; // string types
2173 FATAL_ERROR("Type::ispresent_anyvalue_embedded_field()");
2179 void Type::generate_code_ispresentbound(expression_struct
*expr
,
2180 Ttcn::FieldOrArrayRefs
*subrefs
, Common::Module
* module
,
2181 const string
& global_id
, const string
& external_id
, const bool is_template
,
2184 if (!subrefs
) return;
2188 bool next_o
; // next is optional value
2189 size_t nof_refs
= subrefs
->get_nof_refs();
2190 subrefs
->clear_string_element_ref();
2191 char *tmp_generalid_str
= mcopystr(external_id
.c_str());
2192 expstring_t closing_brackets
= memptystr(); //The closing parts collected
2193 for (size_t i
= 0; i
< nof_refs
; i
++) {
2194 t
= t
->get_type_refd_last();
2195 // stop immediately if current type t is erroneous
2196 // (e.g. because of circular reference)
2197 if (t
->typetype
== T_ERROR
) return;
2200 bool anyval_ret_val
= true;
2202 anyval_ret_val
= ispresent_anyvalue_embedded_field(t
, subrefs
, i
);
2204 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2205 expr
->expr
= mputprintf(expr
->expr
,
2206 "switch (%s.get_selection()) {\n"
2207 "case UNINITIALIZED_TEMPLATE:\n"
2213 "case SPECIFIC_VALUE: {\n",
2214 tmp_generalid_str
, global_id
.c_str(), global_id
.c_str(),
2215 anyval_ret_val
? "true" : "false");
2217 expstring_t closing_brackets_switch
= mprintf(
2225 global_id
.c_str(), closing_brackets
);
2226 Free(closing_brackets
);
2227 closing_brackets
= closing_brackets_switch
;
2230 Ttcn::FieldOrArrayRef
*ref
= subrefs
->get_ref(i
);
2231 switch (ref
->get_type()) {
2232 case Ttcn::FieldOrArrayRef::FIELD_REF
: {
2233 const Identifier
& id
= *ref
->get_id();
2234 CompField
* cf
= t
->get_comp_byName(id
);
2235 next_t
= cf
->get_type();
2236 next_o
= !is_template
&& cf
->get_is_optional();
2238 switch (t
->typetype
) {
2242 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2243 expr
->expr
= mputprintf(expr
->expr
,
2244 "%s = %s.ischosen(%s::ALT_%s);\n", global_id
.c_str(),
2246 t
->get_genname_value(module
).c_str(),
2247 id
.get_name().c_str());
2248 expr
->expr
= mputstr(expr
->expr
, "}\n");
2249 // intentionally missing break
2257 FATAL_ERROR("Type::generate_code_isbound()");
2261 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2262 expstring_t closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2263 Free(closing_brackets
);
2264 closing_brackets
= closing_brackets2
;
2266 const string
& tmp_id
= module
->get_temporary_id();
2267 const char *tmp_id_str
= tmp_id
.c_str();
2268 expr
->expr
= mputprintf(expr
->expr
,
2269 "const OPTIONAL<%s%s>& %s = %s.%s();\n",
2270 next_t
->get_genname_value(module
).c_str(),
2271 is_template
?"_template":"", tmp_id_str
, tmp_generalid_str
,
2272 id
.get_name().c_str());
2274 if (i
==(nof_refs
-1)) {
2275 // we are at the end of the reference chain
2276 expr
->expr
= mputprintf(expr
->expr
,
2277 "switch (%s.get_selection()) {\n"
2278 "case OPTIONAL_UNBOUND:\n"
2281 "case OPTIONAL_OMIT:\n"
2285 tmp_id_str
, global_id
.c_str(),global_id
.c_str(),
2286 isbound
? "true" : "false");
2287 Free(tmp_generalid_str
);
2288 tmp_generalid_str
= mcopystr(tmp_id_str
);
2290 expr
->expr
= mputstr(expr
->expr
, "{\n");
2291 const string
& tmp_id2
= module
->get_temporary_id();
2292 const char *tmp_id2_str
= tmp_id2
.c_str();
2293 expr
->expr
= mputprintf(expr
->expr
,
2294 "const %s%s& %s = (const %s%s&) %s;\n",
2295 next_t
->get_genname_value(module
).c_str(),
2296 is_template
?"_template":"", tmp_id2_str
,
2297 next_t
->get_genname_value(module
).c_str(),
2298 is_template
?"_template":"", tmp_id_str
);
2300 expr
->expr
= mputprintf(expr
->expr
,
2301 "%s = %s.%s();\n", global_id
.c_str(),
2302 tmp_id2_str
, isbound
? "is_bound" : "is_present");
2303 Free(tmp_generalid_str
);
2304 tmp_generalid_str
= mcopystr(tmp_id2_str
);
2306 expr
->expr
= mputprintf(expr
->expr
,
2310 expr
->expr
= mputprintf(expr
->expr
,
2311 "switch (%s.get_selection()) {\n"
2312 "case OPTIONAL_UNBOUND:\n"
2313 "case OPTIONAL_OMIT:\n"
2319 tmp_id_str
, global_id
.c_str());
2320 Free(tmp_generalid_str
);
2321 tmp_generalid_str
= mcopystr(tmp_id_str
);
2323 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2324 closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2325 Free(closing_brackets
);
2326 closing_brackets
= closing_brackets2
;
2328 const string
& tmp_id2
= module
->get_temporary_id();
2329 const char *tmp_id2_str
= tmp_id2
.c_str();
2330 expr
->expr
= mputprintf(expr
->expr
,
2331 "const %s%s& %s = (const %s%s&) %s;\n",
2332 next_t
->get_genname_value(module
).c_str(),
2333 is_template
?"_template":"", tmp_id2_str
,
2334 next_t
->get_genname_value(module
).c_str(),
2335 is_template
?"_template":"", tmp_id_str
);
2337 expr
->expr
= mputprintf(expr
->expr
,
2338 "%s = %s.is_bound();\n", global_id
.c_str(),
2340 Free(tmp_generalid_str
);
2341 tmp_generalid_str
= mcopystr(tmp_id2_str
);
2344 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2345 expstring_t closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2346 Free(closing_brackets
);
2347 closing_brackets
= closing_brackets2
;
2349 const string
& tmp_id
= module
->get_temporary_id();
2350 const char *tmp_id_str
= tmp_id
.c_str();
2351 expr
->expr
= mputprintf(expr
->expr
,
2352 "const %s%s& %s = %s.%s();\n",
2353 next_t
->get_genname_value(module
).c_str(),
2354 is_template
?"_template":"", tmp_id_str
, tmp_generalid_str
,
2355 id
.get_name().c_str());
2357 expr
->expr
= mputprintf(expr
->expr
,
2358 "%s = %s.%s();\n", global_id
.c_str(),
2359 tmp_id_str
, isbound
||(i
!=(nof_refs
-1)) ? "is_bound" : "is_present");
2360 Free(tmp_generalid_str
);
2361 tmp_generalid_str
= mcopystr(tmp_id_str
);
2366 case Ttcn::FieldOrArrayRef::ARRAY_REF
: {
2367 Type
*embedded_type
= 0;
2368 bool is_string
= true;
2369 bool is_string_element
= false;
2370 switch (t
->typetype
) {
2373 embedded_type
= t
->u
.seof
.ofType
;
2377 embedded_type
= t
->u
.array
.element_type
;
2387 case T_NUMERICSTRING
:
2388 case T_PRINTABLESTRING
:
2389 case T_TELETEXSTRING
:
2390 case T_VIDEOTEXSTRING
:
2392 case T_GRAPHICSTRING
:
2393 case T_VISIBLESTRING
:
2394 case T_GENERALSTRING
:
2395 case T_UNIVERSALSTRING
:
2398 case T_GENERALIZEDTIME
:
2399 case T_OBJECTDESCRIPTOR
:
2400 if (subrefs
->refers_to_string_element()) {
2401 FATAL_ERROR("Type::generate_code_isbound()");
2403 subrefs
->set_string_element_ref();
2404 // string elements have the same type as the string itself
2406 is_string_element
= true;
2410 FATAL_ERROR("Type::generate_code_isbound()");
2413 next_t
= embedded_type
;
2415 // check the index value
2416 Value
*index_value
= ref
->get_val();
2417 Value
*v_last
= index_value
->get_value_refd_last();
2419 const string
& tmp_index_id
= module
->get_temporary_id();
2420 const char *tmp_index_id_str
= tmp_index_id
.c_str();
2421 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2423 expstring_t closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2424 Free(closing_brackets
);
2425 closing_brackets
= closing_brackets2
;
2427 expr
->expr
= mputprintf(expr
->expr
, "const int %s = ", tmp_index_id_str
);
2428 v_last
->generate_code_expr_mandatory(expr
);
2429 expr
->expr
= mputstr(expr
->expr
, ";\n");
2430 expr
->expr
= mputprintf(expr
->expr
, "%s = (%s >= 0) && (%s.%s > %s);\n",
2431 global_id
.c_str(), tmp_index_id_str
, tmp_generalid_str
,
2432 is_string
? "lengthof()": ( is_template
? "n_elem()" : "size_of()" ),
2434 expr
->expr
= mputprintf(expr
->expr
, "if(%s) {\n",global_id
.c_str());
2436 closing_brackets2
= mprintf("}\n%s", closing_brackets
);
2437 Free(closing_brackets
);
2438 closing_brackets
= closing_brackets2
;
2440 const string
& tmp_id
= module
->get_temporary_id();
2441 const char *tmp_id_str
= tmp_id
.c_str();
2443 if (is_string_element
) {
2444 expr
->expr
= mputprintf(expr
->expr
,
2445 "%s = %s[%s].%s();\n", global_id
.c_str(),
2446 tmp_generalid_str
, tmp_index_id_str
,
2447 isbound
||(i
!=(nof_refs
-1)) ? "is_bound" : "is_present");
2450 expr
->expr
= mputprintf(expr
->expr
,
2451 "const %s& %s = %s[%s];\n",
2452 next_t
->get_genname_template(module
).c_str(),
2453 tmp_id_str
, tmp_generalid_str
,
2456 expr
->expr
= mputprintf(expr
->expr
,
2457 "const %s%s& %s = %s[%s];\n",
2458 next_t
->get_genname_value(module
).c_str(),
2459 is_template
?"_template":"", tmp_id_str
, tmp_generalid_str
,
2463 expr
->expr
= mputprintf(expr
->expr
,
2464 "%s = %s.%s();\n", global_id
.c_str(), tmp_id_str
,
2465 isbound
||(i
!=(nof_refs
-1)) ? "is_bound" : "is_present");
2468 Free(tmp_generalid_str
);
2469 tmp_generalid_str
= mcopystr(tmp_id_str
);
2471 // change t to the embedded type
2475 FATAL_ERROR("Type::generate_code_isbound(): invalid reference type");
2479 Free(tmp_generalid_str
);
2480 expr
->expr
= mputstr(expr
->expr
, closing_brackets
);
2481 Free(closing_brackets
);
2484 string
Type::get_optimize_attribute()
2488 vector
<SingleWithAttrib
> const &real_attribs
2489 = w_attrib_path
->get_real_attrib();
2490 for (size_t i
= 0; i
< real_attribs
.size(); i
++) {
2491 SingleWithAttrib
* temp_single
= real_attribs
[i
];
2492 if (temp_single
->get_attribKeyword()
2493 == SingleWithAttrib::AT_EXTENSION
2494 && (!temp_single
->get_attribQualifiers()
2495 || (temp_single
->get_attribQualifiers()
2496 ->get_nof_qualifiers() == 0)))
2498 const string
& spec
= temp_single
->get_attribSpec().get_spec();
2499 // TODO: use a real parser to allow whitespaces, etc.
2500 if (spec
.find("optimize:")==0 && spec
.size()>9)
2502 string spec_optimize_for_what
= spec
.substr(9);
2503 return spec_optimize_for_what
;
2511 string
Type::get_sourcefile_attribute()
2515 vector
<SingleWithAttrib
> const &real_attribs
2516 = w_attrib_path
->get_real_attrib();
2518 for (size_t i
= 0; i
< real_attribs
.size(); i
++) {
2519 SingleWithAttrib
* temp_single
= real_attribs
[i
];
2520 if (temp_single
->get_attribKeyword()
2521 == SingleWithAttrib::AT_EXTENSION
2522 && (!temp_single
->get_attribQualifiers()
2523 || (temp_single
->get_attribQualifiers()
2524 ->get_nof_qualifiers() == 0)))
2526 const string
& spec
= temp_single
->get_attribSpec().get_spec();
2527 if (spec
.find("sourcefile:")==0 && spec
.size()>11)
2529 string spec_filename
= spec
.substr(11);
2530 // TODO: check if string can be a valid filename
2531 return spec_filename
;
2539 bool Type::has_done_attribute()
2543 vector
<SingleWithAttrib
> const &real_attribs
2544 = w_attrib_path
->get_real_attrib();
2546 for (size_t i
= 0; i
< real_attribs
.size(); i
++) {
2547 SingleWithAttrib
* temp_single
= real_attribs
[i
];
2548 if (temp_single
->get_attribKeyword()
2549 == SingleWithAttrib::AT_EXTENSION
2550 && (!temp_single
->get_attribQualifiers()
2551 || (temp_single
->get_attribQualifiers()
2552 ->get_nof_qualifiers() == 0))
2553 && temp_single
->get_attribSpec().get_spec() == "done")
2562 void Type::generate_code_object(const_def
*cdef
, Scope
*p_scope
,
2563 const string
& name
, const char *prefix
, bool is_template
)
2566 if (is_template
) type_name
= get_genname_template(p_scope
);
2567 else type_name
= get_genname_value(p_scope
);
2568 const char *name_str
= name
.c_str();
2569 const char *type_name_str
= type_name
.c_str();
2571 cdef
->decl
= mputprintf(cdef
->decl
, "extern const %s& %s;\n",
2572 type_name_str
, name_str
);
2573 cdef
->def
= mputprintf(cdef
->def
, "static %s %s%s;\n"
2574 "const %s& %s = %s%s;\n", type_name_str
, prefix
, name_str
,
2575 type_name_str
, name_str
, prefix
, name_str
);
2577 cdef
->decl
= mputprintf(cdef
->decl
, "extern %s %s;\n",
2578 type_name_str
, name_str
);
2579 cdef
->def
= mputprintf(cdef
->def
, "%s %s;\n",
2580 type_name_str
, name_str
);
2584 void Type::generate_code_object(const_def
*cdef
, GovernedSimple
*p_setting
)
2586 bool is_template
= false;
2587 switch (p_setting
->get_st()) {
2594 FATAL_ERROR("Type::generate_code_object()");
2596 if (p_setting
->get_err_descr()) {
2597 cdef
->def
= p_setting
->get_err_descr()->generate_code_str(cdef
->def
,
2598 p_setting
->get_genname_prefix() + p_setting
->get_genname_own());
2600 generate_code_object(cdef
, p_setting
->get_my_scope(),
2601 p_setting
->get_genname_own(), p_setting
->get_genname_prefix(),
2605 void Type::generate_json_schema(JSON_Tokenizer
& json
, bool embedded
, bool as_value
)
2607 // add a new property for the type if it has its own definition
2609 json
.put_next_token(JSON_TOKEN_NAME
, get_dispname().c_str());
2612 // create an object containing the type's schema
2613 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2615 // if this is a field of a record/set/union with an alias, the field's
2616 // original name must be stored ("originalName" property), it also needs to be
2617 // stored if this is a field of a union with the "as value" coding instruction
2618 if (ownertype
== OT_COMP_FIELD
) {
2619 CompField
* cf
= static_cast<CompField
*>(owner
);
2620 if(as_value
|| (cf
->get_type()->jsonattrib
!= NULL
2621 && cf
->get_type()->jsonattrib
->alias
!= NULL
)) {
2622 json
.put_next_token(JSON_TOKEN_NAME
, "originalName");
2623 char* field_str
= mprintf("\"%s\"", cf
->get_name().get_dispname().c_str());
2624 json
.put_next_token(JSON_TOKEN_STRING
, field_str
);
2628 // if the parent is a union with the "as value" coding instruction AND the field
2629 // has an alias, then the alias needs to be stored as well ("unusedAlias" property)
2630 if (as_value
&& cf
->get_type()->jsonattrib
!= NULL
2631 && cf
->get_type()->jsonattrib
->alias
!= NULL
) {
2632 json
.put_next_token(JSON_TOKEN_NAME
, "unusedAlias");
2633 char* alias_str
= mprintf("\"%s\"", cf
->get_type()->jsonattrib
->alias
);
2634 json
.put_next_token(JSON_TOKEN_STRING
, alias_str
);
2639 // get the type at the end of the reference chain
2640 Type
* last
= get_type_refd_last();
2642 // if the type has its own definition and it's embedded in another type, then
2643 // its schema already exists, only add a reference to it
2644 if (embedded
&& (last
->ownertype
== OT_TYPE_DEF
/* TTCN-3 type definition */
2645 || last
->ownertype
== OT_TYPE_ASS
/* ASN.1 type assignment */ )) {
2646 json
.put_next_token(JSON_TOKEN_NAME
, "$ref");
2647 char* ref_str
= mprintf("\"#/definitions/%s/%s\"",
2648 last
->my_scope
->get_scope_mod()->get_modid().get_dispname().c_str(),
2649 last
->get_dispname().c_str());
2650 json
.put_next_token(JSON_TOKEN_STRING
, ref_str
);
2653 // generate the schema for the referenced type
2654 switch (last
->typetype
) {
2656 // use the JSON boolean type
2657 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2658 json
.put_next_token(JSON_TOKEN_STRING
, "\"boolean\"");
2662 // use the JSON integer type
2663 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2664 json
.put_next_token(JSON_TOKEN_STRING
, "\"integer\"");
2667 // any of: JSON number or the special values as strings (in an enum)
2668 json
.put_next_token(JSON_TOKEN_NAME
, "anyOf");
2669 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2670 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2671 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2672 json
.put_next_token(JSON_TOKEN_STRING
, "\"number\"");
2673 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2674 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2675 json
.put_next_token(JSON_TOKEN_NAME
, "enum");
2676 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2677 json
.put_next_token(JSON_TOKEN_STRING
, "\"not_a_number\"");
2678 json
.put_next_token(JSON_TOKEN_STRING
, "\"infinity\"");
2679 json
.put_next_token(JSON_TOKEN_STRING
, "\"-infinity\"");
2680 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2681 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2682 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2688 // use the JSON string type and add a pattern to only allow bits or hex digits
2689 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2690 json
.put_next_token(JSON_TOKEN_STRING
, "\"string\"");
2691 json
.put_next_token(JSON_TOKEN_NAME
, "pattern");
2692 json
.put_next_token(JSON_TOKEN_STRING
,
2693 (last
->typetype
== T_OSTR
) ? "\"^([0-9A-Fa-f][0-9A-Fa-f])*$\"" :
2694 ((last
->typetype
== T_HSTR
) ? "\"^[0-9A-Fa-f]*$\"" : "\"^[01]*$\""));
2697 case T_NUMERICSTRING
:
2698 case T_PRINTABLESTRING
:
2700 case T_VISIBLESTRING
:
2701 // use the JSON string type and add a "subType" property to distinguish it from
2702 // universal charstring types
2703 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2704 json
.put_next_token(JSON_TOKEN_STRING
, "\"string\"");
2705 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2706 json
.put_next_token(JSON_TOKEN_STRING
, "\"charstring\"");
2709 case T_GENERALSTRING
:
2710 case T_UNIVERSALSTRING
:
2713 case T_GRAPHICSTRING
:
2714 case T_TELETEXSTRING
:
2715 case T_VIDEOTEXSTRING
:
2716 // use the JSON string type and add a "subType" property to distinguish it from
2718 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2719 json
.put_next_token(JSON_TOKEN_STRING
, "\"string\"");
2720 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2721 json
.put_next_token(JSON_TOKEN_STRING
, "\"universal charstring\"");
2724 // enumerate the possible values
2725 json
.put_next_token(JSON_TOKEN_NAME
, "enum");
2726 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2727 json
.put_next_token(JSON_TOKEN_STRING
, "\"none\"");
2728 json
.put_next_token(JSON_TOKEN_STRING
, "\"pass\"");
2729 json
.put_next_token(JSON_TOKEN_STRING
, "\"inconc\"");
2730 json
.put_next_token(JSON_TOKEN_STRING
, "\"fail\"");
2731 json
.put_next_token(JSON_TOKEN_STRING
, "\"error\"");
2732 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2736 // enumerate the possible values
2737 json
.put_next_token(JSON_TOKEN_NAME
, "enum");
2738 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2739 for (size_t i
= 0; i
< u
.enums
.eis
->get_nof_eis(); ++i
) {
2740 char* enum_str
= mprintf("\"%s\"", get_ei_byIndex(i
)->get_name().get_dispname().c_str());
2741 json
.put_next_token(JSON_TOKEN_STRING
, enum_str
);
2744 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2749 last
->generate_json_schema_array(json
);
2755 last
->generate_json_schema_record(json
);
2760 last
->generate_json_schema_union(json
);
2763 FATAL_ERROR("Type::generate_json_schema");
2767 // insert default value (if any)
2768 if (jsonattrib
!= NULL
&& jsonattrib
->default_value
!= NULL
) {
2769 json
.put_next_token(JSON_TOKEN_NAME
, "default");
2770 switch (last
->typetype
) {
2772 json
.put_next_token((jsonattrib
->default_value
[0] == 't') ?
2773 JSON_TOKEN_LITERAL_TRUE
: JSON_TOKEN_LITERAL_FALSE
);
2777 if (jsonattrib
->default_value
[0] != 'n' && jsonattrib
->default_value
[0] != 'i'
2778 && jsonattrib
->default_value
[1] != 'i') {
2779 json
.put_next_token(JSON_TOKEN_NUMBER
, jsonattrib
->default_value
);
2782 // no break, insert the special float values as strings
2790 char* default_str
= mprintf("\"%s\"", jsonattrib
->default_value
);
2791 json
.put_next_token(JSON_TOKEN_STRING
, default_str
);
2795 FATAL_ERROR("Type::generate_json_schema");
2799 // end of type's schema
2800 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2803 void Type::generate_json_schema_array(JSON_Tokenizer
& json
)
2805 // use the JSON array type
2806 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2807 json
.put_next_token(JSON_TOKEN_STRING
, "\"array\"");
2809 if (typetype
!= T_ARRAY
) {
2810 // use the "subType" property to distinguish 'record of' from 'set of'
2811 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2812 json
.put_next_token(JSON_TOKEN_STRING
, (typetype
== T_SEQOF
) ?
2813 "\"record of\"" : "\"set of\"");
2815 // set the number of elements for arrays
2816 char* size_str
= mprintf("%lu", get_nof_comps());
2817 json
.put_next_token(JSON_TOKEN_NAME
, "minItems");
2818 json
.put_next_token(JSON_TOKEN_NUMBER
, size_str
);
2819 json
.put_next_token(JSON_TOKEN_NAME
, "maxItems");
2820 json
.put_next_token(JSON_TOKEN_NUMBER
, size_str
);
2824 // set the element type
2825 json
.put_next_token(JSON_TOKEN_NAME
, "items");
2827 // pass the tokenizer to the elements' type object to insert its schema
2828 get_ofType()->generate_json_schema(json
, true, false);
2831 void Type::generate_json_schema_record(JSON_Tokenizer
& json
)
2833 // use the JSON object type
2834 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2835 json
.put_next_token(JSON_TOKEN_STRING
, "\"object\"");
2837 // use the "subType" property to distinguish records from sets
2838 json
.put_next_token(JSON_TOKEN_NAME
, "subType");
2839 json
.put_next_token(JSON_TOKEN_STRING
, (typetype
== T_SEQ_T
|| typetype
== T_SEQ_A
) ?
2840 "\"record\"" : "\"set\"");
2843 json
.put_next_token(JSON_TOKEN_NAME
, "properties");
2844 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2845 size_t field_count
= get_nof_comps();
2846 bool has_non_optional
= false;
2847 for (size_t i
= 0; i
< field_count
; ++i
) {
2848 Type
* field
= get_comp_byIndex(i
)->get_type();
2850 // use the field's alias if it has one
2851 json
.put_next_token(JSON_TOKEN_NAME
,
2852 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
2853 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_dispname().c_str());
2855 // optional fields can also get the JSON null value
2856 if (get_comp_byIndex(i
)->get_is_optional()) {
2857 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2858 json
.put_next_token(JSON_TOKEN_NAME
, "anyOf");
2859 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2860 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2861 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2862 json
.put_next_token(JSON_TOKEN_STRING
, "\"null\"");
2863 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2864 } else if (!has_non_optional
) {
2865 has_non_optional
= true;
2868 // pass the tokenizer to the field's type to insert its schema
2869 field
->generate_json_schema(json
, true, false);
2871 // for optional fields: specify the presence of the "omit as null" coding instruction
2872 // and close structures
2873 if (get_comp_byIndex(i
)->get_is_optional()) {
2874 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2875 json
.put_next_token(JSON_TOKEN_NAME
, "omitAsNull");
2876 json
.put_next_token((field
->jsonattrib
!= NULL
&& field
->jsonattrib
->omit_as_null
) ?
2877 JSON_TOKEN_LITERAL_TRUE
: JSON_TOKEN_LITERAL_FALSE
);
2878 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2882 // end of properties
2883 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2885 // do not accept additional fields
2886 json
.put_next_token(JSON_TOKEN_NAME
, "additionalProperties");
2887 json
.put_next_token(JSON_TOKEN_LITERAL_FALSE
);
2889 // set the field order
2890 if (field_count
> 1) {
2891 json
.put_next_token(JSON_TOKEN_NAME
, "fieldOrder");
2892 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2893 for (size_t i
= 0; i
< field_count
; ++i
) {
2894 Type
* field
= get_comp_byIndex(i
)->get_type();
2895 // use the field's alias if it has one
2896 char* field_str
= mprintf("\"%s\"",
2897 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
2898 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_dispname().c_str());
2899 json
.put_next_token(JSON_TOKEN_STRING
, field_str
);
2902 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2905 // set the required (non-optional) fields
2906 if (has_non_optional
) {
2907 json
.put_next_token(JSON_TOKEN_NAME
, "required");
2908 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2909 for (size_t i
= 0; i
< field_count
; ++i
) {
2910 if (!get_comp_byIndex(i
)->get_is_optional()) {
2911 Type
* field
= get_comp_byIndex(i
)->get_type();
2912 // use the field's alias if it has one
2913 char* field_str
= mprintf("\"%s\"",
2914 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
2915 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_dispname().c_str());
2916 json
.put_next_token(JSON_TOKEN_STRING
, field_str
);
2920 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2924 void Type::generate_json_schema_union(JSON_Tokenizer
& json
)
2926 // use an "anyOf" structure containing the union's alternatives
2927 json
.put_next_token(JSON_TOKEN_NAME
, "anyOf");
2928 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2930 for (size_t i
= 0; i
< get_nof_comps(); ++i
) {
2931 Type
* field
= get_comp_byIndex(i
)->get_type();
2933 if (jsonattrib
!= NULL
&& jsonattrib
->as_value
) {
2934 // only add the alternative's schema
2935 field
->generate_json_schema(json
, true, true);
2937 // use a JSON object with one key-value pair for each alternative
2938 // the schema is the same as a record's with one field
2939 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2941 json
.put_next_token(JSON_TOKEN_NAME
, "type");
2942 json
.put_next_token(JSON_TOKEN_STRING
, "\"object\"");
2944 json
.put_next_token(JSON_TOKEN_NAME
, "properties");
2945 json
.put_next_token(JSON_TOKEN_OBJECT_START
);
2947 // use the alternative's alias if it has one
2948 json
.put_next_token(JSON_TOKEN_NAME
,
2949 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
2950 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_dispname().c_str());
2952 // let the alternative's type insert its schema
2953 field
->generate_json_schema(json
, true, false);
2955 // continue the schema for the record with one field
2956 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2958 json
.put_next_token(JSON_TOKEN_NAME
, "additionalProperties");
2959 json
.put_next_token(JSON_TOKEN_LITERAL_FALSE
);
2961 // the one field is non-optional
2962 json
.put_next_token(JSON_TOKEN_NAME
, "required");
2963 json
.put_next_token(JSON_TOKEN_ARRAY_START
);
2965 // use the alternative's alias here as well
2966 char* field_str
= mprintf("\"%s\"",
2967 (field
->jsonattrib
!= NULL
&& field
->jsonattrib
->alias
!= NULL
) ?
2968 field
->jsonattrib
->alias
: get_comp_byIndex(i
)->get_name().get_dispname().c_str());
2969 json
.put_next_token(JSON_TOKEN_STRING
, field_str
);
2972 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2974 json
.put_next_token(JSON_TOKEN_OBJECT_END
);
2978 // close the "anyOf" array
2979 json
.put_next_token(JSON_TOKEN_ARRAY_END
);
2982 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2984 } // namespace Common