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