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