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