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