Sync with 5.3.0
[deliverable/titan.core.git] / compiler2 / Type_codegen.cc
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"
9 #include "Type.hh"
10 #include "CompField.hh"
11 #include "EnumItem.hh"
12 #include "SigParam.hh"
13 #include "main.hh"
14
15 #include "enum.h"
16 #include "record.h"
17 #include "union.h"
18 #include "record_of.h"
19 #include "functionref.h"
20
21
22 #include "ttcn3/Ttcnstuff.hh"
23 #include "ttcn3/ArrayDimensions.hh"
24 #include "ttcn3/Attributes.hh"
25 #include "ttcn3/signature.h"
26 #include "XerAttributes.hh"
27
28 #include "asn1/TableConstraint.hh"
29 #include "asn1/Object.hh"
30 #include "asn1/Tag.hh"
31 #include "asn1/Ref.hh"
32
33 #include "CodeGenHelper.hh"
34
35 #include "../common/JSON_Tokenizer.hh"
36
37 namespace Common {
38
39 using Asn::Tags;
40 using Ttcn::SingleWithAttrib;
41
42 void Type::generate_code(output_struct *target)
43 {
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);
53 } else {
54 switch(typetype) {
55 case T_ENUM_A:
56 case T_ENUM_T:
57 generate_code_Enum(target);
58 break;
59 case T_CHOICE_A:
60 case T_CHOICE_T:
61 case T_OPENTYPE:
62 case T_ANYTYPE:
63 generate_code_Choice(target);
64 break;
65 case T_SEQ_A:
66 case T_SEQ_T:
67 case T_SET_A:
68 case T_SET_T:
69 generate_code_Se(target);
70 break;
71 case T_SEQOF:
72 case T_SETOF:
73 generate_code_SeOf(target);
74 break;
75 case T_PORT:
76 u.port->generate_code(target);
77 break;
78 case T_ARRAY:
79 generate_code_Array(target);
80 break;
81 case T_SIGNATURE:
82 generate_code_Signature(target);
83 break;
84 case T_FUNCTION:
85 case T_ALTSTEP:
86 case T_TESTCASE:
87 generate_code_Fat(target);
88 break;
89 default:
90 generate_code_alias(target);
91 break;
92 } // switch
93 }
94 generate_code_embedded_after(target);
95 if (!is_asn1()) {
96 if (has_done_attribute()) generate_code_done(target);
97 if (sub_type) sub_type->generate_code(*target);
98 }
99 }
100
101 void Type::generate_code_include(const string& sourcefile, output_struct *target)
102 {
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,
106 "class %s;\n"
107 "class %s_template;\n",
108 name, name);
109
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());
114 }
115
116 void Type::generate_code_embedded_before(output_struct *target)
117 {
118 switch (typetype) {
119 case T_SEQ_A:
120 case T_SEQ_T:
121 case T_SET_A:
122 case T_SET_T: {
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()
131 )
132 );
133 CodeGenHelper::GetInstance().finalize_generation(
134 cf->get_type()->get_type_refd_last()
135 );
136 // escape from recursion loops
137 if (code_generated) break;
138 }
139 }
140 break; }
141 case T_REFD:
142 case T_SELTYPE:
143 case T_REFDSPEC:
144 case T_OCFT: {
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);
151 break; }
152 case T_SIGNATURE:
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);
159 }
160 }
161 if (u.signature.return_type)
162 u.signature.return_type->generate_code(target);
163 break;
164 case T_ARRAY:
165 u.array.element_type->generate_code(target);
166 break;
167 default:
168 break;
169 }
170 }
171
172 void Type::generate_code_embedded_after(output_struct *target)
173 {
174 switch (typetype) {
175 case T_SEQ_A:
176 case T_SEQ_T:
177 case T_SET_A:
178 case T_SET_T: {
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);
187 }
188 }
189 break; }
190 case T_ANYTYPE:
191 case T_CHOICE_A:
192 case T_CHOICE_T: {
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);
198 }
199 break; }
200 case T_OPENTYPE:
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);
207 }
208 break;
209 case T_SEQOF:
210 case T_SETOF:
211 // generate code for the embedded type
212 if (!u.seof.ofType->is_pure_refd()) u.seof.ofType->generate_code(target);
213 break;
214 case T_FUNCTION:
215 case T_ALTSTEP:
216 case T_TESTCASE: {
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);
221 }
222 break; }
223 default:
224 break;
225 }
226 }
227
228 void Type::generate_code_typedescriptor(output_struct *target)
229 {
230 bool force_xer = false;
231 switch (get_type_refd_last()->typetype) {
232 case T_PORT:
233 case T_SIGNATURE:
234 // do not generate any type descriptor for these non-data types
235 return;
236 case T_ARRAY:
237 // no force xer
238 break;
239
240 default:
241 switch (ownertype) {
242 case OT_TYPE_ASS:
243 case OT_TYPE_DEF:
244 case OT_COMP_FIELD:
245 case OT_RECORD_OF:
246 case OT_REF_SPEC:
247 force_xer = has_encoding(CT_XER); // && (is_ref() || (xerattrib && !xerattrib->empty()));
248 break;
249 default:
250 break;
251 } // switch(ownertype)
252 break;
253 } // switch
254
255 const string& gennameown = get_genname_own();
256 const char *gennameown_str = gennameown.c_str();
257 const string& gennametypedescriptor = get_genname_typedescriptor(my_scope);
258 //printf("generate_code_typedescriptor(%s)\n", gennameown_str);
259
260 // FIXME: force_xer should be elminated. if a type needs a descriptor,
261 // it should say so via get_genname_typedescriptor()
262
263 /* genname{type,ber,raw,text,xer}descriptor == gennameown is true if
264 * the type needs its own {type,ber,raw,text,xer}descriptor
265 * and can't use the descriptor of one of the built-in types.
266 */
267 if (gennametypedescriptor == gennameown
268 || force_xer) {
269 // the type has its own type descriptor
270 bool generate_ber = has_encoding(CT_BER) && enable_ber();
271 const string& gennameberdescriptor = get_genname_berdescriptor();
272 if (generate_ber && gennameberdescriptor == gennameown)
273 generate_code_berdescriptor(target);
274
275 bool generate_raw = has_encoding(CT_RAW) && enable_raw();
276 const string& gennamerawdescriptor = get_genname_rawdescriptor();
277 if (generate_raw && gennamerawdescriptor == gennameown)
278 generate_code_rawdescriptor(target);
279
280 bool generate_text = has_encoding(CT_TEXT) && enable_text();
281 const string& gennametextdescriptor = get_genname_textdescriptor();
282 if (generate_text && gennametextdescriptor == gennameown)
283 generate_code_textdescriptor(target);
284
285 bool generate_xer = has_encoding(CT_XER) && enable_xer();
286 const string& gennamexerdescriptor = get_genname_xerdescriptor();
287 if (generate_xer && gennamexerdescriptor == gennameown)
288 generate_code_xerdescriptor(target);
289 else target->source.global_vars=mputprintf(target->source.global_vars,
290 "// No XER for %s\n", gennamexerdescriptor.c_str());
291
292 const string& gennamejsondescriptor = get_genname_jsondescriptor();
293 bool generate_json = has_encoding(CT_JSON) && enable_json() &&
294 gennamejsondescriptor == gennameown;
295 if (generate_json) {
296 generate_code_jsondescriptor(target);
297 }
298
299 // the type descriptor must be always exported.
300 // embedded (possibly unnamed) types can be referenced from other modules
301 // using field/array sub-references
302 target->header.global_vars = mputprintf(target->header.global_vars,
303 "extern const TTCN_Typedescriptor_t %s_descr_;\n", gennameown_str);
304 target->source.global_vars = mputprintf(target->source.global_vars,
305 "const TTCN_Typedescriptor_t %s_descr_ = { \"%s\", ", gennameown_str,
306 get_fullname().c_str());
307
308 if(generate_ber)
309 target->source.global_vars=mputprintf
310 (target->source.global_vars,
311 "&%s_ber_, ", gennameberdescriptor.c_str());
312 else
313 target->source.global_vars=mputstr
314 (target->source.global_vars, "NULL, ");
315
316 if (generate_raw)
317 target->source.global_vars=mputprintf
318 (target->source.global_vars,
319 "&%s_raw_, ", gennamerawdescriptor.c_str());
320 else
321 target->source.global_vars=mputstr
322 (target->source.global_vars, "NULL, ");
323
324 if (generate_text)
325 target->source.global_vars=mputprintf
326 (target->source.global_vars,
327 "&%s_text_, ", gennametextdescriptor.c_str());
328 else
329 target->source.global_vars=mputstr
330 (target->source.global_vars, "NULL, ");
331
332 if (generate_xer)
333 target->source.global_vars = mputprintf(target->source.global_vars,
334 "&%s_xer_, ", gennamexerdescriptor.c_str());
335 else
336 target->source.global_vars = mputprintf(target->source.global_vars,
337 "NULL, ");
338
339 if (generate_json) {
340 target->source.global_vars = mputprintf(target->source.global_vars,
341 "&%s_json_, ", gennamejsondescriptor.c_str());
342 } else {
343 switch(get_type_refd_last()->typetype) {
344 case T_BOOL:
345 case T_INT:
346 case T_INT_A:
347 case T_REAL:
348 case T_BSTR:
349 case T_BSTR_A:
350 case T_HSTR:
351 case T_OSTR:
352 case T_CSTR:
353 case T_USTR:
354 case T_UTF8STRING:
355 case T_NUMERICSTRING:
356 case T_PRINTABLESTRING:
357 case T_TELETEXSTRING:
358 case T_VIDEOTEXSTRING:
359 case T_IA5STRING:
360 case T_GRAPHICSTRING:
361 case T_VISIBLESTRING:
362 case T_GENERALSTRING:
363 case T_UNIVERSALSTRING:
364 case T_BMPSTRING:
365 case T_VERDICT:
366 case T_NULL:
367 case T_OID:
368 case T_ROID:
369 case T_ANY:
370 // use predefined JSON descriptors instead of null pointers for basic types
371 target->source.global_vars = mputprintf(target->source.global_vars,
372 "&%s_json_, ", gennamejsondescriptor.c_str());
373 break;
374 case T_ENUM_T:
375 case T_ENUM_A:
376 // use a predefined JSON descriptor for enumerated types
377 target->source.global_vars = mputstr(target->source.global_vars,
378 "&ENUMERATED_json_, ");
379 break;
380 default:
381 target->source.global_vars = mputstr(target->source.global_vars,
382 "NULL, ");
383 }
384 }
385
386 if (T_SEQOF == get_type_refd_last()->typetype ||
387 T_SETOF == get_type_refd_last()->typetype) {
388 target->source.global_vars=mputprintf(target->source.global_vars,
389 "&%s_descr_, ", get_type_refd_last()->u.seof.ofType->get_genname_typedescriptor(my_scope).c_str());
390 }
391 else {
392 target->source.global_vars = mputstr(target->source.global_vars,
393 "NULL, ");
394 }
395
396 target->source.global_vars=mputprintf(target->source.global_vars,
397 "TTCN_Typedescriptor_t::%s };\n"
398 #ifndef NDEBUG
399 "\n"
400 #endif
401 , get_genname_typedescr_asnbasetype());
402 } else {
403 // the type uses the type descriptor of another type
404 if (needs_alias()) {
405 // we need to generate an aliased type descriptor only if the type is
406 // directly accessible by the user
407 target->header.global_vars = mputprintf(target->header.global_vars,
408 "extern const TTCN_Typedescriptor_t& %s_descr_;\n", gennameown_str);
409 target->source.global_vars = mputprintf(target->source.global_vars,
410 "const TTCN_Typedescriptor_t& %s_descr_ = %s_descr_;\n",
411 gennameown_str, gennametypedescriptor.c_str());
412 }
413 #ifndef NDEBUG
414 else {
415 target->source.global_vars = mputprintf( target->source.global_vars,
416 "// %s_descr_ not needed, use %s_descr_\n",
417 gennameown_str, gennametypedescriptor.c_str());
418 } // if(needs_alias())
419 #endif
420
421 } // if (gennameown == gennametypedescriptor)
422 }
423
424 void Type::generate_code_berdescriptor(output_struct *target)
425 {
426 const char *gennameown_str = get_genname_own().c_str();
427 char *str = mprintf("static const ASN_Tag_t %s_tag_[] = { ",
428 gennameown_str);
429 Tags *joinedtags = build_tags_joined();
430 size_t tagarraysize = joinedtags->get_nof_tags();
431 for (size_t i = 0; i < tagarraysize; i++) {
432 if (i > 0) str = mputstr(str, ", ");
433 Tag *t_tag = joinedtags->get_tag_byIndex(i);
434 str = mputprintf(str, "{ %s, %su }", t_tag->get_tagclass_str(),
435 Int2string(t_tag->get_tagvalue()).c_str());
436 }
437 delete joinedtags;
438 str = mputstr(str, "};\n");
439 target->source.global_vars = mputstr(target->source.global_vars, str);
440 Free(str);
441 target->header.global_vars = mputprintf(target->header.global_vars,
442 "extern const ASN_BERdescriptor_t %s_ber_;\n", gennameown_str);
443 target->source.global_vars = mputprintf(target->source.global_vars,
444 "const ASN_BERdescriptor_t %s_ber_ = { %luu, %s_tag_ };\n",
445 gennameown_str, (unsigned long)tagarraysize, gennameown_str);
446 }
447
448 static const char* whitespace_action[3] = {"PRESERVE", "REPLACE", "COLLAPSE"};
449
450 extern void change_name(string &name, XerAttributes::NameChange change);
451 // implemented in Type_chk.cc
452
453 void Type::generate_code_xerdescriptor(output_struct* target)
454 {
455 const char *gennameown_str = get_genname_own().c_str();
456 target->header.global_vars = mputprintf(target->header.global_vars,
457 "extern const XERdescriptor_t %s_xer_;\n", gennameown_str);
458 string last_s;
459
460 Type *ot = this;
461 for(;;) {
462 string full_s = ot->get_fullname();
463 size_t dot_pos = full_s.rfind('.');
464 if (full_s.size() == dot_pos) dot_pos = 0;
465 last_s = full_s.substr(dot_pos+1); // FIXME: may be better to use replace(pos, n, s)
466
467 if ('&'==last_s[0] // object class field ?
468 ||'<'==last_s[0]) { // <oftype> and the like
469 if (ot->is_ref()) {
470 ot = ot->get_type_refd();
471 /* Fetch the referenced type and use that. Do not use
472 * get_type_refd_last() here. In case of a record-of user-defined type:
473 * <ttcn>type integer MyInt; type record of MyInt MyRecof;</ttcn>
474 * we want "MyInt" and not "integer" */
475 continue;
476 }
477 else { // probably a built-in type, punt with the C++ class name
478 last_s = ot->get_genname_value(0);
479 break;
480 }
481 }
482 break;
483 }
484
485 // Name for basic XER which ignores all the EXER fanciness
486 string bxer_name(last_s);
487
488 long ns_index = -1;
489 //fprintf(stderr, "%2d gno='%s'\tfn='%s'\n", typetype, gennameown_str, last_s.c_str());
490 int atrib=0, any_atr=0, any_elem=0, base64=0, decimal=0, embed=0, list=0,
491 text=0, untagged=0, use_nil=0, use_number=0, use_order=0, use_qname=0,
492 use_type_attr=0, ws=0, has_1untag=0, form_qualified=0, any_from=0,
493 any_except=0, nof_ns_uris=0;
494 const char* dfe_str = 0;
495 char** ns_uris = 0;
496 char* oftype_descr_name = 0;
497 if (xerattrib) {
498 change_name(last_s, xerattrib->name_);
499
500 if (xerattrib->namespace_.uri && xerattrib->namespace_.prefix) {
501 ns_index = my_scope->get_scope_mod()->get_ns_index(
502 xerattrib->namespace_.prefix);
503 // This is known to have succeeded
504 }
505
506 any_atr = has_aa(xerattrib);
507 any_elem= has_ae(xerattrib);
508 atrib = xerattrib->attribute_;
509 base64 = xerattrib->base64_;
510 decimal = xerattrib->decimal_;
511 embed = xerattrib->embedValues_;
512 form_qualified = (xerattrib->form_ & XerAttributes::QUALIFIED)
513 || (xerattrib->element_); // a global element is always qualified
514 list = xerattrib->list_;
515 untagged= xerattrib->untagged_;
516 ws = xerattrib->whitespace_;
517 // only set TEXT if it has no TextToBeUsed (plain "text" for a bool)
518 text = xerattrib->num_text_ && xerattrib->text_->prefix == 0;
519 use_nil = xerattrib->useNil_;
520 use_number= xerattrib->useNumber_;
521 use_order = xerattrib->useOrder_;
522 use_qname = xerattrib->useQName_;
523 // In ASN.1, the use of a type identification attribute is optional
524 // (encoder's choice) for USE-UNION. However, TTCN-3 removes this choice:
525 // it is mandatory to use it when possible (valid choice for ASN.1 too).
526 use_type_attr = xerattrib->useType_ || xerattrib->useUnion_;
527
528 if (xerattrib->defaultValue_) {
529 Type *t = xerattrib->defaultValue_->get_my_governor();
530 dfe_str = xerattrib->defaultValue_->get_genname_own().c_str();
531 const_def cdef;
532 Code::init_cdef(&cdef);
533 t->generate_code_object(&cdef, xerattrib->defaultValue_);
534 cdef.init = xerattrib->defaultValue_->generate_code_init
535 (cdef.init, xerattrib->defaultValue_->get_lhs_name().c_str());
536 Code::merge_cdef(target, &cdef);
537 Code::free_cdef(&cdef);
538 }
539
540 if (any_elem) {
541 // data needed for "anyElement from ..." and "anyElement except ..." encoding instructions
542 any_from = xerattrib->anyElement_.type_ == NamespaceRestriction::FROM;
543 any_except = xerattrib->anyElement_.type_ == NamespaceRestriction::EXCEPT;
544 nof_ns_uris = xerattrib->anyElement_.nElements_;
545 ns_uris = xerattrib->anyElement_.uris_;
546 }
547 else if (any_atr) {
548 // data needed for "anyAttributes from ..." and "anyAttributes except ..." encoding instructions
549 any_from = xerattrib->anyAttributes_.type_ == NamespaceRestriction::FROM;
550 any_except = xerattrib->anyAttributes_.type_ == NamespaceRestriction::EXCEPT;
551 nof_ns_uris = xerattrib->anyAttributes_.nElements_;
552 ns_uris = xerattrib->anyAttributes_.uris_;
553 }
554 }
555 else if (ownertype == OT_COMP_FIELD
556 && parent_type && parent_type->xerattrib) {
557 //no xerattrib, this must be an element; apply element default
558 form_qualified = (parent_type->xerattrib->form_
559 & XerAttributes::ELEMENT_DEFAULT_QUALIFIED);
560 }
561
562 Type *last = get_type_refd_last();
563 has_1untag= last->is_secho() && last->u.secho.has_single_charenc; // does not come from xerattrib
564
565 /* If this is a string type whose grandparent is a record
566 * (containing a record-of (this)string) which has EMBED-VALUES,
567 * then reuse this string's any_element field in the XER descriptor
568 * to signal this (ANY-ELEMENT causes the tag to be omitted,
569 * which is what we want in EMBED-VALUES) */
570 if (parent_type && parent_type->parent_type) switch (last->typetype) {
571 case T_UTF8STRING:
572 case T_USTR: // the TTCN equivalent of UTF8String
573 if ( T_SEQOF == parent_type->typetype
574 && (T_SEQ_T == parent_type->parent_type->typetype
575 ||T_SEQ_A == parent_type->parent_type->typetype)
576 && parent_type->parent_type->xerattrib) {
577 embed |= (parent_type->parent_type->xerattrib->embedValues_);
578 }
579 break;
580 default:
581 break;
582 }
583 size_t last_len = 2 + last_s.size(); // 2 for > \n
584 size_t bxer_len = 2 + bxer_name.size(); // 2 for > \n
585
586 if ((T_SEQOF == last->typetype || T_SETOF == last->typetype) &&
587 T_ANYTYPE != last->u.seof.ofType->get_type_refd_last()->typetype) {
588 // anytypes don't have XER descriptors
589 oftype_descr_name = mprintf("&%s_xer_", last->u.seof.ofType->get_genname_typedescriptor(my_scope).c_str());
590 }
591
592 // Generate a separate variable for the namespace URIs, if there are any
593 char* ns_uris_var = 0;
594 if (ns_uris && nof_ns_uris) {
595 ns_uris_var = mputprintf(ns_uris_var, "%s_ns_uris_", gennameown_str);
596 target->source.global_vars = mputprintf(target->source.global_vars,
597 "const char* %s[] = {", ns_uris_var);
598 for (int idx = 0; idx < nof_ns_uris; ++idx) {
599 // The unqualified namespace is sometimes stored as an empty string and
600 // sometimes as a null pointer -> unify it, always store it as an empty string
601 target->source.global_vars = mputprintf(target->source.global_vars,
602 "%s\"%s\"", (idx != 0) ? ", " : "", ns_uris[idx] ? ns_uris[idx] : "");
603 }
604 target->source.global_vars = mputstrn(target->source.global_vars, "};\n", 3);
605 }
606
607 // Generate the XER descriptor itself
608 target->source.global_vars = mputprintf(target->source.global_vars,
609 "const XERdescriptor_t %s_xer_ = { {\"%s>\\n\", \"%s>\\n\"},"
610 " {%lu, %lu}, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s, WHITESPACE_%s, %c%s, "
611 "&%s, %ld, %u, %s, %s };\n",
612 gennameown_str,
613 bxer_name.c_str(), last_s.c_str(), // names
614 (unsigned long)bxer_len, (unsigned long)last_len, // lengths
615 (any_atr ? "ANY_ATTRIBUTES" : "0"),
616 (any_elem ? " |ANY_ELEMENT" : ""),
617 (atrib ? " |XER_ATTRIBUTE" : ""),
618 (base64 ? " |BASE_64" : ""),
619 (decimal ? " |XER_DECIMAL" : ""),
620 (embed ? " |EMBED_VALUES" : ""),
621 (list ? " |XER_LIST" : ""),
622 (text ? " |XER_TEXT" : ""),
623 (untagged ? " |UNTAGGED" : ""),
624 (use_nil ? " |USE_NIL" : ""),
625 (use_number ? " |USE_NUMBER" : ""),
626 (use_order ? " |USE_ORDER" : ""),
627 (use_qname ? " |USE_QNAME" : ""),
628 (use_type_attr ? " |USE_TYPE_ATTR" : ""),
629 (has_1untag ? " |HAS_1UNTAGGED" : ""),
630 (form_qualified ? "" : " |FORM_UNQUALIFIED"),
631 (any_from ? " |ANY_FROM" : ""),
632 (any_except ? " |ANY_EXCEPT" : ""),
633 whitespace_action[ws],
634 (dfe_str ? '&' : ' '), (dfe_str ? dfe_str : "NULL"),
635 "module_object",
636 ns_index,
637 nof_ns_uris,
638 (ns_uris_var ? ns_uris_var : "NULL"),
639 (oftype_descr_name ? oftype_descr_name : "NULL")
640 );
641
642 Free(ns_uris_var);
643 Free(oftype_descr_name);
644 }
645
646 void Type::generate_code_rawdescriptor(output_struct *target)
647 {
648 const char *gennameown_str = get_genname_own().c_str();
649 target->header.global_vars = mputprintf(target->header.global_vars,
650 "extern const TTCN_RAWdescriptor_t %s_raw_;\n", gennameown_str);
651 char *str = mprintf("const TTCN_RAWdescriptor_t %s_raw_ = {",
652 gennameown_str);
653 str = mputprintf(str, "%d,", rawattrib->fieldlength);
654 if (rawattrib->comp == XDEFCOMPL) str = mputstr(str, "SG_2COMPL,");
655 else if (rawattrib->comp == XDEFSIGNBIT) str = mputstr(str, "SG_SG_BIT,");
656 else str = mputstr(str, "SG_NO,");
657 if (rawattrib->byteorder == XDEFLAST) str = mputstr(str, "ORDER_MSB,");
658 else str = mputstr(str, "ORDER_LSB,");
659 if (rawattrib->align == XDEFLEFT) str = mputstr(str, "ORDER_MSB,");
660 else str = mputstr(str, "ORDER_LSB,");
661 if (rawattrib->bitorderinfield == XDEFMSB)
662 str = mputstr(str, "ORDER_MSB,");
663 else str = mputstr(str, "ORDER_LSB,");
664 if (rawattrib->bitorderinoctet == XDEFMSB)
665 str = mputstr(str, "ORDER_MSB,");
666 else str = mputstr(str, "ORDER_LSB,");
667 if (rawattrib->extension_bit == XDEFYES)
668 str = mputstr(str, "EXT_BIT_YES,");
669 else if (rawattrib->extension_bit == XDEFREVERSE)
670 str = mputstr(str, "EXT_BIT_REVERSE,");
671 else str = mputstr(str, "EXT_BIT_NO,");
672 if (rawattrib->hexorder == XDEFHIGH) str = mputstr(str, "ORDER_MSB,");
673 else str = mputstr(str, "ORDER_LSB,");
674 if (rawattrib->fieldorder == XDEFMSB) str = mputstr(str, "ORDER_MSB,");
675 else str = mputstr(str, "ORDER_LSB,");
676 if (rawattrib->topleveleind) {
677 if (rawattrib->toplevel.bitorder==XDEFLSB)
678 str = mputstr(str, "TOP_BIT_LEFT,");
679 else str = mputstr(str, "TOP_BIT_RIGHT,");
680 } else str = mputstr(str, "TOP_BIT_INHERITED,");
681 str = mputprintf(str, "%d,", rawattrib->padding);
682 str = mputprintf(str, "%d,", rawattrib->prepadding);
683 str = mputprintf(str, "%d,", rawattrib->ptroffset);
684 str = mputprintf(str, "%d,", rawattrib->unit);
685 str = mputprintf(str, "%d,", rawattrib->padding_pattern_length);
686 if (rawattrib->padding_pattern_length > 0)
687 str = mputprintf(str, "%s,", my_scope->get_scope_mod_gen()
688 ->add_padding_pattern(string(rawattrib->padding_pattern)).c_str());
689 else str = mputstr(str, "NULL,");
690 str = mputprintf(str, "%d};\n", rawattrib->length_restrition);
691 target->source.global_vars = mputstr(target->source.global_vars, str);
692 Free(str);
693 }
694
695 void Type::generate_code_textdescriptor(output_struct *target)
696 {
697 const char *gennameown_str = get_genname_own().c_str();
698 char *union_member_name=NULL;
699 Common::Module *mymod=my_scope->get_scope_mod();
700 Type *t = get_type_refd_last();
701 switch (t->typetype) {
702 case T_BOOL:
703 if (textattrib->true_params || textattrib->false_params) {
704 target->source.global_vars = mputprintf(target->source.global_vars,
705 "static const TTCN_TEXTdescriptor_bool %s_bool_ = {", gennameown_str);
706 if (textattrib->true_params &&
707 textattrib->true_params->encode_token) {
708 target->source.global_vars = mputprintf(target->source.global_vars,
709 "&%s,", mymod->add_charstring_literal(
710 string(textattrib->true_params->encode_token)).c_str());
711 } else {
712 target->source.global_vars=mputstr(target->source.global_vars,
713 "NULL,");
714 }
715 if (textattrib->true_params &&
716 textattrib->true_params->decode_token) {
717 char *pstr = make_posix_str_code(
718 textattrib->true_params->decode_token,
719 textattrib->true_params->case_sensitive);
720 target->source.global_vars = mputprintf(target->source.global_vars,
721 "&%s,", mymod->add_matching_literal(string(pstr)).c_str());
722 Free(pstr);
723 } else if (textattrib->true_params &&
724 !textattrib->true_params->case_sensitive) {
725 target->source.global_vars = mputprintf(target->source.global_vars,
726 "&%s,", mymod->add_matching_literal(
727 string("N^(true).*$")).c_str());
728 } else {
729 target->source.global_vars = mputstr(target->source.global_vars,
730 "NULL,");
731 }
732 if (textattrib->false_params &&
733 textattrib->false_params->encode_token) {
734 target->source.global_vars = mputprintf(target->source.global_vars,
735 "&%s,",mymod->add_charstring_literal(
736 string(textattrib->false_params->encode_token)).c_str());
737 } else {
738 target->source.global_vars = mputstr(target->source.global_vars,
739 "NULL,");
740 }
741 if (textattrib->false_params &&
742 textattrib->false_params->decode_token) {
743 char *pstr = make_posix_str_code(
744 textattrib->false_params->decode_token,
745 textattrib->false_params->case_sensitive);
746 target->source.global_vars=mputprintf(target->source.global_vars,
747 "&%s};\n", mymod->add_matching_literal(string(pstr)).c_str());
748 Free(pstr);
749 } else if (textattrib->false_params &&
750 !textattrib->false_params->case_sensitive) {
751 target->source.global_vars = mputprintf(target->source.global_vars,
752 "&%s};\n", mymod->add_matching_literal(
753 string("N^(false).*$")).c_str());
754 } else {
755 target->source.global_vars = mputstr(target->source.global_vars,
756 "NULL};\n");
757 }
758 union_member_name = mprintf("(TTCN_TEXTdescriptor_param_values*)"
759 "&%s_bool_", gennameown_str);
760 }
761 break;
762 case T_ENUM_T:
763 target->source.global_vars = mputprintf(target->source.global_vars,
764 "static const TTCN_TEXTdescriptor_enum %s_enum_[] = { ",
765 gennameown_str);
766 for (size_t i = 0; i < t->u.enums.eis->get_nof_eis(); i++) {
767 if (i > 0) target->source.global_vars =
768 mputstr(target->source.global_vars, ", ");
769 target->source.global_vars =
770 mputstr(target->source.global_vars, "{ ");
771 if (textattrib->field_params && textattrib->field_params[i] &&
772 textattrib->field_params[i]->value.encode_token) {
773 // the encode token is present
774 target->source.global_vars = mputprintf(target->source.global_vars,
775 "&%s, ", mymod->add_charstring_literal(
776 string(textattrib->field_params[i]->value.encode_token)).c_str());
777 } else {
778 // the encode token is not present: generate a NULL pointer and the
779 // RTE will substitute the enumerated value
780 target->source.global_vars = mputstr(target->source.global_vars,
781 "NULL, ");
782 }
783 // a pattern must be always present for decoding
784 const char *decode_token;
785 bool case_sensitive;
786 if (textattrib->field_params && textattrib->field_params[i]) {
787 if (textattrib->field_params[i]->value.decode_token) {
788 // the decode token is present
789 decode_token = textattrib->field_params[i]->value.decode_token;
790 } else {
791 // there is an attribute for the enumerated value,
792 // but the decode token is omitted
793 // use the value as decode token
794 decode_token = t->u.enums.eis->get_ei_byIndex(i)->get_name()
795 .get_dispname().c_str();
796 }
797 // take the case sensitivity from the attribute
798 case_sensitive = textattrib->field_params[i]->value.case_sensitive;
799 } else {
800 // there is no attribute for the enumerated value
801 // use the value as decode token
802 decode_token = t->u.enums.eis->get_ei_byIndex(i)->get_name()
803 .get_dispname().c_str();
804 // it is always case sensitive
805 case_sensitive = true;
806 }
807 char *pstr = make_posix_str_code(decode_token, case_sensitive);
808 target->source.global_vars = mputprintf(target->source.global_vars,
809 " &%s }", mymod->add_matching_literal(string(pstr)).c_str());
810 Free(pstr);
811 }
812 target->source.global_vars = mputstr(target->source.global_vars,
813 " };\n");
814 union_member_name = mprintf(
815 "(TTCN_TEXTdescriptor_param_values*)%s_enum_", gennameown_str);
816 break;
817 case T_INT:
818 case T_CSTR:
819 if(textattrib->coding_params.leading_zero ||
820 textattrib->coding_params.min_length!=-1 ||
821 textattrib->coding_params.max_length!=-1 ||
822 textattrib->coding_params.convert!=0 ||
823 textattrib->coding_params.just!=1 ||
824 textattrib->decoding_params.leading_zero ||
825 textattrib->decoding_params.min_length!=-1 ||
826 textattrib->decoding_params.max_length!=-1 ||
827 textattrib->decoding_params.convert!=0 ||
828 textattrib->decoding_params.just!=1 ){
829 target->source.global_vars=mputprintf(target->source.global_vars,
830 "static const TTCN_TEXTdescriptor_param_values %s_par_ = {",
831 gennameown_str);
832 target->source.global_vars=mputprintf(target->source.global_vars,
833 "{%s,%s,%i,%i,%i,%i},{%s,%s,%i,%i,%i,%i}};\n"
834 ,textattrib->coding_params.leading_zero?"true":"false"
835 ,textattrib->coding_params.repeatable?"true":"false"
836 ,textattrib->coding_params.min_length
837 ,textattrib->coding_params.max_length
838 ,textattrib->coding_params.convert
839 ,textattrib->coding_params.just
840 ,textattrib->decoding_params.leading_zero?"true":"false"
841 ,textattrib->decoding_params.repeatable?"true":"false"
842 ,textattrib->decoding_params.min_length
843 ,textattrib->decoding_params.max_length
844 ,textattrib->decoding_params.convert
845 ,textattrib->decoding_params.just);
846
847 union_member_name=mprintf("&%s_par_", gennameown_str);
848 }
849 break;
850 case T_SEQOF:
851 case T_SETOF:
852 target->source.global_vars=mputprintf(target->source.global_vars,
853 "static const TTCN_TEXTdescriptor_param_values %s_par_ = {",
854 gennameown_str);
855 target->source.global_vars=mputprintf(target->source.global_vars,
856 "{%s,%s,%i,%i,%i,%i},{%s,%s,%i,%i,%i,%i}};\n"
857 ,textattrib->coding_params.leading_zero?"true":"false"
858 ,textattrib->coding_params.repeatable?"true":"false"
859 ,textattrib->coding_params.min_length
860 ,textattrib->coding_params.max_length
861 ,textattrib->coding_params.convert
862 ,textattrib->coding_params.just
863 ,textattrib->decoding_params.leading_zero?"true":"false"
864 ,textattrib->decoding_params.repeatable?"true":"false"
865 ,textattrib->decoding_params.min_length
866 ,textattrib->decoding_params.max_length
867 ,textattrib->decoding_params.convert
868 ,textattrib->decoding_params.just);
869
870 union_member_name=mprintf("&%s_par_", gennameown_str);
871 break;
872 default:
873 break;
874 }
875
876 target->header.global_vars = mputprintf(target->header.global_vars,
877 "extern const TTCN_TEXTdescriptor_t %s_text_;\n", gennameown_str);
878 target->source.global_vars = mputprintf(target->source.global_vars,
879 "const TTCN_TEXTdescriptor_t %s_text_ = {", gennameown_str);
880
881 if (textattrib->begin_val && textattrib->begin_val->encode_token) {
882 target->source.global_vars = mputprintf(target->source.global_vars,
883 "&%s,", mymod->add_charstring_literal(
884 string(textattrib->begin_val->encode_token)).c_str());
885 } else {
886 target->source.global_vars = mputstr(target->source.global_vars,
887 "NULL,");
888 }
889 if(textattrib->begin_val && textattrib->begin_val->decode_token){
890 char *pstr = make_posix_str_code(
891 textattrib->begin_val->decode_token,
892 textattrib->begin_val->case_sensitive);
893 target->source.global_vars = mputprintf(target->source.global_vars,
894 "&%s,", mymod->add_matching_literal(string(pstr)).c_str());
895 Free(pstr);
896 } else {
897 target->source.global_vars = mputstr(target->source.global_vars,
898 "NULL,");
899 }
900 if (textattrib->end_val && textattrib->end_val->encode_token) {
901 target->source.global_vars = mputprintf(target->source.global_vars,
902 "&%s,",mymod->add_charstring_literal(
903 string(textattrib->end_val->encode_token)).c_str());
904 } else {
905 target->source.global_vars = mputstr(target->source.global_vars,
906 "NULL,");
907 }
908 if (textattrib->end_val && textattrib->end_val->decode_token) {
909 char *pstr = make_posix_str_code(
910 textattrib->end_val->decode_token,
911 textattrib->end_val->case_sensitive);
912 target->source.global_vars = mputprintf(target->source.global_vars,
913 "&%s,", mymod->add_matching_literal(string(pstr)).c_str());
914 Free(pstr);
915 } else {
916 target->source.global_vars = mputstr(target->source.global_vars,
917 "NULL,");
918 }
919
920 if (textattrib->separator_val &&
921 textattrib->separator_val->encode_token) {
922 target->source.global_vars = mputprintf(target->source.global_vars,
923 "&%s,", mymod->add_charstring_literal(
924 string(textattrib->separator_val->encode_token)).c_str());
925 } else {
926 target->source.global_vars = mputstr(target->source.global_vars,
927 "NULL,");
928 }
929 if(textattrib->separator_val &&
930 textattrib->separator_val->decode_token) {
931 char *pstr = make_posix_str_code(
932 textattrib->separator_val->decode_token,
933 textattrib->separator_val->case_sensitive);
934 target->source.global_vars = mputprintf(target->source.global_vars,
935 "&%s,", mymod->add_matching_literal(string(pstr)).c_str());
936 Free(pstr);
937 } else {
938 target->source.global_vars=mputstr(target->source.global_vars,
939 "NULL,");
940 }
941
942 if (textattrib->decode_token) {
943 char *pstr = make_posix_str_code(textattrib->decode_token,
944 textattrib->case_sensitive);
945 target->source.global_vars = mputprintf(target->source.global_vars,
946 "&%s,", mymod->add_matching_literal(string(pstr)).c_str());
947 Free(pstr);
948 } else {
949 target->source.global_vars = mputstr(target->source.global_vars,
950 "NULL,");
951 }
952
953 if (union_member_name) {
954 target->source.global_vars = mputprintf(target->source.global_vars,
955 "{%s}};\n", union_member_name);
956 Free(union_member_name);
957 } else {
958 target->source.global_vars = mputstr(target->source.global_vars,
959 "{NULL}};\n");
960 }
961 }
962
963 void Type::generate_code_jsondescriptor(output_struct *target)
964 {
965 target->header.global_vars = mputprintf(target->header.global_vars,
966 "extern const TTCN_JSONdescriptor_t %s_json_;\n", get_genname_own().c_str());
967
968 if (NULL == jsonattrib) {
969 target->source.global_vars = mputprintf(target->source.global_vars,
970 "const TTCN_JSONdescriptor_t %s_json_ = { false, NULL, false, NULL };\n"
971 , get_genname_own().c_str());
972 } else {
973 char* alias = jsonattrib->alias ? mputprintf(NULL, "\"%s\"", jsonattrib->alias) : NULL;
974 char* def_val = jsonattrib->default_value ?
975 mputprintf(NULL, "\"%s\"", jsonattrib->default_value) : NULL;
976 target->source.global_vars = mputprintf(target->source.global_vars,
977 "const TTCN_JSONdescriptor_t %s_json_ = { %s, %s, %s, %s };\n"
978 , get_genname_own().c_str()
979 , jsonattrib->omit_as_null ? "true" : "false"
980 , alias ? alias : "NULL"
981 , jsonattrib->as_value ? "true" : "false"
982 , def_val ? def_val : "NULL");
983 Free(alias);
984 Free(def_val);
985 }
986
987 }
988
989 void Type::generate_code_alias(output_struct *target)
990 {
991 if (!needs_alias()) return;
992
993 const string& t_genname = get_genname_value(my_scope);
994 const char *refd_name = t_genname.c_str();
995 const char *own_name = get_genname_own().c_str();
996
997 Type *t_last = get_type_refd_last();
998 switch (t_last->typetype) {
999 case T_PORT: // only value class exists
1000 target->header.typedefs = mputprintf(target->header.typedefs,
1001 "typedef %s %s;\n", refd_name, own_name);
1002 break;
1003 case T_SIGNATURE: // special classes (7 pcs.) exist
1004 target->header.typedefs = mputprintf(target->header.typedefs,
1005 "typedef %s_call %s_call;\n"
1006 "typedef %s_call_redirect %s_call_redirect;\n",
1007 refd_name, own_name, refd_name, own_name);
1008 if (!t_last->is_nonblocking_signature()) {
1009 target->header.typedefs = mputprintf(target->header.typedefs,
1010 "typedef %s_reply %s_reply;\n"
1011 "typedef %s_reply_redirect %s_reply_redirect;\n",
1012 refd_name, own_name, refd_name, own_name);
1013 }
1014 if (t_last->get_signature_exceptions()) {
1015 target->header.typedefs = mputprintf(target->header.typedefs,
1016 "typedef %s_exception %s_exception;\n"
1017 "typedef %s_exception_template %s_exception_template;\n",
1018 refd_name, own_name, refd_name, own_name);
1019 }
1020 target->header.typedefs = mputprintf(target->header.typedefs,
1021 "typedef %s_template %s_template;\n",
1022 refd_name, own_name);
1023 break;
1024 default: // value and template classes exist
1025 target->header.typedefs = mputprintf(target->header.typedefs,
1026 #ifndef NDEBUG
1027 "// written by %s in " __FILE__ " at %d\n"
1028 #endif
1029 "typedef %s %s;\n"
1030 "typedef %s_template %s_template;\n",
1031 #ifndef NDEBUG
1032 __FUNCTION__, __LINE__,
1033 #endif
1034 refd_name, own_name, refd_name, own_name);
1035 break;
1036 }
1037 }
1038
1039 void Type::generate_code_Enum(output_struct *target)
1040 {
1041 stringpool pool;
1042 enum_def e_def;
1043 memset(&e_def, 0, sizeof(e_def));
1044 e_def.name = get_genname_own().c_str();
1045 e_def.dispname = get_fullname().c_str();
1046 e_def.isASN1 = is_asn1();
1047 e_def.nElements = u.enums.eis->get_nof_eis();
1048 e_def.elements = (enum_field*)
1049 Malloc(e_def.nElements*sizeof(*e_def.elements));
1050 e_def.firstUnused = u.enums.first_unused;
1051 e_def.secondUnused = u.enums.second_unused;
1052 e_def.hasText = textattrib!=NULL;
1053 e_def.hasRaw = rawattrib!=NULL;
1054 e_def.hasXer = has_encoding(CT_XER);
1055 e_def.hasJson = has_encoding(CT_JSON);
1056 if (xerattrib) {
1057 e_def.xerUseNumber = xerattrib->useNumber_;
1058 }
1059 for (size_t i = 0; i < e_def.nElements; i++) {
1060 EnumItem *ei = u.enums.eis->get_ei_byIndex(i);
1061 e_def.elements[i].name = ei->get_name().get_name().c_str();
1062 e_def.elements[i].dispname = ei->get_name().get_ttcnname().c_str();
1063 if (ei->get_text().empty()) e_def.elements[i].text = 0;
1064 else {
1065 e_def.xerText = TRUE;
1066 e_def.elements[i].text = ei->get_text().c_str();
1067 }
1068 e_def.elements[i].value = ei->get_value()->get_val_Int()->get_val();
1069 }
1070
1071 defEnumClass(&e_def, target);
1072 defEnumTemplate(&e_def, target);
1073
1074 Free(e_def.elements);
1075 }
1076
1077 void Type::generate_code_Choice(output_struct *target)
1078 {
1079 stringpool pool;
1080 struct_def sdef;
1081 memset(&sdef, 0, sizeof(sdef));
1082 sdef.name = get_genname_own().c_str();
1083 sdef.dispname=get_fullname().c_str();
1084 if (T_ANYTYPE==typetype) {
1085 if (0 == get_nof_comps()) {
1086 //return; // don't generate code for empty anytype
1087 // XXX what to do with empty anytype ?
1088 // Easy: make sure it doesn't happen by filling it from the AST!
1089 }
1090 sdef.kind = ANYTYPE;
1091 }
1092 else sdef.kind = UNION;
1093 sdef.isASN1 = is_asn1();
1094 sdef.hasText = textattrib!=NULL;
1095 sdef.hasXer = has_encoding(CT_XER);
1096 sdef.hasJson = has_encoding(CT_JSON);
1097 sdef.has_opentypes = get_has_opentypes();
1098 sdef.opentype_outermost = get_is_opentype_outermost();
1099 sdef.ot = generate_code_ot(pool);
1100 sdef.nElements = get_nof_comps();
1101 sdef.elements = (struct_field*)
1102 Malloc(sdef.nElements*sizeof(*sdef.elements));
1103 memset(sdef.elements, 0, sdef.nElements*sizeof(*sdef.elements));
1104 sdef.exerMaybeEmptyIndex = -1;
1105 if (jsonattrib) {
1106 sdef.jsonAsValue = jsonattrib->as_value;
1107 }
1108 for(size_t i = 0; i < sdef.nElements; i++) {
1109 CompField *cf = get_comp_byIndex(i);
1110 const Identifier& id = cf->get_name();
1111 Type *cftype = cf->get_type();
1112 sdef.elements[i].type = pool.add(cftype->get_genname_value(my_scope));
1113 sdef.elements[i].typedescrname =
1114 pool.add(cftype->get_genname_typedescriptor(my_scope));
1115 sdef.elements[i].typegen = pool.add(cftype->get_genname_xerdescriptor());
1116 sdef.elements[i].name = id.get_name().c_str();
1117 sdef.elements[i].dispname = id.get_ttcnname().c_str();
1118 if (xerattrib) {
1119 if (cftype->has_empty_xml()) sdef.exerMaybeEmptyIndex = i;
1120 // This will overwrite lower values, which is what we want.
1121 }
1122 if (sdef.jsonAsValue) {
1123 // Determine the JSON value type of each field to make decoding faster
1124 typetype_t tt = cftype->get_type_refd_last()->typetype;
1125 switch(tt) {
1126 case T_INT:
1127 sdef.elements[i].jsonValueType = JSON_NUMBER;
1128 break;
1129 case T_REAL:
1130 sdef.elements[i].jsonValueType = JSON_NUMBER | JSON_STRING;
1131 break;
1132 case T_BOOL:
1133 sdef.elements[i].jsonValueType = JSON_LITERAL;
1134 break;
1135 case T_BSTR:
1136 case T_HSTR:
1137 case T_OSTR:
1138 case T_CSTR:
1139 case T_USTR:
1140 case T_VERDICT:
1141 case T_ENUM_T:
1142 sdef.elements[i].jsonValueType = JSON_STRING;
1143 break;
1144 case T_SEQ_T:
1145 case T_SET_T:
1146 case T_CHOICE_T:
1147 sdef.elements[i].jsonValueType = JSON_OBJECT;
1148 break;
1149 case T_SEQOF:
1150 case T_SETOF:
1151 sdef.elements[i].jsonValueType = JSON_ARRAY;
1152 break;
1153 default:
1154 FATAL_ERROR("Type::generate_code_Choice - invalid field type %d", tt);
1155 }
1156 }
1157 if (cftype->jsonattrib) {
1158 sdef.elements[i].jsonAlias = cftype->jsonattrib->alias;
1159 if (sdef.jsonAsValue && cftype->jsonattrib->as_value) {
1160 // Override the JSON_OBJECT value given in the switch
1161 sdef.elements[i].jsonValueType = JSON_ANY_VALUE;
1162 }
1163 }
1164 }
1165 if(rawattrib) {
1166 copy_rawAST_to_struct(rawattrib,&(sdef.raw));
1167 sdef.hasRaw=true;
1168 // building taglist
1169 for(int c=0;c<rawattrib->taglist.nElements;c++){
1170 if(rawattrib->taglist.tag[c].nElements)
1171 sdef.raw.taglist.list[c].fields=
1172 (rawAST_coding_field_list*)
1173 Malloc(rawattrib->taglist.tag[c].nElements
1174 *sizeof(rawAST_coding_field_list));
1175 else sdef.raw.taglist.list[c].fields=NULL;
1176 sdef.raw.taglist.list[c].nElements=
1177 rawattrib->taglist.tag[c].nElements;
1178 sdef.raw.taglist.list[c].fieldName=
1179 rawattrib->taglist.tag[c].fieldName->get_name().c_str();
1180 Identifier *idf=rawattrib->taglist.tag[c].fieldName;
1181 sdef.raw.taglist.list[c].fieldnum=get_comp_index_byName(*idf);
1182 for(int a=0;a<rawattrib->taglist.tag[c].nElements;a++){
1183 rawAST_coding_field_list* key=
1184 sdef.raw.taglist.list[c].fields+a;
1185 key->nElements=
1186 rawattrib->taglist.tag[c].keyList[a].keyField->nElements+1;
1187 key->value=rawattrib->taglist.tag[c].keyList[a].value;
1188 key->start_pos=0;
1189 key->fields=(rawAST_coding_fields*)
1190 Malloc(key->nElements*sizeof(rawAST_coding_fields));
1191 CompField *cf=get_comp_byIndex(sdef.raw.taglist.list[c].fieldnum);
1192 Type *t=cf->get_type()->get_type_refd_last();
1193
1194 key->fields[0].nthfield = sdef.raw.taglist.list[c].fieldnum;
1195 key->fields[0].nthfieldname =
1196 rawattrib->taglist.tag[c].fieldName->get_name().c_str();
1197 key->fields[0].fieldtype = UNION_FIELD;
1198 key->fields[0].type = pool.add(t->get_genname_value(my_scope));
1199 key->fields[0].typedescr =
1200 pool.add(t->get_genname_typedescriptor(my_scope));
1201
1202 for (int b = 1; b < key->nElements; b++) {
1203 Identifier *idf2 =
1204 rawattrib->taglist.tag[c].keyList[a].keyField->names[b-1];
1205 size_t comp_index = t->get_comp_index_byName(*idf2);
1206 CompField *cf2 = t->get_comp_byIndex(comp_index);
1207 key->fields[b].nthfield = comp_index;
1208 key->fields[b].nthfieldname = idf2->get_name().c_str();
1209 if (t->typetype == T_CHOICE_T)
1210 key->fields[b].fieldtype = UNION_FIELD;
1211 else if (cf2->get_is_optional()){
1212 key->fields[b].fieldtype = OPTIONAL_FIELD;
1213 }else key->fields[b].fieldtype = MANDATORY_FIELD;
1214 Type *field_type = cf2->get_type();
1215 key->fields[b].type =
1216 pool.add(field_type->get_genname_value(my_scope));
1217 key->fields[b].typedescr =
1218 pool.add(field_type->get_genname_typedescriptor(my_scope));
1219 if (field_type->typetype == T_SEQ_T && field_type->rawattrib
1220 && (field_type->rawattrib->pointerto
1221 || field_type->rawattrib->lengthto_num))
1222 key->start_pos = -1;
1223
1224 if(t->typetype != T_CHOICE_T && t->typetype != T_SET_T){
1225 Type *t2;
1226 for(size_t i = 0; i < comp_index && key->start_pos >=0; i++)
1227 {
1228 t2 = t->get_comp_byIndex(i)->get_type();
1229 if(t2->get_raw_length() >= 0){
1230 if(t2->rawattrib)
1231 key->start_pos += t2->rawattrib->padding;
1232 key->start_pos += t2->get_raw_length();
1233 }else key->start_pos = -1;
1234 }
1235 }
1236 t = field_type->get_type_refd_last();
1237 }
1238 }
1239 }
1240 } else sdef.hasRaw=false;
1241 if (xerattrib) {
1242 Module *my_module = get_my_scope()->get_scope_mod();
1243 sdef.xerHasNamespaces = my_module->get_nof_ns() != 0;
1244 const char *ns, *prefix;
1245 my_module->get_controlns(ns, prefix);
1246 sdef.control_ns_prefix = prefix;
1247 sdef.xerUseUnion = xerattrib->useUnion_;
1248 sdef.xerUseTypeAttr = xerattrib->useType_ || xerattrib->useUnion_;
1249 }
1250 defUnionClass(&sdef, target);
1251 defUnionTemplate(&sdef, target);
1252
1253 free_code_ot(sdef.ot);
1254 sdef.ot=0;
1255 if (rawattrib) {
1256 free_raw_attrib_struct(&sdef.raw);
1257 }
1258 Free(sdef.elements);
1259 }
1260
1261 Opentype_t *Type::generate_code_ot(stringpool& pool)
1262 {
1263 using namespace Asn;
1264 if(typetype!=T_OPENTYPE)
1265 return 0;
1266 if(!u.secho.my_tableconstraint
1267 || !u.secho.my_tableconstraint->get_ans()) {
1268 DEBUG(1, "Opentype ObjectClassFieldType without"
1269 " ComponentRelationConstraint: `%s'",
1270 get_fullname().c_str());
1271 return 0;
1272 }
1273 const AtNotations *ans=u.secho.my_tableconstraint->get_ans();
1274 Opentype_t *ot=(Opentype_t*)Malloc(sizeof(*ot));
1275 ot->anl.nElements = ans->get_nof_ans();
1276 ot->anl.elements = (AtNotation_t*)
1277 Malloc(ot->anl.nElements * sizeof(*ot->anl.elements));
1278 for(size_t i=0; i<ans->get_nof_ans(); i++) {
1279 AtNotation *an=ans->get_an_byIndex(i);
1280 AtNotation_t *an_t = ot->anl.elements + i;
1281 an_t->dispname = pool.add(an->get_dispname());
1282 an_t->parent_level=an->get_levels();
1283 an_t->parent_typename =
1284 pool.add(an->get_firstcomp()->get_genname_value(my_scope));
1285 an_t->type_name =
1286 pool.add(an->get_lastcomp()->get_genname_value(my_scope));
1287 an_t->sourcecode=memptystr();
1288 FieldName* cids=an->get_cids();
1289 Type *t_type=an->get_firstcomp();
1290 for(size_t j=0; j<cids->get_nof_fields(); j++) {
1291 CompField *cf=
1292 t_type->get_comp_byName(*cids->get_field_byIndex(j));
1293 if(j) an_t->sourcecode=mputstr(an_t->sourcecode, ".");
1294 an_t->sourcecode=mputprintf
1295 (an_t->sourcecode, "%s()",
1296 cf->get_name().get_name().c_str());
1297 if(cf->get_is_optional())
1298 an_t->sourcecode=mputstr(an_t->sourcecode, "()");
1299 t_type=cf->get_type();
1300 } // for j
1301 } // i
1302 const Identifier *oc_fieldname_t
1303 =u.secho.my_tableconstraint->get_oc_fieldname();
1304 Objects *objs
1305 =u.secho.my_tableconstraint->get_os()->get_refd_last()->get_objs();
1306 ot->oal.nElements = objs->get_nof_objs();
1307 ot->oal.elements = (OpentypeAlternative_t*)
1308 Malloc(ot->oal.nElements * sizeof(*ot->oal.elements));
1309 size_t nElements_missing=0;
1310 Value **val_prev=(Value**)
1311 Malloc(ans->get_nof_ans()*sizeof(*val_prev));
1312 boolean differs_from_prev=true;
1313 for(size_t i=0; i<objs->get_nof_objs(); i++) {
1314 Obj_defn *obj=objs->get_obj_byIndex(i);
1315 if(!obj->has_fs_withName_dflt(*oc_fieldname_t)) {
1316 nElements_missing++;
1317 continue;
1318 }
1319 OpentypeAlternative_t *oa_t = ot->oal.elements + i - nElements_missing;
1320 Type *t_type=dynamic_cast<Type*>
1321 (obj->get_setting_byName_dflt(*oc_fieldname_t));
1322 bool is_strange;
1323 const Identifier& altname = t_type->get_otaltname(is_strange);
1324 oa_t->alt = pool.add(altname.get_name());
1325 oa_t->alt_dispname = pool.add(altname.get_asnname());
1326 oa_t->alt_typename = pool.add(t_type->get_genname_value(my_scope));
1327 oa_t->alt_typedescrname =
1328 pool.add(t_type->get_genname_typedescriptor(my_scope));
1329 oa_t->valuenames=(const char**)Malloc
1330 (ans->get_nof_ans()*sizeof(*oa_t->valuenames));
1331 oa_t->const_valuenames=(const char**)Malloc
1332 (ans->get_nof_ans()*sizeof(*oa_t->const_valuenames));
1333 for(size_t j=0; j<ans->get_nof_ans(); j++) {
1334 AtNotation *an=ans->get_an_byIndex(j);
1335 const Identifier *oc_fieldname_v=an->get_oc_fieldname();
1336 Value *t_value=dynamic_cast<Value*>
1337 (obj->get_setting_byName_dflt(*oc_fieldname_v));
1338 oa_t->valuenames[j] = pool.add(t_value->get_genname_own(my_scope));
1339 if(!differs_from_prev && *val_prev[j]==*t_value)
1340 oa_t->const_valuenames[j]=0;
1341 else {
1342 oa_t->const_valuenames[j] =
1343 pool.add(t_value->get_genname_own(my_scope));
1344 differs_from_prev=true;
1345 }
1346 val_prev[j]=t_value;
1347 } //j
1348 differs_from_prev=false;
1349 } // i
1350 Free(val_prev);
1351 ot->oal.nElements -= nElements_missing;
1352 ot->oal.elements = (OpentypeAlternative_t*)
1353 Realloc(ot->oal.elements,
1354 ot->oal.nElements * sizeof(*ot->oal.elements));
1355 return ot;
1356 }
1357
1358 void Type::free_code_ot(Opentype_t* p_ot)
1359 {
1360 if (!p_ot) return;
1361 for (size_t i = 0; i < p_ot->oal.nElements; i++) {
1362 Free(p_ot->oal.elements[i].valuenames);
1363 Free(p_ot->oal.elements[i].const_valuenames);
1364 }
1365 Free(p_ot->oal.elements);
1366 for (size_t i = 0; i < p_ot->anl.nElements; i++)
1367 Free(p_ot->anl.elements[i].sourcecode);
1368 Free(p_ot->anl.elements);
1369 Free(p_ot);
1370 }
1371
1372 size_t Type::get_codegen_index(size_t index)
1373 {
1374 // This sorting is because of CER coding of SET types, see X.690 9.3.
1375 // see: Type::generate_code_Se()
1376 // TODO: maybe result should be cached into this type
1377 // ( inside u.secho as dynamic_array<size_t>* codegen_indexes ? )
1378 if (typetype==T_SET_A) {
1379 size_t nof_comps = get_nof_comps();
1380 map<Tag, void> se_index_map;
1381 for (size_t i=0; i<nof_comps; i++) {
1382 Tag *tag = get_comp_byIndex(i)->get_type()->get_smallest_tag();
1383 se_index_map.add(*tag, (void*)i); // hack: store size_t in void* to avoid Malloc()
1384 delete tag;
1385 }
1386 for(size_t i=0; i<nof_comps; i++) {
1387 if (se_index_map.get_nth_elem(i)==(void*)index) {
1388 se_index_map.clear();
1389 return i;
1390 }
1391 }
1392 FATAL_ERROR("Type::get_codegen_index()");
1393 }
1394 return index;
1395 }
1396
1397 void Type::generate_code_Se(output_struct *target)
1398 {
1399 stringpool pool;
1400 struct_def sdef;
1401 Type * last_field_type = 0;
1402 memset(&sdef, 0, sizeof(sdef));
1403 sdef.name = get_genname_own().c_str();
1404 sdef.dispname = get_fullname().c_str();
1405 //printf("generate_code_Se(%s)\n", sdef.dispname);
1406 switch(typetype) {
1407 case T_SEQ_A:
1408 sdef.kind=RECORD;
1409 sdef.isASN1=TRUE;
1410 break;
1411 case T_SEQ_T:
1412 sdef.kind=RECORD;
1413 sdef.isASN1=FALSE;
1414 break;
1415 case T_SET_A:
1416 sdef.kind=SET;
1417 sdef.isASN1=TRUE;
1418 break;
1419 case T_SET_T:
1420 sdef.kind=SET;
1421 sdef.isASN1=FALSE;
1422 break;
1423 default:
1424 FATAL_ERROR("Type::generate_code_Se()");
1425 } // switch
1426 sdef.hasText = textattrib!=NULL;
1427 sdef.nElements = sdef.totalElements = get_nof_comps();
1428 sdef.has_opentypes = get_has_opentypes();
1429 sdef.opentype_outermost = get_is_opentype_outermost();
1430 sdef.ot = NULL;
1431 sdef.hasXer = has_encoding(CT_XER);
1432 sdef.hasJson = has_encoding(CT_JSON);
1433 if (xerattrib){
1434 Module *my_module = get_my_scope()->get_scope_mod();
1435 sdef.xerHasNamespaces = my_module->get_nof_ns() != 0;
1436 const char *ns, *prefix;
1437 my_module->get_controlns(ns, prefix);
1438 sdef.control_ns_prefix = prefix;
1439 sdef.xerUntagged = xerattrib->untagged_;
1440 sdef.xerUntaggedOne = u.secho.has_single_charenc;
1441 sdef.xerUseNilPossible = use_nil_possible;
1442 sdef.xerEmbedValuesPossible = embed_values_possible;
1443 sdef.xerUseOrderPossible = use_order_possible;
1444 if (xerattrib->useOrder_ && xerattrib->useNil_) {
1445 // We need information about the fields of the USE-NIL component
1446 const CompField *cf = get_comp_byIndex(sdef.totalElements-1);
1447 last_field_type = cf->get_type()->get_type_refd_last();
1448 sdef.totalElements += last_field_type->get_nof_comps();
1449 }
1450 sdef.xerUseQName = xerattrib->useQName_;
1451 if (xerattrib->useType_ || xerattrib->useUnion_) {
1452 FATAL_ERROR("Type::generate_code_Se()"); // union only, not for record
1453 }
1454 }
1455 sdef.elements = (struct_field*)
1456 Malloc(sdef.totalElements*sizeof(*sdef.elements));
1457 memset(sdef.elements, 0, sdef.totalElements * sizeof(*sdef.elements));
1458
1459 /* This sorting is because of CER coding of SET types, see X.690
1460 9.3. */
1461 vector<CompField> se_comps;
1462 if(typetype==T_SET_A) {
1463 map<Tag, CompField> se_comps_map;
1464 for(size_t i=0; i<sdef.nElements; i++) {
1465 CompField* cf=get_comp_byIndex(i);
1466 Tag *tag = cf->get_type()->get_smallest_tag();
1467 se_comps_map.add(*tag, cf);
1468 delete tag;
1469 }
1470 for(size_t i=0; i<sdef.nElements; i++)
1471 se_comps.add(se_comps_map.get_nth_elem(i));
1472 se_comps_map.clear();
1473 }
1474 else {
1475 for(size_t i=0; i<sdef.nElements; i++)
1476 se_comps.add(get_comp_byIndex(i));
1477 }
1478
1479 for(size_t i = 0; i < sdef.nElements; i++) {
1480 struct_field &cur = sdef.elements[i];
1481 CompField *cf = se_comps[i];
1482 const Identifier& id = cf->get_name();
1483 Type *type = cf->get_type();
1484 cur.type = pool.add(type->get_genname_value(my_scope));
1485 cur.typegen = pool.add(type->get_genname_own());
1486 cur.of_type = type->get_type_refd_last()->is_seof();
1487 cur.typedescrname =
1488 pool.add(type->get_genname_typedescriptor(my_scope));
1489 cur.name = id.get_name().c_str();
1490 cur.dispname = id.get_ttcnname().c_str();
1491 cur.isOptional = cf->get_is_optional();
1492 cur.isDefault = cf->has_default();
1493 cur.optimizedMemAlloc = cur.of_type && (type->get_optimize_attribute() == "memalloc");
1494 if (cur.isDefault) {
1495 Value *defval = cf->get_defval();
1496 const_def cdef;
1497 Code::init_cdef(&cdef);
1498 type->generate_code_object(&cdef, defval);
1499 cdef.init = defval->generate_code_init
1500 (cdef.init, defval->get_lhs_name().c_str());
1501 Code::merge_cdef(target, &cdef);
1502 Code::free_cdef(&cdef);
1503 cur.defvalname = defval->get_genname_own().c_str();
1504 }
1505
1506 if (type->xerattrib) {
1507 cur.xerAttribute = type->xerattrib->attribute_;
1508
1509 if (has_aa(type->xerattrib)) {
1510 cur.xerAnyNum = type->xerattrib->anyAttributes_.nElements_;
1511 cur.xerAnyKind = ANY_ATTRIB_BIT |
1512 (type->xerattrib->anyAttributes_.type_ == NamespaceRestriction::FROM ?
1513 ANY_FROM_BIT : ANY_EXCEPT_BIT);
1514 if (cur.xerAnyNum > 0)
1515 cur.xerAnyUris = (char**)Malloc(cur.xerAnyNum * sizeof(char*));
1516 for (size_t uu=0; uu<cur.xerAnyNum; ++uu)
1517 cur.xerAnyUris[uu] = type->xerattrib->anyAttributes_.uris_[uu];
1518 }
1519 else if(has_ae(type->xerattrib)) {
1520 cur.xerAnyNum = type->xerattrib->anyElement_.nElements_;
1521 cur.xerAnyKind = ANY_ELEM_BIT |
1522 (type->xerattrib->anyElement_.type_ == NamespaceRestriction::FROM ?
1523 ANY_FROM_BIT : ANY_EXCEPT_BIT);
1524 if (cur.xerAnyNum > 0)
1525 cur.xerAnyUris = (char**)Malloc(cur.xerAnyNum* sizeof(char*));
1526 for (size_t uu=0; uu<cur.xerAnyNum; ++uu)
1527 cur.xerAnyUris[uu] = type->xerattrib->anyElement_.uris_[uu];
1528 }
1529 } // if xerattrib
1530 if (type->jsonattrib) {
1531 cur.jsonOmitAsNull = type->jsonattrib->omit_as_null;
1532 cur.jsonAlias = type->jsonattrib->alias;
1533 cur.jsonDefaultValue = type->jsonattrib->default_value;
1534 } // if jsonattrib
1535 } // next element
1536
1537 if (last_field_type)
1538 for (size_t i = sdef.nElements; i < sdef.totalElements; i++) {
1539 struct_field &cur = sdef.elements[i];
1540 CompField *cf = last_field_type->get_comp_byIndex(i - sdef.nElements);
1541 const Identifier& id = cf->get_name();
1542 Type *type = cf->get_type();
1543 cur.type = pool.add(type->get_genname_value(my_scope));
1544 cur.typegen = pool.add(type->get_genname_own());
1545 cur.of_type = type->get_type_refd_last()->is_seof();
1546 cur.typedescrname =
1547 pool.add(type->get_genname_typedescriptor(my_scope));
1548 cur.name = id.get_name().c_str();
1549 cur.dispname = id.get_ttcnname().c_str();
1550 cur.isOptional = cf->get_is_optional();
1551 }
1552 se_comps.clear();
1553
1554 if(rawattrib) {
1555 copy_rawAST_to_struct(rawattrib,&(sdef.raw));
1556 sdef.hasRaw=true;
1557 // building taglist
1558 for(int c=0;c<rawattrib->taglist.nElements;c++) {
1559 if(rawattrib->taglist.tag[c].nElements)
1560 sdef.raw.taglist.list[c].fields=
1561 (rawAST_coding_field_list*)
1562 Malloc(rawattrib->taglist.tag[c].nElements
1563 *sizeof(rawAST_coding_field_list));
1564 else sdef.raw.taglist.list[c].fields=NULL;
1565 sdef.raw.taglist.list[c].nElements=
1566 rawattrib->taglist.tag[c].nElements;
1567 sdef.raw.taglist.list[c].fieldName=
1568 rawattrib->taglist.tag[c].fieldName->get_name().c_str();
1569 Identifier *idf=rawattrib->taglist.tag[c].fieldName;
1570 sdef.raw.taglist.list[c].fieldnum=get_comp_index_byName(*idf);
1571 for(int a=0;a<rawattrib->taglist.tag[c].nElements;a++){
1572 rawAST_coding_field_list* key=
1573 sdef.raw.taglist.list[c].fields+a;
1574 key->nElements=
1575 rawattrib->taglist.tag[c].keyList[a].keyField->nElements+1;
1576 key->value=rawattrib->taglist.tag[c].keyList[a].value;
1577 key->start_pos=0;
1578 key->fields=(rawAST_coding_fields*)
1579 Malloc(key->nElements*sizeof(rawAST_coding_fields));
1580
1581 CompField *cf=get_comp_byIndex(sdef.raw.taglist.list[c].fieldnum);
1582 Type *t=cf->get_type()->get_type_refd_last();
1583
1584 key->fields[0].nthfield = sdef.raw.taglist.list[c].fieldnum;
1585 key->fields[0].nthfieldname =
1586 rawattrib->taglist.tag[c].fieldName->get_name().c_str();
1587 if (cf->get_is_optional())
1588 key->fields[0].fieldtype = OPTIONAL_FIELD;
1589 else key->fields[0].fieldtype = MANDATORY_FIELD;
1590 key->fields[0].type = pool.add(t->get_genname_value(my_scope));
1591 key->fields[0].typedescr =
1592 pool.add(t->get_genname_typedescriptor(my_scope));
1593
1594 CompField *cf2;
1595 for (int b = 1; b < key->nElements; b++) {
1596 Identifier *idf2 =
1597 rawattrib->taglist.tag[c].keyList[a].keyField->names[b-1];
1598 size_t comp_index = t->get_comp_index_byName(*idf2);
1599 cf2 = t->get_comp_byIndex(comp_index);
1600 key->fields[b].nthfield = comp_index;
1601 key->fields[b].nthfieldname = idf2->get_name().c_str();
1602 if (t->typetype == T_CHOICE_T)
1603 key->fields[b].fieldtype = UNION_FIELD;
1604 else if (cf2->get_is_optional())
1605 key->fields[b].fieldtype = OPTIONAL_FIELD;
1606 else key->fields[b].fieldtype = MANDATORY_FIELD;
1607 Type *field_type = cf2->get_type();
1608 key->fields[b].type =
1609 pool.add(field_type->get_genname_value(my_scope));
1610 key->fields[b].typedescr =
1611 pool.add(field_type->get_genname_typedescriptor(my_scope));
1612 if (field_type->typetype == T_SEQ_T && field_type->rawattrib
1613 && (field_type->rawattrib->pointerto
1614 || field_type->rawattrib->lengthto_num))
1615 key->start_pos = -1;
1616
1617 if(t->typetype != T_CHOICE_T && t->typetype != T_SET_T){
1618 Type *t2;
1619 for(size_t i = 0; i < comp_index && key->start_pos >=0; i++)
1620 {
1621 t2 = t->get_comp_byIndex(i)->get_type();
1622 if(t2->get_raw_length() >= 0){
1623 if(t2->rawattrib)
1624 key->start_pos += t2->rawattrib->padding;
1625 key->start_pos += t2->get_raw_length();
1626 }else key->start_pos = -1;
1627 }
1628 }
1629 t = field_type->get_type_refd_last();
1630 }
1631 }
1632 }
1633 // building presence list
1634 for(int a=0;a<rawattrib->presence.nElements;a++) {
1635 rawAST_coding_field_list* presences=sdef.raw.presence.fields+a;
1636 presences->nElements=
1637 rawattrib->presence.keyList[a].keyField->nElements;
1638 presences->value=rawattrib->presence.keyList[a].value;
1639 presences->fields=(rawAST_coding_fields*)
1640 Malloc(presences->nElements*sizeof(rawAST_coding_fields));
1641 Type *t = this;
1642 for (int b = 0; b < presences->nElements; b++) {
1643 Identifier *idf = rawattrib->presence.keyList[a].keyField->names[b];
1644 size_t comp_index = t->get_comp_index_byName(*idf);
1645 CompField *cf = t->get_comp_byIndex(comp_index);
1646 presences->fields[b].nthfield = comp_index;
1647 presences->fields[b].nthfieldname = idf->get_name().c_str();
1648 if (t->typetype == T_CHOICE_T)
1649 presences->fields[b].fieldtype = UNION_FIELD;
1650 else if (cf->get_is_optional())
1651 presences->fields[b].fieldtype = OPTIONAL_FIELD;
1652 else presences->fields[b].fieldtype = MANDATORY_FIELD;
1653 Type *field_type = cf->get_type();
1654 presences->fields[b].type =
1655 pool.add(field_type->get_genname_value(my_scope));
1656 presences->fields[b].typedescr =
1657 pool.add(field_type->get_genname_typedescriptor(my_scope));
1658 t = field_type->get_type_refd_last();
1659 }
1660 }
1661 for(int c=0;c<rawattrib->ext_bit_goup_num;c++){
1662 Identifier *idf=rawattrib->ext_bit_groups[c].from;
1663 Identifier *idf2=rawattrib->ext_bit_groups[c].to;
1664 sdef.raw.ext_bit_groups[c].ext_bit=rawattrib->ext_bit_groups[c].ext_bit;
1665 sdef.raw.ext_bit_groups[c].from=(int)get_comp_index_byName(*idf);
1666 sdef.raw.ext_bit_groups[c].to=(int)get_comp_index_byName(*idf2);
1667 }
1668 for(size_t i=0; i<sdef.totalElements; i++) {
1669 CompField *cf = get_comp_byIndex(i);
1670 Type *t_field = cf->get_type();
1671 Type *t_field_last = t_field->get_type_refd_last();
1672 RawAST *rawpar = t_field->rawattrib;
1673 if(rawpar) {
1674 copy_rawAST_to_struct(rawpar,&(sdef.elements[i].raw));
1675 for(int j=0; j<rawpar->lengthto_num;j++){
1676 Identifier *idf=rawpar->lengthto[j];
1677 sdef.elements[i].raw.lengthto[j]=get_comp_index_byName(*idf);
1678 }
1679 if (rawpar->lengthto_num && rawpar->lengthindex) {
1680 Identifier *idf = rawpar->lengthindex->names[0];
1681 size_t comp_index = t_field_last->get_comp_index_byName(*idf);
1682 sdef.elements[i].raw.lengthindex->nthfield = comp_index;
1683 sdef.elements[i].raw.lengthindex->nthfieldname =
1684 idf->get_name().c_str();
1685 CompField *cf2 = t_field_last->get_comp_byIndex(comp_index);
1686 Type *t_field2 = cf2->get_type();
1687 if (t_field2->typetype == T_CHOICE_T)
1688 sdef.elements[i].raw.lengthindex->fieldtype = UNION_FIELD;
1689 else if (cf2->get_is_optional())
1690 sdef.elements[i].raw.lengthindex->fieldtype = OPTIONAL_FIELD;
1691 else sdef.elements[i].raw.lengthindex->fieldtype = MANDATORY_FIELD;
1692 sdef.elements[i].raw.lengthindex->type =
1693 pool.add(t_field2->get_genname_value(my_scope));
1694 sdef.elements[i].raw.lengthindex->typedescr =
1695 pool.add(t_field2->get_genname_typedescriptor(my_scope));
1696 }
1697 if (rawpar->lengthto_num && !rawpar->lengthindex &&
1698 t_field_last->is_secho()) {
1699 int comp_num=(int)t_field_last->get_nof_comps();
1700 sdef.elements[i].raw.union_member_num=comp_num;
1701 sdef.elements[i].raw.member_name=
1702 (const char **)Malloc((comp_num+1)*sizeof(const char*));
1703 sdef.elements[i].raw.member_name[0] =
1704 pool.add(t_field_last->get_genname_value(my_scope));
1705 for(int m=1;m<comp_num+1;m++){
1706 CompField *compf=t_field_last->get_comp_byIndex(m-1);
1707 sdef.elements[i].raw.member_name[m]=
1708 compf->get_name().get_name().c_str();
1709 }
1710 }
1711 if(rawpar->pointerto){
1712 Identifier *idf=rawpar->pointerto;
1713 sdef.elements[i].raw.pointerto=get_comp_index_byName(*idf);
1714 if(rawpar->ptrbase){
1715 Identifier *idf2=rawpar->ptrbase;
1716 sdef.elements[i].raw.pointerbase=get_comp_index_byName(*idf2);
1717 } else sdef.elements[i].raw.pointerbase=i;
1718 }
1719 // building presence list
1720 for(int a=0;a<rawpar->presence.nElements;a++) {
1721 rawAST_coding_field_list* presences=
1722 sdef.elements[i].raw.presence.fields+a;
1723 presences->nElements=
1724 rawpar->presence.keyList[a].keyField->nElements;
1725 presences->value=rawpar->presence.keyList[a].value;
1726 presences->fields=(rawAST_coding_fields*)
1727 Malloc(presences->nElements*sizeof(rawAST_coding_fields));
1728 Type *t = this;
1729 for (int b = 0; b < presences->nElements; b++) {
1730 Identifier *idf = rawpar->presence.keyList[a].keyField->names[b];
1731 size_t comp_index = t->get_comp_index_byName(*idf);
1732 CompField *cf2 = t->get_comp_byIndex(comp_index);
1733 presences->fields[b].nthfield = comp_index;
1734 presences->fields[b].nthfieldname = idf->get_name().c_str();
1735 if (t->typetype == T_CHOICE_T)
1736 presences->fields[b].fieldtype = UNION_FIELD;
1737 else if (cf2->get_is_optional())
1738 presences->fields[b].fieldtype = OPTIONAL_FIELD;
1739 else presences->fields[b].fieldtype = MANDATORY_FIELD;
1740 Type *field_type = cf2->get_type();
1741 presences->fields[b].type =
1742 pool.add(field_type->get_genname_value(my_scope));
1743 presences->fields[b].typedescr =
1744 pool.add(field_type->get_genname_typedescriptor(my_scope));
1745 t = field_type->get_type_refd_last();
1746 }
1747 }
1748 // building crosstaglist
1749 for(int c=0;c<rawpar->crosstaglist.nElements;c++){
1750 if(rawpar->crosstaglist.tag[c].nElements)
1751 sdef.elements[i].raw.crosstaglist.list[c].fields=
1752 (rawAST_coding_field_list*)
1753 Malloc(rawpar->crosstaglist.tag[c].nElements
1754 *sizeof(rawAST_coding_field_list));
1755 else sdef.elements[i].raw.crosstaglist.list[c].fields=NULL;
1756 sdef.elements[i].raw.crosstaglist.list[c].nElements=
1757 rawpar->crosstaglist.tag[c].nElements;
1758 sdef.elements[i].raw.crosstaglist.list[c].fieldName=
1759 rawpar->crosstaglist.tag[c].fieldName->get_name().c_str();
1760 Identifier *idf=rawpar->crosstaglist.tag[c].fieldName;
1761 sdef.elements[i].raw.crosstaglist.list[c].fieldnum=
1762 t_field_last->get_comp_index_byName(*idf);
1763 sdef.elements[i].raw.crosstaglist.list[c].fieldnum=
1764 t_field_last->get_comp_index_byName(*idf);
1765 for(int a=0;a<rawpar->crosstaglist.tag[c].nElements;a++) {
1766 rawAST_coding_field_list* key=
1767 sdef.elements[i].raw.crosstaglist.list[c].fields+a;
1768 key->nElements=
1769 rawpar->crosstaglist.tag[c].keyList[a].keyField->nElements;
1770 key->value=rawpar->crosstaglist.tag[c].keyList[a].value;
1771 key->fields=(rawAST_coding_fields*)
1772 Malloc(key->nElements*sizeof(rawAST_coding_fields));
1773 Type *t = this;
1774 for (int b = 0; b < key->nElements; b++) {
1775 Identifier *idf2 =
1776 rawpar->crosstaglist.tag[c].keyList[a].keyField->names[b];
1777 size_t comp_index = t->get_comp_index_byName(*idf2);
1778 CompField *cf2 = t->get_comp_byIndex(comp_index);
1779 key->fields[b].nthfield = comp_index;
1780 key->fields[b].nthfieldname = idf2->get_name().c_str();
1781 if (t->typetype == T_CHOICE_T)
1782 key->fields[b].fieldtype = UNION_FIELD;
1783 else if (cf2->get_is_optional())
1784 key->fields[b].fieldtype = OPTIONAL_FIELD;
1785 else key->fields[b].fieldtype = MANDATORY_FIELD;
1786 Type *field_type = cf2->get_type();
1787 key->fields[b].type =
1788 pool.add(field_type->get_genname_value(my_scope));
1789 key->fields[b].typedescr =
1790 pool.add(field_type->get_genname_typedescriptor(my_scope));
1791 t = field_type->get_type_refd_last();
1792 }
1793 }
1794 }
1795 sdef.elements[i].raw.length = t_field->get_raw_length();
1796 sdef.elements[i].hasRaw=true;
1797 }
1798 else {
1799 sdef.elements[i].hasRaw=false;
1800 }
1801 }
1802 }
1803 else {
1804 for(size_t i = 0; i < sdef.totalElements; i++) {
1805 sdef.elements[i].hasRaw=false;
1806 }
1807 sdef.hasRaw=false;
1808 }
1809
1810 defRecordClass(&sdef, target);
1811 defRecordTemplate(&sdef, target);
1812
1813 for(size_t i = 0; i < sdef.totalElements; i++) {
1814 // free the array but not the strings
1815 if (sdef.elements[i].xerAnyNum > 0) Free(sdef.elements[i].xerAnyUris);
1816 } // next i
1817
1818 if (rawattrib) {
1819 free_raw_attrib_struct(&sdef.raw);
1820 for (size_t i = 0; i < sdef.totalElements; i++) {
1821 if (sdef.elements[i].hasRaw) {
1822 free_raw_attrib_struct(&sdef.elements[i].raw);
1823 }
1824 }
1825 }
1826 Free(sdef.elements);
1827 }
1828
1829 bool Type::is_untagged() const { return xerattrib && xerattrib->untagged_; }
1830
1831 void Type::generate_code_SeOf(output_struct *target)
1832 {
1833 const Type *oftypelast = u.seof.ofType->get_type_refd_last();
1834 const string& oftypename = u.seof.ofType->get_genname_value(my_scope);
1835 boolean optimized_memalloc = !use_runtime_2 && get_optimize_attribute() == "memalloc";
1836
1837 if (is_pregenerated()) {
1838 switch(oftypelast->typetype) {
1839 case T_USTR:
1840 case T_UTF8STRING:
1841 case T_TELETEXSTRING:
1842 case T_VIDEOTEXSTRING:
1843 case T_GRAPHICSTRING:
1844 case T_GENERALSTRING:
1845 case T_UNIVERSALSTRING:
1846 case T_BMPSTRING:
1847 case T_OBJECTDESCRIPTOR:
1848 target->header.typedefs = mputprintf(target->header.typedefs,
1849 "typedef PreGenRecordOf::PREGEN__%s__OF__UNIVERSAL__CHARSTRING%s %s;\n"
1850 "typedef PreGenRecordOf::PREGEN__%s__OF__UNIVERSAL__CHARSTRING%s_template %s_template;\n",
1851 (typetype == T_SEQOF) ? "RECORD" : "SET",
1852 optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str(),
1853 (typetype == T_SEQOF) ? "RECORD" : "SET",
1854 optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str());
1855 return;
1856 default:
1857 target->header.typedefs = mputprintf(target->header.typedefs,
1858 "typedef PreGenRecordOf::PREGEN__%s__OF__%s%s %s;\n"
1859 "typedef PreGenRecordOf::PREGEN__%s__OF__%s%s_template %s_template;\n",
1860 (typetype == T_SEQOF) ? "RECORD" : "SET", oftypename.c_str(),
1861 optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str(),
1862 (typetype == T_SEQOF) ? "RECORD" : "SET", oftypename.c_str(),
1863 optimized_memalloc ? "__OPTIMIZED" : "", get_genname_own().c_str());
1864 return;
1865 }
1866 }
1867
1868 stringpool pool;
1869 struct_of_def sofdef;
1870 memset(&sofdef, 0, sizeof(sofdef));
1871 sofdef.name = get_genname_own().c_str();
1872 sofdef.dispname = get_fullname().c_str();
1873 sofdef.kind = typetype == T_SEQOF ? RECORD_OF : SET_OF;
1874 sofdef.isASN1 = is_asn1();
1875 sofdef.hasText = textattrib!=NULL;
1876 sofdef.hasXer = has_encoding(CT_XER);
1877 sofdef.hasJson = has_encoding(CT_JSON);
1878 if (xerattrib) {
1879 //sofdef.xerList = xerattrib->list_;
1880 sofdef.xerAttribute = xerattrib->attribute_;
1881 }
1882 // If a record of UTF8String, we need to prepare for ANY-ATTRIBUTES and
1883 // ANY-ELEMENT
1884 sofdef.xerAnyAttrElem = oftypelast->typetype == T_USTR
1885 || oftypelast->typetype == T_UTF8STRING;
1886 sofdef.type = oftypename.c_str();
1887 sofdef.has_opentypes = get_has_opentypes();
1888 const string& oftypedescrname =
1889 u.seof.ofType->get_genname_typedescriptor(my_scope);
1890 sofdef.oftypedescrname = oftypedescrname.c_str();
1891
1892 if (xerattrib && xerattrib->untagged_
1893 && ((u.seof.ofType->xerattrib && has_ae(u.seof.ofType->xerattrib))
1894 || (xerattrib && has_ae(xerattrib)))) {
1895 // An untagged record-of which has an embedded type with ANY-ELEMENT,
1896 // or itself has ANY-ELEMENT
1897 if (parent_type && parent_type->typetype == T_SEQ_T) {
1898 /* The record-of needs to know the optional siblings following it,
1899 * to be able to stop consuming XML elements that belong
1900 * to the following fields. This is achieved by generating
1901 * a can_start() for the record-of which returns false for XML elements
1902 * that belong to those following fields. */
1903 size_t n_parent_comps = parent_type->get_nof_comps();
1904 boolean found_self = false;
1905 /* Go through the fields of the parent; skip everything until we find
1906 * the field that is this record-of; then collect fields until
1907 * the first non-disappearing field. */
1908 for (size_t pc = 0; pc < n_parent_comps; ++pc) {
1909 CompField *pcf = parent_type->get_comp_byIndex(pc); //"ParentCompField"
1910 Type *pcft = pcf->get_type();
1911 if (found_self) {
1912 const Identifier& cfid = pcf->get_name();
1913 sofdef.followers = (struct_field*)Realloc(sofdef.followers,
1914 (++sofdef.nFollowers) * sizeof(struct_field));
1915 sofdef.followers[sofdef.nFollowers-1].name = pool.add(cfid.get_name());
1916 sofdef.followers[sofdef.nFollowers-1].type =
1917 pool.add(pcft->get_genname_value(my_scope));
1918 sofdef.followers[sofdef.nFollowers-1].typegen =
1919 pool.add(pcft->get_genname_own());
1920
1921 Type *pcft_last = pcft->get_type_refd_last();
1922 if (pcf->get_is_optional()
1923 || (pcft->is_untagged() && pcft_last->has_empty_xml()))
1924 {} // can disappear, continue
1925 else break;
1926 }
1927 else if (pcft == this) found_self = true;
1928 } // next field
1929 } // if parent is record
1930 } // if A-E
1931
1932 switch (oftypelast->typetype) { // X.680/2002, Table 5 under 25.5
1933 // T_CHOICE_A and T_CHOICE_T do not set xmlValueList because choice types
1934 // already omit their own tag.
1935 case T_BOOL:
1936 case T_ENUM_A: case T_ENUM_T:
1937 case T_NULL:
1938 sofdef.xmlValueList = TRUE;
1939 break;
1940
1941 default:
1942 sofdef.xmlValueList = FALSE;
1943 break;
1944 }
1945
1946 if(rawattrib) {
1947 copy_rawAST_to_struct(rawattrib,&(sofdef.raw));
1948 sofdef.hasRaw=true;
1949 } else sofdef.hasRaw=false;
1950
1951 if (optimized_memalloc) {
1952 defRecordOfClassMemAllocOptimized(&sofdef, target);
1953 } else {
1954 defRecordOfClass(&sofdef, target);
1955 }
1956 defRecordOfTemplate(&sofdef, target);
1957
1958 if (sofdef.nFollowers) {
1959 Free(sofdef.followers);
1960 }
1961 }
1962
1963 void Type::generate_code_Array(output_struct *target)
1964 {
1965 if (!u.array.in_typedef) return;
1966 const char *own_name = get_genname_own().c_str();
1967 if (has_encoding(CT_JSON)) {
1968 target->header.class_decls = mputprintf(target->header.class_decls,
1969 "class %s;\n", own_name);
1970 target->header.class_defs = mputprintf(target->header.class_defs,
1971 "class %s : public %s {\n"
1972 "const TTCN_Typedescriptor_t* get_elem_descr() const;\n"
1973 "};\n\n",
1974 own_name,
1975 u.array.dimension->get_value_type(u.array.element_type, my_scope).c_str());
1976 target->source.class_defs = mputprintf(target->source.class_defs,
1977 "const TTCN_Typedescriptor_t* %s::get_elem_descr() const { return &%s_descr_; }\n\n",
1978 own_name, u.array.element_type->get_genname_typedescriptor(my_scope).c_str());
1979 } else {
1980 target->header.typedefs = mputprintf(target->header.typedefs,
1981 #ifndef NDEBUG
1982 "// written by %s in " __FILE__ " at %d\n"
1983 #endif
1984 "typedef %s %s;\n",
1985 #ifndef NDEBUG
1986 __FUNCTION__, __LINE__,
1987 #endif
1988 u.array.dimension->get_value_type(u.array.element_type, my_scope).c_str(),
1989 own_name);
1990 }
1991 target->header.typedefs = mputprintf(target->header.typedefs,
1992 "typedef %s %s_template;\n",
1993 u.array.dimension->get_template_type(u.array.element_type, my_scope).c_str(),
1994 own_name);
1995 }
1996
1997 void Type::generate_code_Fat(output_struct *target)
1998 {
1999 funcref_def fdef;
2000 memset(&fdef, 0, sizeof(fdef));
2001 fdef.name = get_genname_own().c_str();
2002 fdef.dispname = get_fullname().c_str();
2003 switch(typetype) {
2004 case T_FUNCTION:
2005 if(u.fatref.return_type)
2006 if(u.fatref.returns_template)
2007 fdef.return_type = mcopystr(u.fatref.return_type->
2008 get_genname_template(my_scope).c_str());
2009 else fdef.return_type = mcopystr(u.fatref.return_type->
2010 get_genname_value(my_scope).c_str());
2011 else fdef.return_type = NULL;
2012 fdef.type = FUNCTION;
2013 break;
2014 case T_ALTSTEP:
2015 fdef.return_type = NULL;
2016 fdef.type = ALTSTEP;
2017 break;
2018 case T_TESTCASE:
2019 fdef.return_type = NULL;
2020 fdef.type = TESTCASE;
2021 break;
2022 default:
2023 FATAL_ERROR("Type::generate_code_Fat()");
2024 }
2025 fdef.runs_on_self = u.fatref.runs_on.self ? TRUE : FALSE;
2026 fdef.is_startable = u.fatref.is_startable;
2027 fdef.formal_par_list = u.fatref.fp_list->generate_code(memptystr());
2028 u.fatref.fp_list->generate_code_defval(target);
2029 fdef.actual_par_list = u.fatref.fp_list
2030 ->generate_code_actual_parlist(memptystr(),"");
2031 if (typetype == T_TESTCASE) {
2032 if (u.fatref.fp_list->get_nof_fps() > 0) {
2033 fdef.formal_par_list = mputstr(fdef.formal_par_list, ", ");
2034 fdef.actual_par_list = mputstr(fdef.actual_par_list, ", ");
2035 }
2036 fdef.formal_par_list = mputstr(fdef.formal_par_list,
2037 "boolean has_timer, double timer_value");
2038 fdef.actual_par_list = mputstr(fdef.actual_par_list,
2039 "has_timer, timer_value");
2040 }
2041 fdef.nElements = u.fatref.fp_list->get_nof_fps();
2042 fdef.parameters = (const char**)
2043 Malloc(fdef.nElements * sizeof(*fdef.parameters));
2044 for(size_t i = 0;i < fdef.nElements; i++) {
2045 fdef.parameters[i] = u.fatref.fp_list->get_fp_byIndex(i)
2046 ->get_id().get_name().c_str();
2047 }
2048
2049 defFunctionrefClass(&fdef, target);
2050 defFunctionrefTemplate(&fdef, target);
2051 Free(fdef.return_type);
2052 Free(fdef.formal_par_list);
2053 Free(fdef.actual_par_list);
2054 Free(fdef.parameters);
2055 }
2056
2057 void Type::generate_code_Signature(output_struct *target)
2058 {
2059 stringpool pool;
2060 signature_def sdef;
2061 memset(&sdef, 0, sizeof(sdef));
2062 sdef.name = get_genname_own().c_str();
2063 sdef.dispname = get_fullname().c_str();
2064 if (u.signature.return_type) sdef.return_type =
2065 pool.add(u.signature.return_type->get_genname_value(my_scope));
2066 else sdef.return_type = NULL;
2067 if (u.signature.parameters) {
2068 sdef.parameters.nElements = u.signature.parameters->get_nof_params();
2069 sdef.parameters.elements = (signature_par*)
2070 Malloc(sdef.parameters.nElements * sizeof(*sdef.parameters.elements));
2071 for (size_t i = 0; i < sdef.parameters.nElements; i++) {
2072 SignatureParam *param = u.signature.parameters->get_param_byIndex(i);
2073 switch (param->get_direction()) {
2074 case SignatureParam::PARAM_IN:
2075 sdef.parameters.elements[i].direction = PAR_IN;
2076 break;
2077 case SignatureParam::PARAM_OUT:
2078 sdef.parameters.elements[i].direction = PAR_OUT;
2079 break;
2080 case SignatureParam::PARAM_INOUT:
2081 sdef.parameters.elements[i].direction = PAR_INOUT;
2082 break;
2083 default:
2084 FATAL_ERROR("Type::generate_code_Signature()");
2085 }
2086 sdef.parameters.elements[i].type =
2087 pool.add(param->get_type()->get_genname_value(my_scope));
2088 sdef.parameters.elements[i].name = param->get_id().get_name().c_str();
2089 sdef.parameters.elements[i].dispname =
2090 param->get_id().get_ttcnname().c_str();
2091 }
2092 } else {
2093 sdef.parameters.nElements = 0;
2094 sdef.parameters.elements = NULL;
2095 }
2096 sdef.is_noblock = u.signature.no_block;
2097 if (u.signature.exceptions) {
2098 sdef.exceptions.nElements = u.signature.exceptions->get_nof_types();
2099 sdef.exceptions.elements = (signature_exception*)
2100 Malloc(sdef.exceptions.nElements * sizeof(*sdef.exceptions.elements));
2101 for (size_t i = 0; i < sdef.exceptions.nElements; i++) {
2102 Type *type = u.signature.exceptions->get_type_byIndex(i);
2103 sdef.exceptions.elements[i].name =
2104 pool.add(type->get_genname_value(my_scope));
2105 sdef.exceptions.elements[i].dispname = pool.add(type->get_typename());
2106 sdef.exceptions.elements[i].altname = pool.add(type->get_genname_altname());
2107 }
2108 } else {
2109 sdef.exceptions.nElements = 0;
2110 sdef.exceptions.elements = NULL;
2111 }
2112 defSignatureClasses(&sdef, target);
2113 Free(sdef.parameters.elements);
2114 Free(sdef.exceptions.elements);
2115 }
2116
2117 bool Type::needs_alias()
2118 {
2119 /** The decision is actually based on the fullname of the type. If it
2120 * contains two or more dot (.) characters false is returned.
2121 * The following attributes cannot be used for the decision:
2122 * - parent_type, my_scope: types within ASN.1 object classes, objects
2123 * look the same as top-level aliased types, but they do not need alias. */
2124 const string& full_name = get_fullname();
2125 size_t fullname_len = full_name.size();
2126 size_t first_dot = full_name.find('.', 0);
2127 if (first_dot >= fullname_len) return true; // no dots
2128 else if (full_name.find('.', first_dot + 1) < fullname_len) return false;
2129 else return true;
2130 }
2131
2132
2133 void Type::generate_code_done(output_struct *target)
2134 {
2135 const string& t_genname = get_genname_value(my_scope);
2136 const char *genname_str = t_genname.c_str();
2137 const string& dispname = get_typename();
2138 const char *dispname_str = dispname.c_str();
2139 target->header.function_prototypes = mputprintf
2140 (target->header.function_prototypes,
2141 "extern alt_status done(const COMPONENT& component_reference, "
2142 "const %s_template& value_template, %s *value_ptr);\n",
2143 genname_str, genname_str);
2144 target->source.function_bodies = mputprintf
2145 (target->source.function_bodies,
2146 "alt_status done(const COMPONENT& component_reference, "
2147 "const %s_template& value_template, %s *value_ptr)\n"
2148 "{\n"
2149 "if (!component_reference.is_bound()) "
2150 "TTCN_error(\"Performing a done operation on an unbound component "
2151 "reference.\");\n"
2152 "Text_Buf *text_buf;\n"
2153 "alt_status ret_val = TTCN_Runtime::component_done("
2154 "(component)component_reference, \"%s\", text_buf);\n"
2155 "if (ret_val == ALT_YES) {\n"
2156 "%s return_value;\n"
2157 "return_value.decode_text(*text_buf);\n"
2158 "if (value_template.match(return_value)) {\n"
2159 "if (value_ptr != NULL) *value_ptr = return_value;\n"
2160 "TTCN_Logger::begin_event(TTCN_Logger::PARALLEL_PTC);\n"
2161 "TTCN_Logger::log_event_str(\"PTC with component reference \");\n"
2162 "component_reference.log();\n"
2163 "TTCN_Logger::log_event_str(\" is done. Return value: %s : \");\n"
2164 "return_value.log();\n"
2165 "TTCN_Logger::end_event();\n"
2166 "return ALT_YES;\n"
2167 "} else {\n"
2168 "if (TTCN_Logger::log_this_event(TTCN_Logger::MATCHING_DONE)) {\n"
2169 "TTCN_Logger::begin_event(TTCN_Logger::MATCHING_DONE);\n"
2170 "TTCN_Logger::log_event_str(\"Done operation with type %s on"
2171 " component reference \");\n"
2172 "component_reference.log();\n"
2173 "TTCN_Logger::log_event_str(\" failed: Return value does not match "
2174 "the template: \");\n"
2175 "value_template.log_match(return_value);\n"
2176 "TTCN_Logger::end_event();\n"
2177 "}\n"
2178 "return ALT_NO;\n"
2179 "}\n"
2180 "} else return ret_val;\n"
2181 "}\n\n",
2182 genname_str, genname_str, dispname_str, genname_str, dispname_str,
2183 dispname_str);
2184 }
2185
2186 bool Type::ispresent_anyvalue_embedded_field(Type* t,
2187 Ttcn::FieldOrArrayRefs *subrefs, size_t begin_index)
2188 {
2189 if (!subrefs) return true;
2190 size_t nof_refs = subrefs->get_nof_refs();
2191 for (size_t i = begin_index; i < nof_refs; i++) {
2192 t = t->get_type_refd_last();
2193 Ttcn::FieldOrArrayRef *ref = subrefs->get_ref(i);
2194 switch (ref->get_type()) {
2195 case Ttcn::FieldOrArrayRef::FIELD_REF: {
2196 CompField* cf = t->get_comp_byName(*ref->get_id());
2197 switch (t->typetype) {
2198 case T_CHOICE_T:
2199 case T_CHOICE_A:
2200 case T_OPENTYPE:
2201 case T_ANYTYPE:
2202 return false;
2203 case T_SEQ_T:
2204 case T_SET_T:
2205 case T_SEQ_A:
2206 case T_SET_A:
2207 if (cf->get_is_optional()) return false;
2208 break;
2209 default:
2210 FATAL_ERROR("Type::ispresent_anyvalue_embedded_field()");
2211 }
2212 t = cf->get_type();
2213 } break;
2214 case Ttcn::FieldOrArrayRef::ARRAY_REF:
2215 switch (t->typetype) {
2216 case T_SEQOF:
2217 case T_SETOF:
2218 return false; // (the existence of a record of element is optional)
2219 case T_ARRAY:
2220 t = t->u.array.element_type;
2221 break;
2222 default:
2223 return true; // string types
2224 }
2225 break;
2226 default:
2227 FATAL_ERROR("Type::ispresent_anyvalue_embedded_field()");
2228 }
2229 }
2230 return true;
2231 }
2232
2233 void Type::generate_code_ispresentbound(expression_struct *expr,
2234 Ttcn::FieldOrArrayRefs *subrefs, Common::Module* module,
2235 const string& global_id, const string& external_id, const bool is_template,
2236 const bool isbound)
2237 {
2238 if (!subrefs) return;
2239
2240 Type *t = this;
2241 Type *next_t;
2242 bool next_o; // next is optional value
2243 size_t nof_refs = subrefs->get_nof_refs();
2244 subrefs->clear_string_element_ref();
2245 char *tmp_generalid_str = mcopystr(external_id.c_str());
2246 expstring_t closing_brackets = memptystr(); //The closing parts collected
2247 for (size_t i = 0; i < nof_refs; i++) {
2248 t = t->get_type_refd_last();
2249 // stop immediately if current type t is erroneous
2250 // (e.g. because of circular reference)
2251 if (t->typetype == T_ERROR) return;
2252
2253 if (is_template) {
2254 bool anyval_ret_val = true;
2255 if (!isbound) {
2256 anyval_ret_val = ispresent_anyvalue_embedded_field(t, subrefs, i);
2257 }
2258 expr->expr = mputprintf(expr->expr, "if(%s) {\n",global_id.c_str());
2259 expr->expr = mputprintf(expr->expr,
2260 "switch (%s.get_selection()) {\n"
2261 "case UNINITIALIZED_TEMPLATE:\n"
2262 "%s = false;\n"
2263 "break;\n"
2264 "case ANY_VALUE:\n"
2265 "%s = %s;\n"
2266 "break;\n"
2267 "case SPECIFIC_VALUE: {\n",
2268 tmp_generalid_str, global_id.c_str(), global_id.c_str(),
2269 anyval_ret_val ? "true" : "false");
2270
2271 expstring_t closing_brackets_switch = mprintf(
2272 "break;}\n"
2273 "default:\n"
2274 "%s = false;\n"
2275 "break;\n"
2276 "}\n"
2277 "}\n"
2278 "%s",
2279 global_id.c_str(), closing_brackets);
2280 Free(closing_brackets);
2281 closing_brackets = closing_brackets_switch;
2282 }
2283
2284 Ttcn::FieldOrArrayRef *ref = subrefs->get_ref(i);
2285 switch (ref->get_type()) {
2286 case Ttcn::FieldOrArrayRef::FIELD_REF: {
2287 const Identifier& id = *ref->get_id();
2288 CompField* cf = t->get_comp_byName(id);
2289 next_t = cf->get_type();
2290 next_o = !is_template && cf->get_is_optional();
2291
2292 switch (t->typetype) {
2293 case T_CHOICE_A:
2294 case T_CHOICE_T:
2295 case T_OPENTYPE:
2296 expr->expr = mputprintf(expr->expr, "if(%s) {\n",global_id.c_str());
2297 expr->expr = mputprintf(expr->expr,
2298 "%s = %s.ischosen(%s::ALT_%s);\n", global_id.c_str(),
2299 tmp_generalid_str,
2300 t->get_genname_value(module).c_str(),
2301 id.get_name().c_str());
2302 expr->expr = mputstr(expr->expr, "}\n");
2303 // intentionally missing break
2304 case T_SEQ_A:
2305 case T_SEQ_T:
2306 case T_SET_A:
2307 case T_SET_T:
2308 case T_ANYTYPE:
2309 break;
2310 default:
2311 FATAL_ERROR("Type::generate_code_isbound()");
2312 }
2313
2314 if (next_o) {
2315 expr->expr = mputprintf(expr->expr, "if(%s) {\n",global_id.c_str());
2316 expstring_t closing_brackets2 = mprintf("}\n%s", closing_brackets);
2317 Free(closing_brackets);
2318 closing_brackets = closing_brackets2;
2319
2320 const string& tmp_id = module->get_temporary_id();
2321 const char *tmp_id_str = tmp_id.c_str();
2322 expr->expr = mputprintf(expr->expr,
2323 "const OPTIONAL<%s%s>& %s = %s.%s();\n",
2324 next_t->get_genname_value(module).c_str(),
2325 is_template?"_template":"", tmp_id_str, tmp_generalid_str,
2326 id.get_name().c_str());
2327
2328 if (i==(nof_refs-1)) {
2329 // we are at the end of the reference chain
2330 expr->expr = mputprintf(expr->expr,
2331 "switch (%s.get_selection()) {\n"
2332 "case OPTIONAL_UNBOUND:\n"
2333 "%s = false;\n"
2334 "break;\n"
2335 "case OPTIONAL_OMIT:\n"
2336 "%s = %s;\n"
2337 "break;\n"
2338 "default:\n",
2339 tmp_id_str, global_id.c_str(),global_id.c_str(),
2340 isbound ? "true" : "false");
2341 Free(tmp_generalid_str);
2342 tmp_generalid_str = mcopystr(tmp_id_str);
2343
2344 expr->expr = mputstr(expr->expr, "{\n");
2345 const string& tmp_id2 = module->get_temporary_id();
2346 const char *tmp_id2_str = tmp_id2.c_str();
2347 expr->expr = mputprintf(expr->expr,
2348 "const %s%s& %s = (const %s%s&) %s;\n",
2349 next_t->get_genname_value(module).c_str(),
2350 is_template?"_template":"", tmp_id2_str,
2351 next_t->get_genname_value(module).c_str(),
2352 is_template?"_template":"", tmp_id_str);
2353
2354 expr->expr = mputprintf(expr->expr,
2355 "%s = %s.%s();\n", global_id.c_str(),
2356 tmp_id2_str, isbound ? "is_bound" : "is_present");
2357 Free(tmp_generalid_str);
2358 tmp_generalid_str = mcopystr(tmp_id2_str);
2359
2360 expr->expr = mputprintf(expr->expr,
2361 "break;}\n"
2362 "}\n");
2363 } else {
2364 expr->expr = mputprintf(expr->expr,
2365 "switch (%s.get_selection()) {\n"
2366 "case OPTIONAL_UNBOUND:\n"
2367 "case OPTIONAL_OMIT:\n"
2368 "%s = false;\n"
2369 "break;\n"
2370 "default:\n"
2371 "break;\n"
2372 "}\n",
2373 tmp_id_str, global_id.c_str());
2374 Free(tmp_generalid_str);
2375 tmp_generalid_str = mcopystr(tmp_id_str);
2376
2377 expr->expr = mputprintf(expr->expr, "if(%s) {\n",global_id.c_str());
2378 closing_brackets2 = mprintf("}\n%s", closing_brackets);
2379 Free(closing_brackets);
2380 closing_brackets = closing_brackets2;
2381
2382 const string& tmp_id2 = module->get_temporary_id();
2383 const char *tmp_id2_str = tmp_id2.c_str();
2384 expr->expr = mputprintf(expr->expr,
2385 "const %s%s& %s = (const %s%s&) %s;\n",
2386 next_t->get_genname_value(module).c_str(),
2387 is_template?"_template":"", tmp_id2_str,
2388 next_t->get_genname_value(module).c_str(),
2389 is_template?"_template":"", tmp_id_str);
2390
2391 expr->expr = mputprintf(expr->expr,
2392 "%s = %s.is_bound();\n", global_id.c_str(),
2393 tmp_id2_str);
2394 Free(tmp_generalid_str);
2395 tmp_generalid_str = mcopystr(tmp_id2_str);
2396 }
2397 } else {
2398 expr->expr = mputprintf(expr->expr, "if(%s) {\n",global_id.c_str());
2399 expstring_t closing_brackets2 = mprintf("}\n%s", closing_brackets);
2400 Free(closing_brackets);
2401 closing_brackets = closing_brackets2;
2402
2403 const string& tmp_id = module->get_temporary_id();
2404 const char *tmp_id_str = tmp_id.c_str();
2405 expr->expr = mputprintf(expr->expr,
2406 "const %s%s& %s = %s.%s();\n",
2407 next_t->get_genname_value(module).c_str(),
2408 is_template?"_template":"", tmp_id_str, tmp_generalid_str,
2409 id.get_name().c_str());
2410
2411 expr->expr = mputprintf(expr->expr,
2412 "%s = %s.%s();\n", global_id.c_str(),
2413 tmp_id_str, isbound||(i!=(nof_refs-1)) ? "is_bound" : "is_present");
2414 Free(tmp_generalid_str);
2415 tmp_generalid_str = mcopystr(tmp_id_str);
2416 }
2417
2418 t = next_t;
2419 break; }
2420 case Ttcn::FieldOrArrayRef::ARRAY_REF: {
2421 Type *embedded_type = 0;
2422 bool is_string = true;
2423 bool is_string_element = false;
2424 switch (t->typetype) {
2425 case T_SEQOF:
2426 case T_SETOF:
2427 embedded_type = t->u.seof.ofType;
2428 is_string = false;
2429 break;
2430 case T_ARRAY:
2431 embedded_type = t->u.array.element_type;
2432 is_string = false;
2433 break;
2434 case T_BSTR:
2435 case T_BSTR_A:
2436 case T_HSTR:
2437 case T_OSTR:
2438 case T_CSTR:
2439 case T_USTR:
2440 case T_UTF8STRING:
2441 case T_NUMERICSTRING:
2442 case T_PRINTABLESTRING:
2443 case T_TELETEXSTRING:
2444 case T_VIDEOTEXSTRING:
2445 case T_IA5STRING:
2446 case T_GRAPHICSTRING:
2447 case T_VISIBLESTRING:
2448 case T_GENERALSTRING:
2449 case T_UNIVERSALSTRING:
2450 case T_BMPSTRING:
2451 case T_UTCTIME:
2452 case T_GENERALIZEDTIME:
2453 case T_OBJECTDESCRIPTOR:
2454 if (subrefs->refers_to_string_element()) {
2455 FATAL_ERROR("Type::generate_code_isbound()");
2456 } else {
2457 subrefs->set_string_element_ref();
2458 // string elements have the same type as the string itself
2459 embedded_type = t;
2460 is_string_element = true;
2461 break;
2462 }
2463 default:
2464 FATAL_ERROR("Type::generate_code_isbound()");
2465 }
2466
2467 next_t = embedded_type;
2468
2469 // check the index value
2470 Value *index_value = ref->get_val();
2471 Value *v_last = index_value->get_value_refd_last();
2472
2473 const string& tmp_index_id = module->get_temporary_id();
2474 const char *tmp_index_id_str = tmp_index_id.c_str();
2475 expr->expr = mputprintf(expr->expr, "if(%s) {\n",global_id.c_str());
2476
2477 expstring_t closing_brackets2 = mprintf("}\n%s", closing_brackets);
2478 Free(closing_brackets);
2479 closing_brackets = closing_brackets2;
2480
2481 expr->expr = mputprintf(expr->expr, "const int %s = ", tmp_index_id_str);
2482 v_last->generate_code_expr_mandatory(expr);
2483 expr->expr = mputstr(expr->expr, ";\n");
2484 expr->expr = mputprintf(expr->expr, "%s = (%s >= 0) && (%s.%s > %s);\n",
2485 global_id.c_str(), tmp_index_id_str, tmp_generalid_str,
2486 is_string ? "lengthof()": ( is_template ? "n_elem()" : "size_of()" ),
2487 tmp_index_id_str);
2488 expr->expr = mputprintf(expr->expr, "if(%s) {\n",global_id.c_str());
2489
2490 closing_brackets2 = mprintf("}\n%s", closing_brackets);
2491 Free(closing_brackets);
2492 closing_brackets = closing_brackets2;
2493
2494 const string& tmp_id = module->get_temporary_id();
2495 const char *tmp_id_str = tmp_id.c_str();
2496
2497 if (is_string_element) {
2498 expr->expr = mputprintf(expr->expr,
2499 "%s = %s[%s].%s();\n", global_id.c_str(),
2500 tmp_generalid_str, tmp_index_id_str,
2501 isbound||(i!=(nof_refs-1)) ? "is_bound" : "is_present");
2502 } else {
2503 if (is_template) {
2504 expr->expr = mputprintf(expr->expr,
2505 "const %s& %s = %s[%s];\n",
2506 next_t->get_genname_template(module).c_str(),
2507 tmp_id_str, tmp_generalid_str,
2508 tmp_index_id_str);
2509 } else {
2510 expr->expr = mputprintf(expr->expr,
2511 "const %s%s& %s = %s[%s];\n",
2512 next_t->get_genname_value(module).c_str(),
2513 is_template?"_template":"", tmp_id_str, tmp_generalid_str,
2514 tmp_index_id_str);
2515 }
2516
2517 expr->expr = mputprintf(expr->expr,
2518 "%s = %s.%s();\n", global_id.c_str(), tmp_id_str,
2519 isbound||(i!=(nof_refs-1)) ? "is_bound" : "is_present");
2520 }
2521
2522 Free(tmp_generalid_str);
2523 tmp_generalid_str = mcopystr(tmp_id_str);
2524
2525 // change t to the embedded type
2526 t = next_t;
2527 break; }
2528 default:
2529 FATAL_ERROR("Type::generate_code_isbound(): invalid reference type");
2530 }
2531 }
2532
2533 Free(tmp_generalid_str);
2534 expr->expr = mputstr(expr->expr, closing_brackets);
2535 Free(closing_brackets);
2536 }
2537
2538 string Type::get_optimize_attribute()
2539 {
2540 if(w_attrib_path)
2541 {
2542 vector<SingleWithAttrib> const &real_attribs
2543 = w_attrib_path->get_real_attrib();
2544 for (size_t i = 0; i < real_attribs.size(); i++) {
2545 SingleWithAttrib * temp_single = real_attribs[i];
2546 if (temp_single->get_attribKeyword()
2547 == SingleWithAttrib::AT_EXTENSION
2548 && (!temp_single->get_attribQualifiers()
2549 || (temp_single->get_attribQualifiers()
2550 ->get_nof_qualifiers() == 0)))
2551 {
2552 const string& spec = temp_single->get_attribSpec().get_spec();
2553 // TODO: use a real parser to allow whitespaces, etc.
2554 if (spec.find("optimize:")==0 && spec.size()>9)
2555 {
2556 string spec_optimize_for_what = spec.substr(9);
2557 return spec_optimize_for_what;
2558 }
2559 }
2560 }
2561 }
2562 return string();
2563 }
2564
2565 string Type::get_sourcefile_attribute()
2566 {
2567 if(w_attrib_path)
2568 {
2569 vector<SingleWithAttrib> const &real_attribs
2570 = w_attrib_path->get_real_attrib();
2571
2572 for (size_t i = 0; i < real_attribs.size(); i++) {
2573 SingleWithAttrib * temp_single = real_attribs[i];
2574 if (temp_single->get_attribKeyword()
2575 == SingleWithAttrib::AT_EXTENSION
2576 && (!temp_single->get_attribQualifiers()
2577 || (temp_single->get_attribQualifiers()
2578 ->get_nof_qualifiers() == 0)))
2579 {
2580 const string& spec = temp_single->get_attribSpec().get_spec();
2581 if (spec.find("sourcefile:")==0 && spec.size()>11)
2582 {
2583 string spec_filename = spec.substr(11);
2584 // TODO: check if string can be a valid filename
2585 return spec_filename;
2586 }
2587 }
2588 }
2589 }
2590 return string();
2591 }
2592
2593 bool Type::has_done_attribute()
2594 {
2595 if(w_attrib_path)
2596 {
2597 vector<SingleWithAttrib> const &real_attribs
2598 = w_attrib_path->get_real_attrib();
2599
2600 for (size_t i = 0; i < real_attribs.size(); i++) {
2601 SingleWithAttrib * temp_single = real_attribs[i];
2602 if (temp_single->get_attribKeyword()
2603 == SingleWithAttrib::AT_EXTENSION
2604 && (!temp_single->get_attribQualifiers()
2605 || (temp_single->get_attribQualifiers()
2606 ->get_nof_qualifiers() == 0))
2607 && temp_single->get_attribSpec().get_spec() == "done")
2608 {
2609 return true;
2610 }
2611 }
2612 }
2613 return false;
2614 }
2615
2616 void Type::generate_code_object(const_def *cdef, Scope *p_scope,
2617 const string& name, const char *prefix, bool is_template)
2618 {
2619 string type_name;
2620 if (is_template) type_name = get_genname_template(p_scope);
2621 else type_name = get_genname_value(p_scope);
2622 const char *name_str = name.c_str();
2623 const char *type_name_str = type_name.c_str();
2624 if (prefix) {
2625 cdef->decl = mputprintf(cdef->decl, "extern const %s& %s;\n",
2626 type_name_str, name_str);
2627 cdef->def = mputprintf(cdef->def, "static %s %s%s;\n"
2628 "const %s& %s = %s%s;\n", type_name_str, prefix, name_str,
2629 type_name_str, name_str, prefix, name_str);
2630 } else {
2631 cdef->decl = mputprintf(cdef->decl, "extern %s %s;\n",
2632 type_name_str, name_str);
2633 cdef->def = mputprintf(cdef->def, "%s %s;\n",
2634 type_name_str, name_str);
2635 }
2636 }
2637
2638 void Type::generate_code_object(const_def *cdef, GovernedSimple *p_setting)
2639 {
2640 bool is_template = false;
2641 switch (p_setting->get_st()) {
2642 case S_TEMPLATE:
2643 is_template = true;
2644 break;
2645 case S_V:
2646 break;
2647 default:
2648 FATAL_ERROR("Type::generate_code_object()");
2649 }
2650 if (p_setting->get_err_descr()) {
2651 cdef->def = p_setting->get_err_descr()->generate_code_str(cdef->def,
2652 p_setting->get_genname_prefix() + p_setting->get_genname_own());
2653 }
2654 generate_code_object(cdef, p_setting->get_my_scope(),
2655 p_setting->get_genname_own(), p_setting->get_genname_prefix(),
2656 is_template);
2657 }
2658
2659 void Type::generate_json_schema(JSON_Tokenizer& json, bool embedded, bool as_value)
2660 {
2661 // add a new property for the type if it has its own definition
2662 if (!embedded) {
2663 json.put_next_token(JSON_TOKEN_NAME, get_dispname().c_str());
2664 }
2665
2666 // create an object containing the type's schema
2667 json.put_next_token(JSON_TOKEN_OBJECT_START);
2668
2669 // if this is a field of a record/set/union with an alias, the field's
2670 // original name must be stored ("originalName" property), it also needs to be
2671 // stored if this is a field of a union with the "as value" coding instruction
2672 if (ownertype == OT_COMP_FIELD) {
2673 CompField* cf = static_cast<CompField*>(owner);
2674 if (as_value || (cf->get_type()->jsonattrib != NULL
2675 && cf->get_type()->jsonattrib->alias != NULL)) {
2676 json.put_next_token(JSON_TOKEN_NAME, "originalName");
2677 char* field_str = mprintf("\"%s\"", cf->get_name().get_ttcnname().c_str());
2678 json.put_next_token(JSON_TOKEN_STRING, field_str);
2679 Free(field_str);
2680 }
2681
2682 // if the parent is a union with the "as value" coding instruction AND the field
2683 // has an alias, then the alias needs to be stored as well ("unusedAlias" property)
2684 if (as_value && cf->get_type()->jsonattrib != NULL
2685 && cf->get_type()->jsonattrib->alias != NULL) {
2686 json.put_next_token(JSON_TOKEN_NAME, "unusedAlias");
2687 char* alias_str = mprintf("\"%s\"", cf->get_type()->jsonattrib->alias);
2688 json.put_next_token(JSON_TOKEN_STRING, alias_str);
2689 Free(alias_str);
2690 }
2691 }
2692
2693 // get the type at the end of the reference chain
2694 Type* last = get_type_refd_last();
2695
2696 // if the type has its own definition and it's embedded in another type, then
2697 // its schema already exists, only add a reference to it
2698 // exception: instances of ASN.1 parameterized types, always embed their schemas
2699 if (embedded && (!is_ref() || !get_type_refd()->pard_type_instance) &&
2700 (last->ownertype == OT_TYPE_DEF /* TTCN-3 type definition */
2701 || last->ownertype == OT_TYPE_ASS /* ASN.1 type assignment */ )) {
2702 json.put_next_token(JSON_TOKEN_NAME, "$ref");
2703 char* ref_str = mprintf("\"#/definitions/%s/%s\"",
2704 last->my_scope->get_scope_mod()->get_modid().get_ttcnname().c_str(),
2705 (is_ref() && last->pard_type_instance) ? get_type_refd()->get_dispname().c_str() : last->get_dispname().c_str());
2706 json.put_next_token(JSON_TOKEN_STRING, ref_str);
2707 Free(ref_str);
2708 } else {
2709 // generate the schema for the referenced type
2710 switch (last->typetype) {
2711 case T_BOOL:
2712 // use the JSON boolean type
2713 json.put_next_token(JSON_TOKEN_NAME, "type");
2714 json.put_next_token(JSON_TOKEN_STRING, "\"boolean\"");
2715 break;
2716 case T_INT:
2717 case T_INT_A:
2718 // use the JSON integer type
2719 json.put_next_token(JSON_TOKEN_NAME, "type");
2720 json.put_next_token(JSON_TOKEN_STRING, "\"integer\"");
2721 break;
2722 case T_REAL:
2723 // any of: JSON number or the special values as strings (in an enum)
2724 json.put_next_token(JSON_TOKEN_NAME, "anyOf");
2725 json.put_next_token(JSON_TOKEN_ARRAY_START);
2726 json.put_next_token(JSON_TOKEN_OBJECT_START);
2727 json.put_next_token(JSON_TOKEN_NAME, "type");
2728 json.put_next_token(JSON_TOKEN_STRING, "\"number\"");
2729 json.put_next_token(JSON_TOKEN_OBJECT_END);
2730 json.put_next_token(JSON_TOKEN_OBJECT_START);
2731 json.put_next_token(JSON_TOKEN_NAME, "enum");
2732 json.put_next_token(JSON_TOKEN_ARRAY_START);
2733 json.put_next_token(JSON_TOKEN_STRING, "\"not_a_number\"");
2734 json.put_next_token(JSON_TOKEN_STRING, "\"infinity\"");
2735 json.put_next_token(JSON_TOKEN_STRING, "\"-infinity\"");
2736 json.put_next_token(JSON_TOKEN_ARRAY_END);
2737 json.put_next_token(JSON_TOKEN_OBJECT_END);
2738 json.put_next_token(JSON_TOKEN_ARRAY_END);
2739 break;
2740 case T_BSTR:
2741 case T_BSTR_A:
2742 case T_HSTR:
2743 case T_OSTR:
2744 case T_ANY:
2745 // use the JSON string type and add a pattern to only allow bits or hex digits
2746 json.put_next_token(JSON_TOKEN_NAME, "type");
2747 json.put_next_token(JSON_TOKEN_STRING, "\"string\"");
2748 json.put_next_token(JSON_TOKEN_NAME, "subType");
2749 json.put_next_token(JSON_TOKEN_STRING,
2750 (last->typetype == T_OSTR || last->typetype == T_ANY) ? "\"octetstring\"" :
2751 ((last->typetype == T_HSTR) ? "\"hexstring\"" : "\"bitstring\""));
2752 json.put_next_token(JSON_TOKEN_NAME, "pattern");
2753 json.put_next_token(JSON_TOKEN_STRING,
2754 (last->typetype == T_OSTR || last->typetype == T_ANY) ? "\"^([0-9A-Fa-f][0-9A-Fa-f])*$\"" :
2755 ((last->typetype == T_HSTR) ? "\"^[0-9A-Fa-f]*$\"" : "\"^[01]*$\""));
2756 break;
2757 case T_CSTR:
2758 case T_NUMERICSTRING:
2759 case T_PRINTABLESTRING:
2760 case T_IA5STRING:
2761 case T_VISIBLESTRING:
2762 // use the JSON string type and add a "subType" property to distinguish it from
2763 // universal charstring types
2764 json.put_next_token(JSON_TOKEN_NAME, "type");
2765 json.put_next_token(JSON_TOKEN_STRING, "\"string\"");
2766 json.put_next_token(JSON_TOKEN_NAME, "subType");
2767 json.put_next_token(JSON_TOKEN_STRING, "\"charstring\"");
2768 break;
2769 case T_USTR:
2770 case T_GENERALSTRING:
2771 case T_UNIVERSALSTRING:
2772 case T_UTF8STRING:
2773 case T_BMPSTRING:
2774 case T_GRAPHICSTRING:
2775 case T_TELETEXSTRING:
2776 case T_VIDEOTEXSTRING:
2777 // use the JSON string type and add a "subType" property to distinguish it from
2778 // charstring types
2779 json.put_next_token(JSON_TOKEN_NAME, "type");
2780 json.put_next_token(JSON_TOKEN_STRING, "\"string\"");
2781 json.put_next_token(JSON_TOKEN_NAME, "subType");
2782 json.put_next_token(JSON_TOKEN_STRING, "\"universal charstring\"");
2783 break;
2784 case T_OID:
2785 case T_ROID:
2786 json.put_next_token(JSON_TOKEN_NAME, "type");
2787 json.put_next_token(JSON_TOKEN_STRING, "\"string\"");
2788 json.put_next_token(JSON_TOKEN_NAME, "subType");
2789 json.put_next_token(JSON_TOKEN_STRING, "\"objid\"");
2790 json.put_next_token(JSON_TOKEN_NAME, "pattern");
2791 json.put_next_token(JSON_TOKEN_STRING, "\"^[0-2][.][1-3]?[0-9]([.][0-9]|([1-9][0-9]+))*$\"");
2792 break;
2793 case T_VERDICT:
2794 // enumerate the possible values
2795 json.put_next_token(JSON_TOKEN_NAME, "enum");
2796 json.put_next_token(JSON_TOKEN_ARRAY_START);
2797 json.put_next_token(JSON_TOKEN_STRING, "\"none\"");
2798 json.put_next_token(JSON_TOKEN_STRING, "\"pass\"");
2799 json.put_next_token(JSON_TOKEN_STRING, "\"inconc\"");
2800 json.put_next_token(JSON_TOKEN_STRING, "\"fail\"");
2801 json.put_next_token(JSON_TOKEN_STRING, "\"error\"");
2802 json.put_next_token(JSON_TOKEN_ARRAY_END);
2803 break;
2804 case T_ENUM_T:
2805 case T_ENUM_A:
2806 // enumerate the possible values
2807 json.put_next_token(JSON_TOKEN_NAME, "enum");
2808 json.put_next_token(JSON_TOKEN_ARRAY_START);
2809 for (size_t i = 0; i < last->u.enums.eis->get_nof_eis(); ++i) {
2810 char* enum_str = mprintf("\"%s\"", last->get_ei_byIndex(i)->get_name().get_ttcnname().c_str());
2811 json.put_next_token(JSON_TOKEN_STRING, enum_str);
2812 Free(enum_str);
2813 }
2814 json.put_next_token(JSON_TOKEN_ARRAY_END);
2815 // list the numeric values for the enumerated items
2816 json.put_next_token(JSON_TOKEN_NAME, "numericValues");
2817 json.put_next_token(JSON_TOKEN_ARRAY_START);
2818 for (size_t i = 0; i < last->u.enums.eis->get_nof_eis(); ++i) {
2819 char* num_val_str = mprintf("%lli", last->get_ei_byIndex(i)->get_value()->get_val_Int()->get_val());
2820 json.put_next_token(JSON_TOKEN_NUMBER, num_val_str);
2821 Free(num_val_str);
2822 }
2823 json.put_next_token(JSON_TOKEN_ARRAY_END);
2824 break;
2825 case T_NULL:
2826 // use the JSON null value for the ASN.1 NULL type
2827 json.put_next_token(JSON_TOKEN_NAME, "type");
2828 json.put_next_token(JSON_TOKEN_STRING, "\"null\"");
2829 break;
2830 case T_SEQOF:
2831 case T_SETOF:
2832 case T_ARRAY:
2833 last->generate_json_schema_array(json);
2834 break;
2835 case T_SEQ_T:
2836 case T_SEQ_A:
2837 case T_SET_T:
2838 case T_SET_A:
2839 last->generate_json_schema_record(json);
2840 break;
2841 case T_CHOICE_T:
2842 case T_CHOICE_A:
2843 case T_ANYTYPE:
2844 case T_OPENTYPE:
2845 last->generate_json_schema_union(json);
2846 break;
2847 default:
2848 FATAL_ERROR("Type::generate_json_schema");
2849 }
2850 }
2851
2852 // insert default value (if any)
2853 if (jsonattrib != NULL && jsonattrib->default_value != NULL) {
2854 json.put_next_token(JSON_TOKEN_NAME, "default");
2855 switch (last->typetype) {
2856 case T_BOOL:
2857 json.put_next_token((jsonattrib->default_value[0] == 't') ?
2858 JSON_TOKEN_LITERAL_TRUE : JSON_TOKEN_LITERAL_FALSE);
2859 break;
2860 case T_INT:
2861 case T_REAL:
2862 if (jsonattrib->default_value[0] != 'n' && jsonattrib->default_value[0] != 'i'
2863 && jsonattrib->default_value[1] != 'i') {
2864 json.put_next_token(JSON_TOKEN_NUMBER, jsonattrib->default_value);
2865 break;
2866 }
2867 // no break, insert the special float values as strings
2868 case T_BSTR:
2869 case T_HSTR:
2870 case T_OSTR:
2871 case T_CSTR:
2872 case T_USTR:
2873 case T_VERDICT:
2874 case T_ENUM_T: {
2875 char* default_str = mprintf("\"%s\"", jsonattrib->default_value);
2876 json.put_next_token(JSON_TOKEN_STRING, default_str);
2877 Free(default_str);
2878 break; }
2879 default:
2880 FATAL_ERROR("Type::generate_json_schema");
2881 }
2882 }
2883
2884 // end of type's schema
2885 json.put_next_token(JSON_TOKEN_OBJECT_END);
2886 }
2887
2888 void Type::generate_json_schema_array(JSON_Tokenizer& json)
2889 {
2890 // use the JSON array type
2891 json.put_next_token(JSON_TOKEN_NAME, "type");
2892 json.put_next_token(JSON_TOKEN_STRING, "\"array\"");
2893
2894 if (typetype != T_ARRAY) {
2895 // use the "subType" property to distinguish 'record of' from 'set of'
2896 json.put_next_token(JSON_TOKEN_NAME, "subType");
2897 json.put_next_token(JSON_TOKEN_STRING, (typetype == T_SEQOF) ?
2898 "\"record of\"" : "\"set of\"");
2899 } else {
2900 // set the number of elements for arrays
2901 char* size_str = mprintf("%lu", get_nof_comps());
2902 json.put_next_token(JSON_TOKEN_NAME, "minItems");
2903 json.put_next_token(JSON_TOKEN_NUMBER, size_str);
2904 json.put_next_token(JSON_TOKEN_NAME, "maxItems");
2905 json.put_next_token(JSON_TOKEN_NUMBER, size_str);
2906 Free(size_str);
2907 }
2908
2909 // set the element type
2910 json.put_next_token(JSON_TOKEN_NAME, "items");
2911
2912 // pass the tokenizer to the elements' type object to insert its schema
2913 get_ofType()->generate_json_schema(json, true, false);
2914 }
2915
2916 void Type::generate_json_schema_record(JSON_Tokenizer& json)
2917 {
2918 // use the JSON object type
2919 json.put_next_token(JSON_TOKEN_NAME, "type");
2920 json.put_next_token(JSON_TOKEN_STRING, "\"object\"");
2921
2922 // use the "subType" property to distinguish records from sets
2923 json.put_next_token(JSON_TOKEN_NAME, "subType");
2924 json.put_next_token(JSON_TOKEN_STRING, (typetype == T_SEQ_T || typetype == T_SEQ_A) ?
2925 "\"record\"" : "\"set\"");
2926
2927 // set the fields
2928 json.put_next_token(JSON_TOKEN_NAME, "properties");
2929 json.put_next_token(JSON_TOKEN_OBJECT_START);
2930 size_t field_count = get_nof_comps();
2931 bool has_non_optional = false;
2932 for (size_t i = 0; i < field_count; ++i) {
2933 Type* field = get_comp_byIndex(i)->get_type();
2934
2935 // use the field's alias if it has one
2936 json.put_next_token(JSON_TOKEN_NAME,
2937 (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
2938 field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
2939
2940 // optional fields can also get the JSON null value
2941 if (get_comp_byIndex(i)->get_is_optional()) {
2942 // special case: ASN NULL type, since it uses the JSON literal "null" as a value
2943 if (T_NULL != field->get_type_refd_last()->typetype) {
2944 json.put_next_token(JSON_TOKEN_OBJECT_START);
2945 json.put_next_token(JSON_TOKEN_NAME, "anyOf");
2946 json.put_next_token(JSON_TOKEN_ARRAY_START);
2947 json.put_next_token(JSON_TOKEN_OBJECT_START);
2948 json.put_next_token(JSON_TOKEN_NAME, "type");
2949 json.put_next_token(JSON_TOKEN_STRING, "\"null\"");
2950 json.put_next_token(JSON_TOKEN_OBJECT_END);
2951 }
2952 } else if (!has_non_optional) {
2953 has_non_optional = true;
2954 }
2955
2956 // pass the tokenizer to the field's type to insert its schema
2957 field->generate_json_schema(json, true, false);
2958
2959 // for optional fields: specify the presence of the "omit as null" coding instruction
2960 // and close structures
2961 if (get_comp_byIndex(i)->get_is_optional() &&
2962 T_NULL != field->get_type_refd_last()->typetype) {
2963 json.put_next_token(JSON_TOKEN_ARRAY_END);
2964 json.put_next_token(JSON_TOKEN_NAME, "omitAsNull");
2965 json.put_next_token((field->jsonattrib != NULL && field->jsonattrib->omit_as_null) ?
2966 JSON_TOKEN_LITERAL_TRUE : JSON_TOKEN_LITERAL_FALSE);
2967 json.put_next_token(JSON_TOKEN_OBJECT_END);
2968 }
2969 }
2970
2971 // end of properties
2972 json.put_next_token(JSON_TOKEN_OBJECT_END);
2973
2974 // do not accept additional fields
2975 json.put_next_token(JSON_TOKEN_NAME, "additionalProperties");
2976 json.put_next_token(JSON_TOKEN_LITERAL_FALSE);
2977
2978 // set the field order
2979 if (field_count > 1) {
2980 json.put_next_token(JSON_TOKEN_NAME, "fieldOrder");
2981 json.put_next_token(JSON_TOKEN_ARRAY_START);
2982 for (size_t i = 0; i < field_count; ++i) {
2983 Type* field = get_comp_byIndex(i)->get_type();
2984 // use the field's alias if it has one
2985 char* field_str = mprintf("\"%s\"",
2986 (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
2987 field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
2988 json.put_next_token(JSON_TOKEN_STRING, field_str);
2989 Free(field_str);
2990 }
2991 json.put_next_token(JSON_TOKEN_ARRAY_END);
2992 }
2993
2994 // set the required (non-optional) fields
2995 if (has_non_optional) {
2996 json.put_next_token(JSON_TOKEN_NAME, "required");
2997 json.put_next_token(JSON_TOKEN_ARRAY_START);
2998 for (size_t i = 0; i < field_count; ++i) {
2999 if (!get_comp_byIndex(i)->get_is_optional()) {
3000 Type* field = get_comp_byIndex(i)->get_type();
3001 // use the field's alias if it has one
3002 char* field_str = mprintf("\"%s\"",
3003 (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
3004 field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
3005 json.put_next_token(JSON_TOKEN_STRING, field_str);
3006 Free(field_str);
3007 }
3008 }
3009 json.put_next_token(JSON_TOKEN_ARRAY_END);
3010 }
3011 }
3012
3013 void Type::generate_json_schema_union(JSON_Tokenizer& json)
3014 {
3015 // use an "anyOf" structure containing the union's alternatives
3016 json.put_next_token(JSON_TOKEN_NAME, "anyOf");
3017 json.put_next_token(JSON_TOKEN_ARRAY_START);
3018
3019 for (size_t i = 0; i < get_nof_comps(); ++i) {
3020 Type* field = get_comp_byIndex(i)->get_type();
3021
3022 if (jsonattrib != NULL && jsonattrib->as_value) {
3023 // only add the alternative's schema
3024 field->generate_json_schema(json, true, true);
3025 } else {
3026 // use a JSON object with one key-value pair for each alternative
3027 // the schema is the same as a record's with one field
3028 json.put_next_token(JSON_TOKEN_OBJECT_START);
3029
3030 json.put_next_token(JSON_TOKEN_NAME, "type");
3031 json.put_next_token(JSON_TOKEN_STRING, "\"object\"");
3032
3033 json.put_next_token(JSON_TOKEN_NAME, "properties");
3034 json.put_next_token(JSON_TOKEN_OBJECT_START);
3035
3036 // use the alternative's alias if it has one
3037 json.put_next_token(JSON_TOKEN_NAME,
3038 (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
3039 field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
3040
3041 // let the alternative's type insert its schema
3042 field->generate_json_schema(json, true, false);
3043
3044 // continue the schema for the record with one field
3045 json.put_next_token(JSON_TOKEN_OBJECT_END);
3046
3047 json.put_next_token(JSON_TOKEN_NAME, "additionalProperties");
3048 json.put_next_token(JSON_TOKEN_LITERAL_FALSE);
3049
3050 // the one field is non-optional
3051 json.put_next_token(JSON_TOKEN_NAME, "required");
3052 json.put_next_token(JSON_TOKEN_ARRAY_START);
3053
3054 // use the alternative's alias here as well
3055 char* field_str = mprintf("\"%s\"",
3056 (field->jsonattrib != NULL && field->jsonattrib->alias != NULL) ?
3057 field->jsonattrib->alias : get_comp_byIndex(i)->get_name().get_ttcnname().c_str());
3058 json.put_next_token(JSON_TOKEN_STRING, field_str);
3059 Free(field_str);
3060
3061 json.put_next_token(JSON_TOKEN_ARRAY_END);
3062
3063 json.put_next_token(JSON_TOKEN_OBJECT_END);
3064 }
3065 }
3066
3067 // close the "anyOf" array
3068 json.put_next_token(JSON_TOKEN_ARRAY_END);
3069 }
3070
3071 void Type::generate_json_schema_ref(JSON_Tokenizer& json)
3072 {
3073 // start the object containing the reference
3074 json.put_next_token(JSON_TOKEN_OBJECT_START);
3075
3076 // insert the reference
3077 json.put_next_token(JSON_TOKEN_NAME, "$ref");
3078 char* ref_str = mprintf("\"#/definitions/%s/%s\"",
3079 my_scope->get_scope_mod()->get_modid().get_ttcnname().c_str(),
3080 get_dispname().c_str());
3081 json.put_next_token(JSON_TOKEN_STRING, ref_str);
3082 Free(ref_str);
3083
3084 // the object will be closed later, as it may contain other properties
3085 }
3086
3087
3088 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
3089
3090 } // namespace Common
This page took 0.188681 seconds and 6 git commands to generate.