Merge pull request #67 from BenceJanosSzabo/master
[deliverable/titan.core.git] / compiler2 / union.c
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Baranyi, Botond
12 * Beres, Szabolcs
13 * Cserveni, Akos
14 * Delic, Adam
15 * Feher, Csaba
16 * Forstner, Matyas
17 * Kovacs, Ferenc
18 * Kremer, Peter
19 * Ormandi, Matyas
20 * Pandi, Krisztian
21 * Raduly, Csaba
22 * Szabados, Kristof
23 * Szabo, Bence Janos
24 * Szabo, Janos Zoltan – initial implementation
25 * Szalai, Gabor
26 * Pandi, Krisztian
27 *
28 ******************************************************************************/
29 #include <string.h>
30
31 #include "../common/memory.h"
32 #include "datatypes.h"
33 #include "union.h"
34 #include "encdec.h"
35
36 #include "main.hh"
37 #include "ttcn3/compiler.h"
38
39 /** used in the RAW_decode functions generation to store information
40 * about the temporal variables
41 * type is the type of the variable
42 * typedescr is the type's descriptor
43 * start_pos is where the decoding should begin
44 * it is >= 0 if known at compile time, otherwise -1
45 * use_counter stores how many times this type will be used
46 * if it is >1 than we create the variable "globally" so that that
47 * we don't need to create it again in the next component's decode try
48 * if it is ==1 than it is a local variable only referred at one place
49 * we create it only where it is needed, so if at runtime the decoding
50 * comes to a conclusion before the use of this variable, then its
51 * overhead won't slow down the decoding
52 * decoded_for_element is the index of the element in the union for which
53 * this variable was last used for
54 * if it is -1 if the variable hasn't been decoded yet
55 * only in this case it is needed to generate the code to do the decoding
56 * if it is >=0 than we use it generate the conditions
57 * if it doesn't equal to the actual component's index, then we have to
58 * generate the condition and the decoding... parts to it.
59 * if it equals the actual component's index, then we only add its test
60 * to the actual condition
61 */
62 typedef struct{
63 const char* type;
64 const char* typedescr;
65 int start_pos;
66 int use_counter;
67 int decoded_for_element;
68 }temporal_variable;
69
70 void defUnionClass(struct_def const *sdef, output_struct *output)
71 {
72 size_t i;
73 const char *name = sdef->name, *dispname = sdef->dispname;
74 const char *at_field = sdef->kind==ANYTYPE ? "AT_" : "";
75 /* at_field is used to prefix the name of accessor member functions
76 * for the anytype, otherwise the generated "INTEGER()" will look like
77 * a constructor, upsetting the C++ compiler. AT_INTEGER() is ok. */
78 char *def = NULL, *src = NULL;
79 boolean ber_needed = sdef->isASN1 && enable_ber();
80 boolean raw_needed = sdef->hasRaw && enable_raw();
81 boolean text_needed = sdef->hasText && enable_text();
82 boolean xer_needed = sdef->hasXer && enable_xer();
83 boolean json_needed = sdef->hasJson && enable_json();
84
85 char *selection_type, *unbound_value, *selection_prefix;
86 selection_type = mcopystr("union_selection_type");
87 unbound_value = mcopystr("UNBOUND_VALUE");
88 selection_prefix = mcopystr("ALT");
89
90
91 /* class declaration */
92 output->header.class_decls = mputprintf(output->header.class_decls,
93 "class %s;\n", name);
94
95 /* class definition and source code */
96
97 /* class header and data fields*/
98 def = mputprintf(def,
99 #ifndef NDEBUG
100 "// written by defUnionClass in " __FILE__ " at %d\n"
101 #endif
102 "class %s : public Base_Type {\n"
103 #ifndef NDEBUG
104 , __LINE__
105 #endif
106 , name);
107 /* selection type (enum) definition */
108 def = mputstr(def, "public:\n"
109 "enum union_selection_type { UNBOUND_VALUE = 0");
110 for (i = 0; i < sdef->nElements; i++) {
111 def = mputprintf(def, ", ALT_%s = %lu", sdef->elements[i].name,
112 (unsigned long) (i + 1));
113 }
114 def = mputstr(def, " };\n"
115 "private:\n");
116
117 def = mputprintf(def, "%s union_selection;\n"
118 "union {\n", selection_type);
119 for (i = 0; i < sdef->nElements; i++) {
120 def = mputprintf(def, "%s *field_%s;\n", sdef->elements[i].type,
121 sdef->elements[i].name);
122 }
123 def = mputstr(def, "};\n");
124
125 if(ber_needed && sdef->ot) {
126 def=mputstr(def, "ASN_BER_TLV_t tlv_opentype;\n");
127 }
128
129 if (use_runtime_2) {
130 def=mputstr(def, "Erroneous_descriptor_t* err_descr;\n");
131 }
132
133 /* copy_value function */
134 def = mputprintf(def, "void copy_value(const %s& other_value);\n", name);
135 src = mputprintf(src, "void %s::copy_value(const %s& other_value)\n"
136 "{\n"
137 "switch (other_value.union_selection) {\n", name, name);
138 for (i = 0; i < sdef->nElements; i++) {
139 src = mputprintf(src, "case %s_%s:\n", selection_prefix, sdef->elements[i].name);
140 if (legacy_unbound_union_fields) {
141 src = mputprintf(src, "if (other_value.field_%s->is_bound()) ",
142 sdef->elements[i].name);
143 }
144 src = mputprintf(src, "field_%s = new %s(*other_value.field_%s);\n",
145 sdef->elements[i].name, sdef->elements[i].type, sdef->elements[i].name);
146 if (legacy_unbound_union_fields) {
147 src = mputprintf(src,
148 "else {\n"
149 "field_%s = new %s;\n"
150 "TTCN_warning(\"Assignment of a union value with an unbound selected "
151 "alternative\");\n"
152 "}\n", sdef->elements[i].name, sdef->elements[i].type);
153 }
154 src = mputstr(src, "break;\n");
155 }
156 src = mputprintf(src, "default:\n"
157 "TTCN_error(\"Assignment of an unbound union value of type %s.\");\n"
158 "}\n"
159 "union_selection = other_value.union_selection;\n", dispname);
160
161 if (use_runtime_2) {
162 src = mputstr(src, "err_descr = other_value.err_descr;\n");
163 }
164
165 src = mputstr(src, "}\n\n");
166
167 /* default constructor */
168 def = mputprintf(def, "\npublic:\n"
169 "%s();\n", name);
170 src = mputprintf(src, "%s::%s()%s\n"
171 "{\n"
172 "union_selection = %s;\n"
173 "}\n\n", name, name,
174 use_runtime_2 ? ": err_descr(NULL)" : "",
175 unbound_value);
176
177 /* copy constructor */
178 def = mputprintf(def, "%s(const %s& other_value);\n", name, name);
179 src = mputprintf(src, "%s::%s(const %s& other_value)\n"
180 ": Base_Type()" /* call the *default* constructor as before */
181 "{\n"
182 "copy_value(other_value);\n"
183 "}\n\n", name, name, name);
184
185 /* destructor */
186 def = mputprintf(def, "~%s();\n", name);
187 src = mputprintf(src, "%s::~%s()\n"
188 "{\n"
189 "clean_up();\n"
190 "}\n\n", name, name);
191
192 /* assignment operator */
193 def = mputprintf(def, "%s& operator=(const %s& other_value);\n", name, name);
194 src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n"
195 "{\n"
196 "if (this != &other_value) {\n"
197 "clean_up();\n"
198 "copy_value(other_value);\n"
199 "}\n"
200 "return *this;\n"
201 "}\n\n", name, name, name);
202
203 /* comparison operator */
204 def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n",
205 name);
206 src = mputprintf(src, "boolean %s::operator==(const %s& other_value) const\n"
207 "{\n"
208 "if (union_selection == %s) TTCN_error(\"The left operand of comparison "
209 "is an unbound value of union type %s.\");\n"
210 "if (other_value.union_selection == %s) TTCN_error(\"The right operand of "
211 "comparison is an unbound value of union type %s.\");\n"
212 "if (union_selection != other_value.union_selection) return FALSE;\n"
213 "switch (union_selection) {\n", name, name, unbound_value, dispname,
214 unbound_value, dispname);
215 for (i = 0; i < sdef->nElements; i++) {
216 src = mputprintf(src, "case %s_%s:\n"
217 "return *field_%s == *other_value.field_%s;\n", selection_prefix,
218 sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name);
219 }
220 src = mputstr(src, "default:\n"
221 "return FALSE;\n"
222 "}\n"
223 "}\n\n");
224
225 /* != and () operator */
226 def = mputprintf(def, "inline boolean operator!=(const %s& other_value) "
227 "const { return !(*this == other_value); }\n", name);
228
229 /* field access functions */
230 for (i = 0; i < sdef->nElements; i++) {
231 def = mputprintf(def, "%s& %s%s();\n", sdef->elements[i].type,
232 at_field, sdef->elements[i].name);
233 src = mputprintf(src, "%s& %s::%s%s()\n"
234 "{\n"
235 "if (union_selection != %s_%s) {\n"
236 "clean_up();\n"
237 "field_%s = new %s;\n"
238 "union_selection = %s_%s;\n"
239 "}\n"
240 "return *field_%s;\n"
241 "}\n\n", sdef->elements[i].type, name, at_field, sdef->elements[i].name,
242 selection_prefix, sdef->elements[i].name, sdef->elements[i].name,
243 sdef->elements[i].type, selection_prefix, sdef->elements[i].name,
244 sdef->elements[i].name);
245
246 def = mputprintf(def, "const %s& %s%s() const;\n", sdef->elements[i].type,
247 at_field, sdef->elements[i].name);
248 src = mputprintf(src, "const %s& %s::%s%s() const\n"
249 "{\n"
250 "if (union_selection != %s_%s) TTCN_error(\"Using non-selected field "
251 "%s in a value of union type %s.\");\n"
252 "return *field_%s;\n"
253 "}\n\n",
254 sdef->elements[i].type, name, at_field, sdef->elements[i].name, selection_prefix,
255 sdef->elements[i].name, sdef->elements[i].dispname, dispname,
256 sdef->elements[i].name);
257 }
258
259 /* get_selection function */
260 def = mputprintf(def, "inline %s get_selection() const "
261 "{ return union_selection; }\n", selection_type);
262
263 /* ischosen function */
264 def = mputprintf(def, "boolean ischosen(%s checked_selection) const;\n",
265 selection_type);
266 src = mputprintf(src, "boolean %s::ischosen(%s checked_selection) const\n"
267 "{\n"
268 "if (checked_selection == %s) TTCN_error(\"Internal error: Performing "
269 "ischosen() operation on an invalid field of union type %s.\");\n"
270 "if (union_selection == %s) TTCN_error(\"Performing ischosen() operation "
271 "on an unbound value of union type %s.\");\n"
272 "return union_selection == checked_selection;\n"
273 "}\n\n", name, selection_type, unbound_value, dispname, unbound_value,
274 dispname);
275
276 /* is_bound function */
277 def = mputstr (def, "boolean is_bound() const;\n");
278 src = mputprintf(src, "boolean %s::is_bound() const\n"
279 "{\n"
280 " return union_selection != %s;\n"
281 "}\n\n", name, unbound_value);
282
283 /* is_value function */
284 def = mputstr (def, "boolean is_value() const;\n");
285 src = mputprintf(src, "boolean %s::is_value() const\n"
286 "{\n"
287 "switch (union_selection) {\n"
288 "case %s: return FALSE;\n",
289 name, unbound_value);
290 for (i = 0; i < sdef->nElements; ++i) {
291 src = mputprintf(src, "case %s_%s: return field_%s->is_value();\n",
292 selection_prefix, sdef->elements[i].name, sdef->elements[i].name);
293 }
294 src = mputstr(src, "default: TTCN_error(\"Invalid selection in union is_bound\");"
295 "}\n"
296 "}\n\n");
297
298 /* clean_up function */
299 def = mputstr (def, "void clean_up();\n");
300 src = mputprintf(src, "void %s::clean_up()\n"
301 "{\n"
302 "switch (union_selection) {\n",
303 name);
304 for (i = 0; i < sdef->nElements; ++i) {
305 src = mputprintf(src, "case %s_%s:\n"
306 " delete field_%s;\n"
307 " break;\n",
308 selection_prefix, sdef->elements[i].name, sdef->elements[i].name);
309 }
310 src = mputprintf(src, "default:\n"
311 " break;\n"
312 "}\n"
313 "union_selection = %s;\n"
314 "}\n\n", unbound_value);
315
316 if (use_runtime_2) {
317 def = mputstr(def,
318 "boolean is_equal(const Base_Type* other_value) const;\n"
319 "void set_value(const Base_Type* other_value);\n"
320 "Base_Type* clone() const;\n"
321 "const TTCN_Typedescriptor_t* get_descriptor() const;\n"
322 "void set_err_descr(Erroneous_descriptor_t* p_err_descr) { err_descr=p_err_descr; }\n"
323 "Erroneous_descriptor_t* get_err_descr() const { return err_descr; }\n");
324 src = mputprintf(src,
325 "boolean %s::is_equal(const Base_Type* other_value) const "
326 "{ return *this == *(static_cast<const %s*>(other_value)); }\n"
327 "void %s::set_value(const Base_Type* other_value) "
328 "{ *this = *(static_cast<const %s*>(other_value)); }\n"
329 "Base_Type* %s::clone() const { return new %s(*this); }\n"
330 "const TTCN_Typedescriptor_t* %s::get_descriptor() const "
331 "{ return &%s_descr_; }\n",
332 name, name,
333 name, name,
334 name, name,
335 name, name);
336 } else {
337 def = mputstr(def,
338 "inline boolean is_present() const { return is_bound(); }\n");
339 }
340
341 /* log function */
342 def = mputstr(def, "void log() const;\n");
343 src = mputprintf(src, "void %s::log() const\n"
344 "{\n"
345 "switch (union_selection) {\n", name);
346 for (i = 0; i < sdef->nElements; i++) {
347 src = mputprintf(src, "case %s_%s:\n"
348 "TTCN_Logger::log_event_str(\"{ %s := \");\n"
349 "field_%s->log();\n"
350 "TTCN_Logger::log_event_str(\" }\");\n"
351 "break;\n", selection_prefix, sdef->elements[i].name,
352 sdef->elements[i].dispname, sdef->elements[i].name);
353 }
354 src = mputstr(src, "default:\n"
355 "TTCN_Logger::log_event_unbound();\n"
356 "}\n");
357 if (use_runtime_2) {
358 src = mputstr(src, "if (err_descr) err_descr->log();\n");
359 }
360 src = mputstr(src, "}\n\n");
361
362 /* set_param function */
363 def = mputstr(def, "void set_param(Module_Param& param);\n");
364 src = mputprintf(src, "void %s::set_param(Module_Param& param)\n"
365 "{\n"
366 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
367 " param.get_id()->next_name()) {\n"
368 // Haven't reached the end of the module parameter name
369 // => the name refers to one of the fields, not to the whole union
370 " char* param_field = param.get_id()->get_current_name();\n"
371 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
372 " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n"
373 " \" name for union type `%s'\");\n"
374 " }\n"
375 " ", name, dispname);
376 for (i = 0; i < sdef->nElements; i++) {
377 src = mputprintf(src,
378 "if (strcmp(\"%s\", param_field) == 0) {\n"
379 " %s%s().set_param(param);\n"
380 " return;\n"
381 " } else ",
382 sdef->elements[i].dispname, at_field, sdef->elements[i].name);
383 }
384 src = mputprintf(src,
385 "param.error(\"Field `%%s' not found in union type `%s'\", param_field);\n"
386 " }\n"
387 " param.basic_check(Module_Param::BC_VALUE, \"union value\");\n"
388 " Module_Param_Ptr m_p = &param;\n"
389 " if (param.get_type() == Module_Param::MP_Reference) {\n"
390 " m_p = param.get_referenced_param();\n"
391 " }\n"
392 " if (m_p->get_type()==Module_Param::MP_Value_List && m_p->get_size()==0) return;\n"
393 " if (m_p->get_type()!=Module_Param::MP_Assignment_List) {\n"
394 " param.error(\"union value with field name was expected\");\n"
395 " }\n"
396 " Module_Param* mp_last = m_p->get_elem(m_p->get_size()-1);\n", dispname);
397
398 for (i = 0; i < sdef->nElements; i++) {
399 src = mputprintf(src,
400 " if (!strcmp(mp_last->get_id()->get_name(), \"%s\")) {\n"
401 " %s%s().set_param(*mp_last);\n"
402 " if (!%s%s().is_bound()) "
403 , sdef->elements[i].dispname, at_field, sdef->elements[i].name
404 , at_field, sdef->elements[i].name);
405 if (legacy_unbound_union_fields) {
406 src = mputprintf(src,
407 "TTCN_warning(\"Alternative '%s' was selected for union of type '%s', "
408 "but its value is unbound\");\n"
409 , sdef->elements[i].dispname, sdef->dispname);
410 }
411 else {
412 // a union's alternative cannot be unbound
413 src = mputstr(src, "clean_up();\n");
414 }
415 src = mputstr(src,
416 " return;\n"
417 " }\n");
418 }
419 src = mputprintf(src,
420 " mp_last->error(\"Field %%s does not exist in type %s.\", mp_last->get_id()->get_name());\n"
421 "}\n\n", dispname);
422
423 /* get param function */
424 def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
425 src = mputprintf(src,
426 "Module_Param* %s::get_param(Module_Param_Name& param_name) const\n"
427 "{\n"
428 " if (!is_bound()) {\n"
429 " return new Module_Param_Unbound();\n"
430 " }\n"
431 " if (param_name.next_name()) {\n"
432 // Haven't reached the end of the module parameter name
433 // => the name refers to one of the fields, not to the whole union
434 " char* param_field = param_name.get_current_name();\n"
435 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
436 " TTCN_error(\"Unexpected array index in module parameter reference, \"\n"
437 " \"expected a valid field name for union type `%s'\");\n"
438 " }\n"
439 " ", name, dispname);
440 for (i = 0; i < sdef->nElements; i++) {
441 src = mputprintf(src,
442 "if (strcmp(\"%s\", param_field) == 0) {\n"
443 " return %s%s().get_param(param_name);\n"
444 " } else ",
445 sdef->elements[i].dispname, at_field, sdef->elements[i].name);
446 }
447 src = mputprintf(src,
448 "TTCN_error(\"Field `%%s' not found in union type `%s'\", param_field);\n"
449 " }\n"
450 " Module_Param* mp_field = NULL;\n"
451 " switch(union_selection) {\n"
452 , name);
453 for (i = 0; i < sdef->nElements; ++i) {
454 src = mputprintf(src,
455 " case %s_%s:\n"
456 " mp_field = field_%s->get_param(param_name);\n"
457 " mp_field->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n"
458 " break;\n"
459 , selection_prefix, sdef->elements[i].name
460 , sdef->elements[i].name, sdef->elements[i].dispname);
461 }
462 src = mputstr(src,
463 " default:\n"
464 " break;\n"
465 " }\n"
466 " Module_Param_Assignment_List* m_p = new Module_Param_Assignment_List();\n"
467 " m_p->add_elem(mp_field);\n"
468 " return m_p;\n"
469 "}\n\n");
470
471 /* set implicit omit function, recursive */
472 def = mputstr(def, " void set_implicit_omit();\n");
473 src = mputprintf(src,
474 "void %s::set_implicit_omit()\n{\n"
475 "switch (union_selection) {\n", name);
476 for (i = 0; i < sdef->nElements; i++) {
477 src = mputprintf(src,
478 "case %s_%s:\n"
479 "field_%s->set_implicit_omit(); break;\n",
480 selection_prefix, sdef->elements[i].name, sdef->elements[i].name);
481 }
482 src = mputstr(src, "default: break;\n}\n}\n\n");
483
484 /* encode_text function */
485 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
486 src = mputprintf(src, "void %s::encode_text(Text_Buf& text_buf) const\n"
487 "{\n"
488 "text_buf.push_int(union_selection);\n"
489 "switch (union_selection) {\n", name);
490 for (i = 0; i < sdef->nElements; i++) {
491 src = mputprintf(src, "case %s_%s:\n"
492 "field_%s->encode_text(text_buf);\n"
493 "break;\n", selection_prefix, sdef->elements[i].name,
494 sdef->elements[i].name);
495 }
496 src = mputprintf(src, "default:\n"
497 "TTCN_error(\"Text encoder: Encoding an unbound value of union type "
498 "%s.\");\n"
499 "}\n"
500 "}\n\n", dispname);
501
502 /* decode_text function */
503 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
504 src = mputprintf(src, "void %s::decode_text(Text_Buf& text_buf)\n"
505 "{\n"
506 "switch ((%s)text_buf.pull_int().get_val()) {\n", name, selection_type);
507 for (i = 0; i < sdef->nElements; i++) {
508 src = mputprintf(src, "case %s_%s:\n"
509 "%s%s().decode_text(text_buf);\n"
510 "break;\n", selection_prefix, sdef->elements[i].name,
511 at_field, sdef->elements[i].name);
512 }
513 src = mputprintf(src, "default:\n"
514 "TTCN_error(\"Text decoder: Unrecognized union selector was received "
515 "for type %s.\");\n"
516 "}\n"
517 "}\n\n", dispname);
518
519 if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
520 def_encdec(name, &def, &src, ber_needed, raw_needed, text_needed,
521 xer_needed, json_needed, TRUE);
522
523 /* BER functions */
524 if(ber_needed) {
525 def = mputstr(def, "private:\n"
526 "boolean BER_decode_set_selection(const ASN_BER_TLV_t& p_tlv);\n"
527 "public:\n"
528 "boolean BER_decode_isMyMsg(const TTCN_Typedescriptor_t& p_td, "
529 "const ASN_BER_TLV_t& p_tlv);\n");
530
531 /* BER_encode_TLV() */
532 src = mputprintf(src,
533 #ifndef NDEBUG
534 "// written by %s in " __FILE__ " at %d\n"
535 #endif
536 "ASN_BER_TLV_t *%s::BER_encode_TLV("
537 "const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const\n"
538 "{\n"
539 #ifndef NDEBUG
540 , __FUNCTION__, __LINE__
541 #endif
542 , name);
543 if (use_runtime_2) {
544 src = mputstr(src,
545 " if (err_descr) return BER_encode_TLV_negtest(err_descr, p_td, p_coding);\n");
546 }
547 src = mputstr(src,
548 " BER_chk_descr(p_td);\n"
549 " ASN_BER_TLV_t *new_tlv;\n"
550 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
551 " TTCN_EncDec_ErrorContext ec_1;\n"
552 " switch (union_selection) {\n");
553 for (i = 0; i < sdef->nElements; i++) {
554 src = mputprintf(src, " case %s_%s:\n"
555 " ec_1.set_msg(\"%s': \");\n"
556 " new_tlv = field_%s->BER_encode_TLV(%s_descr_, p_coding);\n"
557 " break;\n", selection_prefix, sdef->elements[i].name,
558 sdef->elements[i].dispname,
559 sdef->elements[i].name, sdef->elements[i].typedescrname);
560 } /* for i */
561 src = mputprintf(src, " case %s:\n"
562 " new_tlv = BER_encode_chk_bound(FALSE);\n"
563 " break;\n"
564 " default:\n"
565 " TTCN_EncDec_ErrorContext::error_internal(\"Unknown selection.\");\n"
566 " new_tlv = NULL;\n"
567 " }\n" /* switch */
568 " return ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
569 "}\n\n", unbound_value);
570
571 if (use_runtime_2) { /* BER_encode_TLV_negtest() */
572 def = mputstr(def,
573 "ASN_BER_TLV_t* BER_encode_TLV_negtest(const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const;\n");
574 src = mputprintf(src,
575 "ASN_BER_TLV_t *%s::BER_encode_TLV_negtest(const Erroneous_descriptor_t* p_err_descr, "
576 "const TTCN_Typedescriptor_t& p_td, unsigned p_coding) const\n"
577 "{\n"
578 " BER_chk_descr(p_td);\n"
579 " ASN_BER_TLV_t *new_tlv = NULL;\n"
580 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
581 " TTCN_EncDec_ErrorContext ec_1;\n"
582 " const Erroneous_values_t* err_vals = NULL;\n"
583 " const Erroneous_descriptor_t* emb_descr = NULL;\n"
584 " switch (union_selection) {\n", name);
585 for (i = 0; i < sdef->nElements; i++) {
586 src = mputprintf(src, " case %s_%s:\n"
587 " err_vals = p_err_descr->get_field_err_values(%d);\n"
588 " emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
589 " if (err_vals && err_vals->value) {\n"
590 " if (err_vals->value->errval) {\n"
591 " ec_1.set_msg(\"%s'(erroneous value): \");\n"
592 " if (err_vals->value->raw) {\n"
593 " new_tlv = err_vals->value->errval->BER_encode_negtest_raw();\n"
594 " } else {\n"
595 " if (err_vals->value->type_descr==NULL) TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
596 " new_tlv = err_vals->value->errval->BER_encode_TLV(*err_vals->value->type_descr, p_coding);\n"
597 " }\n"
598 " }\n"
599 " } else {\n"
600 " ec_1.set_msg(\"%s': \");\n"
601 " if (emb_descr) new_tlv = field_%s->BER_encode_TLV_negtest(emb_descr, %s_descr_, p_coding);\n"
602 " else new_tlv = field_%s->BER_encode_TLV(%s_descr_, p_coding);\n"
603 " }\n"
604 " break;\n", selection_prefix, sdef->elements[i].name,
605 (int)i, (int)i, sdef->elements[i].dispname, sdef->elements[i].dispname,
606 sdef->elements[i].name, sdef->elements[i].typedescrname,
607 sdef->elements[i].name, sdef->elements[i].typedescrname);
608 } /* for i */
609 src = mputprintf(src, " case %s:\n"
610 " new_tlv = BER_encode_chk_bound(FALSE);\n"
611 " break;\n"
612 " default:\n"
613 " TTCN_EncDec_ErrorContext::error_internal(\"Unknown selection.\");\n"
614 " new_tlv = NULL;\n"
615 " }\n" /* switch */
616 " if (new_tlv==NULL) new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
617 " return ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
618 "}\n\n", unbound_value);
619 }
620
621 /* BER_decode_set_selection() */
622 src = mputprintf(src, "boolean %s::BER_decode_set_selection("
623 "const ASN_BER_TLV_t& p_tlv)\n"
624 "{\n"
625 " clean_up();\n", name);
626 for (i = 0; i < sdef->nElements; i++) {
627 src = mputprintf(src, " field_%s = new %s;\n"
628 " union_selection = %s_%s;\n"
629 " if (field_%s->BER_decode_isMyMsg(%s_descr_, p_tlv)) return TRUE;\n"
630 " delete field_%s;\n", sdef->elements[i].name, sdef->elements[i].type,
631 selection_prefix, sdef->elements[i].name, sdef->elements[i].name,
632 sdef->elements[i].typedescrname, sdef->elements[i].name);
633 } /* for i */
634 src = mputprintf(src, " union_selection = %s;\n"
635 " return FALSE;\n"
636 "}\n\n", unbound_value);
637
638 /* BER_decode_isMyMsg() */
639 src = mputprintf(src, "boolean %s::BER_decode_isMyMsg("
640 "const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv)\n"
641 "{\n"
642 " if (p_td.ber->n_tags == 0) {\n"
643 " %s tmp_type;\n"
644 " return tmp_type.BER_decode_set_selection(p_tlv);\n"
645 " } else return Base_Type::BER_decode_isMyMsg(p_td, p_tlv);\n"
646 "}\n\n", name, name);
647
648 /* BER_decode_TLV() */
649 src = mputprintf(src, "boolean %s::BER_decode_TLV("
650 "const TTCN_Typedescriptor_t& p_td, const ASN_BER_TLV_t& p_tlv, "
651 "unsigned L_form)\n"
652 "{\n"
653 " BER_chk_descr(p_td);\n"
654 " ASN_BER_TLV_t stripped_tlv;\n"
655 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
656 " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n",
657 name, dispname);
658 if (sdef->ot) {
659 src = mputprintf(src, " if (!BER_decode_TLV_CHOICE(*p_td.ber, "
660 "stripped_tlv, L_form, tlv_opentype)) {\n"
661 " tlv_opentype.Tlen = 0;\n"
662 " return FALSE;\n"
663 " }\n"
664 " clean_up();\n"
665 " union_selection = %s;\n", unbound_value);
666 } else {
667 src = mputstr(src, " ASN_BER_TLV_t tmp_tlv;\n"
668 " if (!BER_decode_TLV_CHOICE(*p_td.ber, stripped_tlv, L_form, "
669 "tmp_tlv) || "
670 "!BER_decode_CHOICE_selection(BER_decode_set_selection(tmp_tlv), "
671 "tmp_tlv)) return FALSE;\n"
672 " TTCN_EncDec_ErrorContext ec_1(\"Alternative '\");\n"
673 " TTCN_EncDec_ErrorContext ec_2;\n"
674 " switch (union_selection) {\n");
675 for(i = 0; i < sdef->nElements; i++) {
676 src = mputprintf(src, " case %s_%s:\n"
677 " ec_2.set_msg(\"%s': \");\n"
678 " field_%s->BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n"
679 " break;\n", selection_prefix, sdef->elements[i].name,
680 sdef->elements[i].dispname,
681 sdef->elements[i].name, sdef->elements[i].typedescrname);
682 } /* for i */
683 src = mputstr(src, " default:\n"
684 " return FALSE;\n"
685 " }\n");
686 if (sdef->opentype_outermost) {
687 src = mputstr(src,
688 " TTCN_EncDec_ErrorContext ec_1(\"While decoding opentypes: \");\n"
689 " TTCN_Type_list p_typelist;\n"
690 " BER_decode_opentypes(p_typelist, L_form);\n");
691 } /* if sdef->opentype_outermost */
692 }
693 src = mputstr(src, " return TRUE;\n"
694 "}\n\n");
695
696 if (sdef->ot || sdef->has_opentypes) { /* theoretically, these are
697 mutually exlusive */
698 /* BER_decode_opentypes() */
699 def = mputstr(def, "void BER_decode_opentypes("
700 "TTCN_Type_list& p_typelist, unsigned L_form);\n");
701 src = mputprintf(src, "void %s::BER_decode_opentypes("
702 "TTCN_Type_list& p_typelist, unsigned L_form)\n"
703 "{\n", name);
704 if (sdef->ot) {
705 AtNotationList_t *anl = &sdef->ot->anl;
706 OpentypeAlternativeList_t *oal = &sdef->ot->oal;
707 src = mputprintf(src,
708 " if (union_selection != %s) return;\n"
709 " TTCN_EncDec_ErrorContext ec_0(\"While decoding open type '%s': "
710 "\");\n", unbound_value, dispname);
711 if (oal->nElements > 0) {
712 size_t oal_i, anl_i;
713 char *s2;
714 /* variable declarations - the referenced components */
715 for (anl_i = 0; anl_i < anl->nElements; anl_i++) {
716 AtNotation_t *an = anl->elements + anl_i;
717 src = mputprintf(src, " const %s& f_%lu = static_cast<const %s*>"
718 "(p_typelist.get_nth(%lu))->%s;\n", an->type_name,
719 (unsigned long) (anl_i + 1), an->parent_typename,
720 (unsigned long) an->parent_level, an->sourcecode);
721 } /* for anl_i */
722 src = mputstr(src, " {\n"
723 " TTCN_EncDec_ErrorContext ec_1(\"Alternative '\");\n"
724 " TTCN_EncDec_ErrorContext ec_2;\n");
725 s2 = mprintf("%*s", (int)(anl->nElements + 2) * 2, "");
726 for (oal_i = 0; oal_i < oal->nElements; oal_i++) {
727 size_t if_level;
728 OpentypeAlternative_t *oa = oal->elements + oal_i;
729 if (oal_i > 0) {
730 for (if_level = 0; if_level < anl->nElements; if_level++)
731 if (oa->const_valuenames[if_level]) break;
732 for (i = anl->nElements; i > if_level; i--)
733 src = mputprintf(src, "%*s}\n", (int)(i + 1) * 2, "");
734 } /* if oal_i */
735 else if_level = 0;
736 for (anl_i = if_level; anl_i < anl->nElements; anl_i++) {
737 src = mputprintf(src, "%*s%sif (f_%lu == %s) {\n",
738 (int)(anl_i + 2) * 2, "",
739 oal_i && anl_i <= if_level ? "else " : "",
740 (unsigned long) (anl_i + 1), oa->const_valuenames[anl_i]);
741 } /* for anl_i */
742 src = mputprintf(src, "%sunion_selection = %s_%s;\n"
743 "%sfield_%s = new %s;\n"
744 "%sec_2.set_msg(\"%s': \");\n"
745 "%sfield_%s->BER_decode_TLV(%s_descr_, tlv_opentype, L_form);\n",
746 s2, selection_prefix, oa->alt, s2, oa->alt, oa->alt_typename, s2,
747 oa->alt_dispname, s2, oa->alt, oa->alt_typedescrname);
748 } /* for oal_i */
749 Free(s2);
750 if (oal->nElements > 0)
751 for (i = anl->nElements; i > 0; i--)
752 src = mputprintf(src, "%*s}\n", (int)(i+1)*2, "");
753 src = mputprintf(src, " }\n"
754 " if (union_selection == %s) {\n"
755 " ec_0.error(TTCN_EncDec::ET_DEC_OPENTYPE, \"Cannot decode "
756 "open type: broken component relation constraint.\");\n"
757 " if (TTCN_EncDec::get_error_behavior("
758 "TTCN_EncDec::ET_DEC_OPENTYPE) != TTCN_EncDec::EB_IGNORE) {\n"
759 " TTCN_Logger::log_str(TTCN_WARNING, \"The value%s of"
760 " constraining component%s:\");\n", unbound_value,
761 anl->nElements > 1 ? "s" : "", anl->nElements > 1 ? "s" : "");
762 for (anl_i = 0; anl_i < anl->nElements; anl_i++) {
763 AtNotation_t *an = anl->elements + anl_i;
764 src = mputprintf(src,
765 " TTCN_Logger::begin_event(TTCN_WARNING);\n"
766 " TTCN_Logger::log_event_str(\"Component '%s': \");\n"
767 " f_%lu.log();\n"
768 " TTCN_Logger::end_event();\n", an->dispname,
769 (unsigned long) (anl_i + 1));
770 } /* for anl_i */
771 src = mputstr(src, " }\n"
772 " }\n");
773 } /* if oal->nElements>0 */
774 else {
775 src = mputstr(src, " ec_0.error(TTCN_EncDec::ET_DEC_OPENTYPE, "
776 "\"Cannot decode open type: the constraining object set is "
777 "empty.\");\n");
778 } /* oal->nElements==0 */
779 } /* if sdef->ot */
780 else { /* if !sdef->ot (but has_opentypes) */
781 src = mputstr(src,
782 " p_typelist.push(this);\n"
783 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
784 " TTCN_EncDec_ErrorContext ec_1;\n"
785 " switch (union_selection) {\n");
786 for (i = 0; i < sdef->nElements; i++) {
787 src = mputprintf(src, " case %s_%s:\n"
788 " ec_1.set_msg(\"%s': \");\n"
789 " field_%s->BER_decode_opentypes(p_typelist, L_form);\n"
790 " break;\n", selection_prefix, sdef->elements[i].name,
791 sdef->elements[i].dispname, sdef->elements[i].name);
792 } /* for i */
793 src = mputstr(src, " default:\n"
794 " break;\n"
795 " }\n"
796 " p_typelist.pop();\n");
797 } /* if has opentypes */
798 src = mputstr(src, "}\n"
799 "\n");
800 } /* if sdef->ot || sdef->has_opentypes */
801 } /* if ber_needed */
802
803 if (raw_needed) {
804 size_t nTemp_variables = 0;
805 temporal_variable* temp_variable_list = NULL;
806 int* tag_type = (int*) Malloc(sdef->nElements*sizeof(int));
807 memset(tag_type, 0, sdef->nElements * sizeof(int));
808 if (sdef->hasRaw) { /* fill tag_type. 0-No tag, >0 index of the tag + 1 */
809 for (i = 0; i < sdef->raw.taglist.nElements; i++) {
810 if (sdef->raw.taglist.list[i].nElements) {
811 boolean found = FALSE;
812 size_t v;
813 for (v = 0; v < sdef->raw.taglist.list[i].nElements; v++) {
814 if (sdef->raw.taglist.list[i].fields[v].start_pos >= 0) {
815 found = TRUE;
816 break;
817 }
818 }
819 if (found)
820 tag_type[sdef->raw.taglist.list[i].fieldnum] = i + 1;
821 else
822 tag_type[sdef->raw.taglist.list[i].fieldnum] = -i - 1;
823 }
824 }
825 }
826 src = mputprintf(src, "int %s::RAW_decode(\n"
827 "const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, int limit, \n"
828 "raw_order_t top_bit_ord, boolean no_err, int sel_field, boolean)\n"
829 "{\n"
830 " int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n"
831 " limit-=prepaddlength;\n"
832 " int decoded_length=0;\n"
833 " int starting_pos=p_buf.get_pos_bit();\n"
834 " if(sel_field!=-1){\n"
835 " switch(sel_field){\n", name);
836 for (i = 0; i < sdef->nElements; i++) {
837 src = mputprintf(src,
838 " case %lu:\n"
839 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, limit, "
840 "top_bit_ord, no_err);\n"
841 " break;\n", (unsigned long) i, sdef->elements[i].name,
842 sdef->elements[i].typedescrname);
843 }
844 src = mputstr(src, " default: break;\n"
845 " }\n"
846 " return decoded_length + p_buf.increase_pos_padd(p_td.raw->padding) + "
847 "prepaddlength;\n"
848 " } else {\n");
849 /* only generate this variable if it will be used */
850 for (i = 0; i < sdef->nElements; i++) {
851 if ((tag_type[i] > 0)
852 && (sdef->raw.taglist.list + tag_type[i] - 1)->nElements) {
853 src = mputstr(src, " boolean already_failed = FALSE;\n");
854 break;
855 }
856 }
857
858 /* precalculate what we know about the temporal variables*/
859 for (i = 0; i < sdef->nElements; i++) {
860 if ((tag_type[i] > 0)
861 && (sdef->raw.taglist.list + tag_type[i] - 1)->nElements) {
862 rawAST_coding_taglist* cur_choice = sdef->raw.taglist.list + tag_type[i] - 1;
863 size_t j;
864 for (j = 0; j < cur_choice->nElements; j++) {
865 rawAST_coding_field_list *fieldlist = cur_choice->fields + j;
866 if (fieldlist->start_pos >= 0) {
867 size_t k;
868 boolean found = FALSE;
869 for (k = 0; k < nTemp_variables; k++) {
870 if (temp_variable_list[k].start_pos == fieldlist->start_pos
871 && !strcmp(temp_variable_list[k].typedescr,
872 fieldlist->fields[fieldlist->nElements - 1].typedescr)) {
873 temp_variable_list[k].use_counter++;
874 fieldlist->temporal_variable_index = k;
875 found = TRUE;
876 break;
877 }
878 }
879 if (!found) {
880 temp_variable_list
881 = (temporal_variable*) Realloc(temp_variable_list,
882 (nTemp_variables + 1) * sizeof(*temp_variable_list));
883 temp_variable_list[nTemp_variables].type
884 = fieldlist->fields[fieldlist->nElements - 1].type;
885 temp_variable_list[nTemp_variables].typedescr
886 = fieldlist->fields[fieldlist->nElements - 1].typedescr;
887 temp_variable_list[nTemp_variables].start_pos
888 = fieldlist->start_pos;
889 temp_variable_list[nTemp_variables].use_counter = 1;
890 temp_variable_list[nTemp_variables].decoded_for_element
891 = -1;
892 fieldlist->temporal_variable_index = nTemp_variables;
893 nTemp_variables++;
894 }
895 }
896 }
897 }
898 }
899
900 for (i = 0; i < nTemp_variables; i++) {
901 if (temp_variable_list[i].use_counter > 1) {
902 src = mputprintf(src, " %s temporal_%lu;\n"
903 " int decoded_%lu_length;\n", temp_variable_list[i].type,
904 (unsigned long) i, (unsigned long) i);
905 }
906 }
907
908 for (i = 0; i < sdef->nElements; i++) { /* fields with tag */
909 if ((tag_type[i] > 0)
910 && (sdef->raw.taglist.list + tag_type[i] - 1)->nElements) {
911 rawAST_coding_taglist* cur_choice = sdef->raw.taglist.list
912 + tag_type[i] - 1;
913 size_t j;
914 src = mputstr(src, " already_failed = FALSE;\n");
915 /* first check the fields we can precode
916 * try to decode those key variables whose position we know
917 * this way we might be able to step over bad values faster
918 */
919 for (j = 0; j < cur_choice->nElements; j++) {
920 rawAST_coding_field_list *cur_field_list = cur_choice->fields + j;
921 if (cur_field_list->start_pos >= 0) {
922 size_t k;
923 size_t variable_index = cur_field_list->temporal_variable_index;
924 if (temp_variable_list[variable_index].decoded_for_element == i) continue;
925 src = mputstr(src, " if (!already_failed) {\n");
926 if (temp_variable_list[variable_index].use_counter == 1) {
927 src = mputprintf(src, " %s temporal_%lu;\n"
928 " int decoded_%lu_length;\n",
929 temp_variable_list[variable_index].type,
930 (unsigned long) variable_index, (unsigned long) variable_index);
931 }
932 if (temp_variable_list[variable_index].decoded_for_element
933 == -1) {
934 src = mputprintf(src,
935 " p_buf.set_pos_bit(starting_pos + %d);\n"
936 " decoded_%lu_length = temporal_%lu.RAW_decode("
937 "%s_descr_, p_buf, limit, top_bit_ord, TRUE);\n",
938 cur_field_list->start_pos, (unsigned long) variable_index,
939 (unsigned long) variable_index,
940 temp_variable_list[variable_index].typedescr);
941 }
942 temp_variable_list[variable_index].decoded_for_element = i;
943 src = mputprintf(src, " if (decoded_%lu_length > 0) {\n"
944 " if (temporal_%lu == %s", (unsigned long) variable_index,
945 (unsigned long) variable_index, cur_field_list->value);
946 for (k = j + 1; k < cur_choice->nElements; k++) {
947 if (cur_choice->fields[k].temporal_variable_index
948 == variable_index) {
949 src = mputprintf(src, " || temporal_%lu == %s",
950 (unsigned long) variable_index, cur_choice->fields[k].value);
951 }
952 }
953 src = mputprintf(src, ") {\n"
954 " p_buf.set_pos_bit(starting_pos);\n"
955 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, "
956 "limit, top_bit_ord, TRUE);\n"
957 " if (decoded_length > 0) {\n", sdef->elements[i].name,
958 sdef->elements[i].typedescrname);
959 src = mputstr(src, " if (");
960 src = genRawFieldChecker(src, cur_choice, TRUE);
961 src = mputstr(src, ") {\n"
962 " return decoded_length + "
963 "p_buf.increase_pos_padd(p_td.raw->padding) + prepaddlength;\n"
964 " }else already_failed = TRUE;\n"
965 " }\n"
966 " }\n"
967 " }\n"
968 " }\n");
969 }
970 }
971 /* if there is one tag key whose position we don't know
972 * and we couldn't decide yet if the element can be decoded or not
973 * than we have to decode it.
974 * note that this is not actually a cycle because of the break
975 */
976 for (j = 0; j < cur_choice->nElements; j++) {
977 if (cur_choice->fields[j].start_pos < 0) {
978 src = mputprintf(src, " if (already_failed) {\n"
979 " p_buf.set_pos_bit(starting_pos);\n"
980 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, limit, "
981 "top_bit_ord, TRUE);\n"
982 " if (decoded_length > 0) {\n", sdef->elements[i].name,
983 sdef->elements[i].typedescrname);
984 src = mputstr(src, " if (");
985 src = genRawFieldChecker(src, cur_choice, TRUE);
986 src = mputstr(src, ") {\n"
987 " return decoded_length + "
988 "p_buf.increase_pos_padd(p_td.raw->padding) + prepaddlength;\n"
989 " }\n"
990 " }\n"
991 " }\n");
992 break;
993 }
994 }
995 }
996 }
997 Free(temp_variable_list);
998 for (i = 0; i < sdef->nElements; i++) { /* fields with only variable tag */
999 if ((tag_type[i] < 0)
1000 && (sdef->raw.taglist.list - tag_type[i] - 1)->nElements) {
1001 rawAST_coding_taglist* cur_choice = sdef->raw.taglist.list
1002 - tag_type[i] - 1;
1003 src = mputprintf(src, " p_buf.set_pos_bit(starting_pos);\n"
1004 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, limit, "
1005 "top_bit_ord, TRUE);\n"
1006 " if (decoded_length >= 0) {\n", sdef->elements[i].name,
1007 sdef->elements[i].typedescrname);
1008 src = mputstr(src, " if (");
1009 src = genRawFieldChecker(src, cur_choice, TRUE);
1010 src = mputstr(src, ") {\n"
1011 " return decoded_length + "
1012 "p_buf.increase_pos_padd(p_td.raw->padding) + prepaddlength;\n"
1013 " }\n"
1014 " }\n");
1015 }
1016 }/**/
1017 for (i = 0; i < sdef->nElements; i++) { /* fields without tag */
1018 if (!tag_type[i]) {
1019 src = mputprintf(src, " p_buf.set_pos_bit(starting_pos);\n"
1020 " decoded_length = %s().RAW_decode(%s_descr_, p_buf, limit, "
1021 "top_bit_ord, TRUE);\n"
1022 " if (decoded_length >= 0) {\n", sdef->elements[i].name,
1023 sdef->elements[i].typedescrname);
1024 src = mputstr(src, " return decoded_length + "
1025 "p_buf.increase_pos_padd(p_td.raw->padding) + prepaddlength;\n"
1026 " }\n");
1027 }
1028 }/**/
1029 src = mputstr(src, " }\n"
1030 " clean_up();\n"
1031 " return -1;\n"
1032 "}\n\n");
1033 /* encoder */
1034 src = mputprintf(src, "int %s::RAW_encode("
1035 "const TTCN_Typedescriptor_t&%s, RAW_enc_tree& myleaf) const\n"
1036 "{\n", name, use_runtime_2 ? " p_td" : "");
1037 if (use_runtime_2) {
1038 src = mputstr(src, " if (err_descr) return RAW_encode_negtest(err_descr, p_td, myleaf);\n");
1039 }
1040 src = mputprintf(src,
1041 " int encoded_length = 0;\n"
1042 " myleaf.isleaf = FALSE;\n"
1043 " myleaf.body.node.num_of_nodes = %lu;"
1044 " myleaf.body.node.nodes = init_nodes_of_enc_tree(%lu);\n"
1045 " memset(myleaf.body.node.nodes, 0, %lu * sizeof(RAW_enc_tree *));\n"
1046 " switch (union_selection) {\n", (unsigned long)sdef->nElements,
1047 (unsigned long)sdef->nElements, (unsigned long)sdef->nElements);
1048 for (i = 0; i < sdef->nElements; i++) {
1049 int t_type = tag_type[i] > 0 ? tag_type[i] : -tag_type[i];
1050 src = mputprintf(src, " case %s_%s:\n"
1051 " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(TRUE, &myleaf, "
1052 "&myleaf.curr_pos, %lu, %s_descr_.raw);\n"
1053 " encoded_length = field_%s->RAW_encode(%s_descr_, "
1054 "*myleaf.body.node.nodes[%lu]);\n"
1055 " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n",
1056 selection_prefix, sdef->elements[i].name, (unsigned long) i,
1057 (unsigned long) i, sdef->elements[i].typedescrname,
1058 sdef->elements[i].name, sdef->elements[i].typedescrname,
1059 (unsigned long) i, (unsigned long) i, sdef->elements[i].typedescrname);
1060 if (t_type && (sdef->raw.taglist.list + t_type - 1)->nElements) {
1061 rawAST_coding_taglist* cur_choice = sdef->raw.taglist.list + t_type - 1;
1062 src = mputstr(src, " if (");
1063 src = genRawFieldChecker(src, cur_choice, FALSE);
1064 src = mputstr(src, ") {\n");
1065 src = genRawTagChecker(src, cur_choice);
1066 src = mputstr(src, " }\n");
1067 }
1068 src = mputstr(src, " break;\n");
1069 }
1070 src = mputstr(src, " default:\n"
1071 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, "
1072 "\"Encoding an unbound value.\");\n"
1073 " }\n"
1074 " return encoded_length;\n"
1075 "}\n\n");
1076 if (use_runtime_2) {
1077 def = mputstr(def, "int RAW_encode_negtest(const Erroneous_descriptor_t *, "
1078 "const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n");
1079 src = mputprintf(src, "int %s::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr, "
1080 "const TTCN_Typedescriptor_t& /*p_td*/, RAW_enc_tree& myleaf) const\n"
1081 "{\n"
1082 " const Erroneous_values_t *err_vals = NULL;\n"
1083 " const Erroneous_descriptor_t *emb_descr = NULL;\n"
1084 " int encoded_length = 0;\n"
1085 " myleaf.isleaf = FALSE;\n"
1086 " myleaf.body.node.num_of_nodes = %lu;\n"
1087 " myleaf.body.node.nodes = init_nodes_of_enc_tree(%lu);\n"
1088 " memset(myleaf.body.node.nodes, 0, %lu * sizeof(RAW_enc_tree *));\n"
1089 " switch (union_selection) {\n", name, (unsigned long)sdef->nElements,
1090 (unsigned long)sdef->nElements, (unsigned long)sdef->nElements);
1091 for (i = 0; i < sdef->nElements; i++) {
1092 int t_type = tag_type[i] > 0 ? tag_type[i] : -tag_type[i];
1093 src = mputprintf(src,
1094 " case %s_%s: {\n",
1095 selection_prefix, sdef->elements[i].name);
1096 if (t_type && (sdef->raw.taglist.list + t_type - 1)->nElements) {
1097 src = mputstr(src, " bool negtest_confl_tag = false;\n");
1098 }
1099 src = mputprintf(src,
1100 " err_vals = p_err_descr->get_field_err_values(%d);\n"
1101 " emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
1102 " if (err_vals && err_vals->value) {\n"
1103 " if (err_vals->value->raw) {\n"
1104 " myleaf.body.node.nodes[%lu] =\n"
1105 " new RAW_enc_tree(TRUE, &myleaf, &myleaf.curr_pos, %lu, "
1106 "err_vals->value->errval->get_descriptor()->raw);\n"
1107 " encoded_length = err_vals->value->errval->RAW_encode_negtest_raw(*myleaf.body.node.nodes[%lu]);\n"
1108 " myleaf.body.node.nodes[%lu]->coding_descr = err_vals->value->errval->get_descriptor();\n"
1109 " } else {\n"
1110 " if (err_vals->value->errval) {\n"
1111 " if (err_vals->value->type_descr == NULL)\n"
1112 " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
1113 " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(TRUE, &myleaf, &myleaf.curr_pos, %lu, err_vals->value->type_descr->raw);\n"
1114 " encoded_length = err_vals->value->errval->RAW_encode(*err_vals->value->type_descr, *myleaf.body.node.nodes[%lu]);\n"
1115 " myleaf.body.node.nodes[%lu]->coding_descr = err_vals->value->type_descr;\n"
1116 " }\n"
1117 " }\n",
1118 (int)i, (int)i,
1119 (unsigned long)i, (unsigned long)i,
1120 (unsigned long)i, (unsigned long)i, (unsigned long)i,
1121 (unsigned long)i, (unsigned long)i, (unsigned long)i);
1122 if (t_type && (sdef->raw.taglist.list + t_type - 1)->nElements) {
1123 /* Avoid TAGs. */
1124 src = mputprintf(src, " negtest_confl_tag = true;\n");
1125 }
1126 src = mputprintf(src,
1127 " } else {\n"
1128 " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(TRUE, "
1129 "&myleaf, &myleaf.curr_pos, %lu, %s_descr_.raw);\n"
1130 " if (emb_descr) {\n",
1131 (unsigned long)i, (unsigned long)i, sdef->elements[i].typedescrname);
1132 if (t_type && (sdef->raw.taglist.list + t_type - 1)->nElements) {
1133 /* Avoid TAGs. */
1134 src = mputprintf(src, " negtest_confl_tag = true;\n");
1135 }
1136 src = mputprintf(src,
1137 " encoded_length = field_%s->RAW_encode_negtest(emb_descr, %s_descr_, *myleaf.body.node.nodes[%lu]);\n"
1138 " } else encoded_length = field_%s->RAW_encode(%s_descr_, *myleaf.body.node.nodes[%lu]);\n"
1139 " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n"
1140 " }\n",
1141 sdef->elements[i].name, sdef->elements[i].typedescrname,
1142 (unsigned long)i, sdef->elements[i].name,
1143 sdef->elements[i].typedescrname, (unsigned long)i, (unsigned long)i,
1144 sdef->elements[i].typedescrname);
1145 if (t_type && (sdef->raw.taglist.list + t_type - 1)->nElements) {
1146 rawAST_coding_taglist *cur_choice = sdef->raw.taglist.list + t_type - 1;
1147 src = mputprintf(src,
1148 " if (negtest_confl_tag) {\n"
1149 " TTCN_EncDec_ErrorContext e_c;\n"
1150 " e_c.set_msg(\"Field '%s': \");\n"
1151 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1152 " \"Conflicting negative testing attributes, TAG attribute "
1153 "will be ignored\");\n"
1154 " }\n"
1155 " if (!negtest_confl_tag && (", sdef->elements[i].name);
1156 src = genRawFieldChecker(src, cur_choice, FALSE);
1157 src = mputstr(src, ")) {\n");
1158 src = genRawTagChecker(src, cur_choice);
1159 src = mputstr(src, " }\n");
1160 }
1161 src = mputstr(src, " break; }\n");
1162 }
1163 src = mputstr(src, " default:\n"
1164 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, "
1165 "\"Encoding an unbound value.\");\n"
1166 " }\n"
1167 " return encoded_length;\n"
1168 "}\n\n");
1169 }
1170 Free(tag_type);
1171 } /* if raw_needed */
1172
1173 if (text_needed) {
1174 src = mputprintf(src, "int %s::TEXT_encode("
1175 "const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const\n"
1176 "{\n", name);
1177 if (use_runtime_2) {
1178 src = mputstr(src, " if (err_descr) return TEXT_encode_negtest(err_descr, p_td, p_buf);\n");
1179 }
1180 src = mputstr(src, " int encoded_length=0;\n"
1181 " if (p_td.text->begin_encode) {\n"
1182 " p_buf.put_cs(*p_td.text->begin_encode);\n"
1183 " encoded_length += p_td.text->begin_encode->lengthof();\n"
1184 " }\n"
1185 " switch(union_selection){\n");
1186 for (i = 0; i < sdef->nElements; i++) {
1187 src = mputprintf(src, " case %s_%s:\n"
1188 " encoded_length += field_%s->TEXT_encode(%s_descr_,p_buf);\n"
1189 " break;\n", selection_prefix, sdef->elements[i].name,
1190 sdef->elements[i].name, sdef->elements[i].typedescrname);
1191 }
1192 src = mputstr(src, " default:\n"
1193 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, "
1194 "\"Encoding an unbound value.\");\n"
1195 " break;\n"
1196 " }\n"
1197 " if (p_td.text->end_encode) {\n"
1198 " p_buf.put_cs(*p_td.text->end_encode);\n"
1199 " encoded_length += p_td.text->end_encode->lengthof();\n"
1200 " }\n"
1201 " return encoded_length;\n"
1202 "}\n\n");
1203 if (use_runtime_2) {/*TEXT_encde_negtest()*/
1204 def = mputstr(def,
1205 "int TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const;\n");
1206 src = mputprintf(src, "int %s::TEXT_encode_negtest("
1207 "const Erroneous_descriptor_t* p_err_descr, const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf) const\n"
1208 "{\n"
1209 " int encoded_length=0;\n"
1210 " const Erroneous_values_t* err_vals = NULL;\n"
1211 " const Erroneous_descriptor_t* emb_descr = NULL;\n"
1212 " if (p_td.text->begin_encode) {\n"
1213 " p_buf.put_cs(*p_td.text->begin_encode);\n"
1214 " encoded_length += p_td.text->begin_encode->lengthof();\n"
1215 " }\n"
1216 " switch(union_selection){\n", name);
1217 for (i = 0; i < sdef->nElements; i++) {
1218 src = mputprintf(src, " case %s_%s:\n"
1219 " err_vals = p_err_descr->get_field_err_values(%d);\n"
1220 " emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
1221 " if (err_vals && err_vals->value){\n"
1222 " if (err_vals->value->errval) {\n"
1223 " if(err_vals->value->raw){\n"
1224 " encoded_length += err_vals->value->errval->encode_raw(p_buf);\n"
1225 " }else{\n"
1226 " if (err_vals->value->type_descr==NULL) TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
1227 " encoded_length += err_vals->value->errval->TEXT_encode(*err_vals->value->type_descr,p_buf);\n"
1228 " }\n"
1229 " }\n"
1230 " }else{\n"
1231 " if (emb_descr) encoded_length += field_%s->TEXT_encode_negtest(emb_descr,%s_descr_,p_buf);\n"
1232 " else field_%s->TEXT_encode(%s_descr_,p_buf);\n"
1233 " }\n"
1234 " break;\n", selection_prefix, sdef->elements[i].name,(int)i,(int)i,
1235 sdef->elements[i].name, sdef->elements[i].typedescrname, sdef->elements[i].name, sdef->elements[i].typedescrname);
1236 }
1237 src = mputstr(src, " default:\n"
1238 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, "
1239 "\"Encoding an unbound value.\");\n"
1240 " break;\n"
1241 " }\n"
1242 " if (p_td.text->end_encode) {\n"
1243 " p_buf.put_cs(*p_td.text->end_encode);\n"
1244 " encoded_length += p_td.text->end_encode->lengthof();\n"
1245 " }\n"
1246 " return encoded_length;\n"
1247 "}\n\n");
1248 }
1249
1250 src = mputprintf(src, "int %s::TEXT_decode("
1251 "const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& p_buf, "
1252 "Limit_Token_List& limit, boolean no_err, boolean)\n"
1253 "{\n"
1254 " int decoded_length = 0;\n"
1255 " if(p_td.text->begin_decode){\n"
1256 " int tl = p_td.text->begin_decode->match_begin(p_buf);\n"
1257 " if (tl >= 0) {\n"
1258 " decoded_length += tl;\n"
1259 " p_buf.increase_pos(tl);\n"
1260 " } else {\n"
1261 " if (no_err) return -1;\n"
1262 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR, "
1263 "\"The specified token '%%s' not found for '%%s': \", "
1264 "(const char*)(*p_td.text->begin_decode), p_td.name);\n"
1265 " return 0;\n"
1266 " }\n"
1267 " }\n"
1268 " if (p_buf.get_read_len() < 1 && no_err) return -1;\n"
1269 "%s"
1270 " int ml = 0;\n"
1271 " boolean found = FALSE;\n"
1272 " if (p_td.text->end_decode) {\n"
1273 " limit.add_token(p_td.text->end_decode);\n"
1274 " ml++;\n"
1275 " }\n", name, sdef->nElements > 1 ? " size_t pos = p_buf.get_pos();\n" : "");
1276 if (sdef->nElements > 0) {
1277 src = mputprintf(src,
1278 " int str_len = %s().TEXT_decode(%s_descr_, p_buf, limit, true);\n"
1279 " if (str_len >= 0) found = TRUE;\n", sdef->elements[0].name,
1280 sdef->elements[0].typedescrname);
1281 }
1282 for (i = 1; i < sdef->nElements; i++) {
1283 src = mputprintf(src, " if (!found) {\n"
1284 " p_buf.set_pos(pos);\n"
1285 " str_len = %s().TEXT_decode(%s_descr_, p_buf, limit, true);\n"
1286 " if (str_len >= 0) found = TRUE;\n"
1287 " }\n", sdef->elements[i].name, sdef->elements[i].typedescrname);
1288 }
1289 src = mputstr(src, " limit.remove_tokens(ml);\n"
1290 " if (found) {\n"
1291 " decoded_length += str_len;\n"
1292 " if (p_td.text->end_decode) {\n"
1293 " int tl = p_td.text->end_decode->match_begin(p_buf);\n"
1294 " if (tl >= 0){\n"
1295 " decoded_length += tl;\n"
1296 " p_buf.increase_pos(tl);\n"
1297 " } else {\n"
1298 " if (no_err) return -1;\n"
1299 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR, "
1300 "\"The specified token '%s' not found for '%s': \", "
1301 "(const char*)(*p_td.text->end_decode), p_td.name);\n"
1302 " }\n"
1303 " }\n"
1304 " } else {\n"
1305 " if (no_err) return -1;\n"
1306 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TOKEN_ERR, "
1307 "\"No union member found for '%s': \", p_td.name);\n"
1308 " clean_up();\n"
1309 " }\n"
1310 " return decoded_length;\n"
1311 "}\n");
1312 }
1313
1314 if (xer_needed) { /* XERSTUFF encoder functions for union */
1315 def = mputstr(def,
1316 "char **collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const;\n");
1317
1318 src=mputprintf(src,
1319 "boolean %s::can_start(const char *name, const char *uri,"
1320 " const XERdescriptor_t& xd, unsigned int flavor) {\n"
1321 " boolean exer = is_exer(flavor);\n"
1322 " if (!exer || (!(xd.xer_bits & UNTAGGED) && !(flavor & (USE_NIL|(exer ? XER_LIST : XER_RECOF))))) "
1323 /* If the union has no own tag, there is nothing to check. */
1324 "return check_name(name, xd, exer)" /* if false, return immediately */
1325 " && (!exer || (flavor & USE_TYPE_ATTR) || check_namespace(uri, xd));\n"
1326 /* else check the ns, unless Basic XER (which has no namespaces, ever)
1327 * or USE_TYPE (where we only have a name from the type id attribute) */
1328 , name
1329 );
1330 src = mputstr(src, " flavor &= ~XER_RECOF;\n");
1331
1332 /* An untagged union can start with the start tag of any alternative */
1333 for (i = 0; i < sdef->nElements; i++) {
1334 src=mputprintf(src,
1335 " if (%s::can_start(name, uri, %s_xer_, flavor)) return true;\n"
1336 , sdef->elements[i].type, sdef->elements[i].typegen
1337 );
1338 }
1339 src = mputstr(src, " return false;\n}\n\n");
1340
1341 src = mputprintf(src,
1342 "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool& def_ns) const {\n"
1343 " size_t num_collected;\n"
1344 " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n"
1345 /* Two-level new memory allocated */
1346 " char **new_ns;\n"
1347 " size_t num_new;\n"
1348 " boolean need_type = FALSE;\n"
1349 " try {\n"
1350 " bool def_ns_1 = false;\n"
1351 " switch (union_selection) {\n"
1352 , name
1353 );
1354 for (i = 0; i < sdef->nElements; i++) {
1355 src = mputprintf(src,
1356 " case %s_%s:\n"
1357 " new_ns = field_%s->collect_ns(%s_xer_, num_new, def_ns_1);\n"
1358 " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */
1359 " merge_ns(collected_ns, num_collected, new_ns, num_new);\n"
1360 /* merge_ns() deallocated new_ns and duplicated strings,
1361 * copied the new ones into the expanded new_ns */
1362 , selection_prefix, sdef->elements[i].name
1363 , sdef->elements[i].name
1364 , sdef->elements[i].typegen
1365 );
1366 /* Type id attribute not needed for the first field in case of USE-TYPE */
1367 if (sdef->xerUseUnion || i > 0) src = mputprintf(src,
1368 " need_type = (%s_xer_.namelens[1] > 2);\n"
1369 , sdef->elements[i].typegen);
1370 src = mputstr(src, " break;\n");
1371 }
1372
1373 src = mputstr(src,
1374 " default: break;\n"
1375 " }\n" /* switch */
1376 " if ((p_td.xer_bits & USE_TYPE_ATTR) && !(p_td.xer_bits & XER_ATTRIBUTE) && need_type) {\n"
1377 /* control ns for type attribute */
1378 " collected_ns = (char**)Realloc(collected_ns, sizeof(char*) * ++num_collected);\n"
1379 " const namespace_t *c_ns = p_td.my_module->get_controlns();\n"
1380 " collected_ns[num_collected-1] = mprintf(\" xmlns:%s='%s'\", c_ns->px, c_ns->ns);\n"
1381 " }\n"
1382 " }\n"
1383 " catch (...) {\n"
1384 /* Probably a TC_Error thrown from field_%s->collect_ns() if e.g.
1385 * encoding an unbound value. */
1386 " while (num_collected > 0) Free(collected_ns[--num_collected]);\n"
1387 " Free(collected_ns);\n"
1388 " throw;\n"
1389 " }\n"
1390 " num = num_collected;\n"
1391 " return collected_ns;\n"
1392 "}\n\n"
1393 );
1394
1395 src = mputprintf(src, /* XERSTUFF XER_encode for union */
1396 "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
1397 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n"
1398 "{\n"
1399 "%s"
1400 " if (%s==union_selection) {\n"
1401 " TTCN_error(\"Attempt to XER-encode an unbound union value.\");\n"
1402 " return 0;\n"
1403 " }\n"
1404 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
1405 " TTCN_EncDec_ErrorContext ec_1;\n"
1406 " int encoded_length=(int)p_buf.get_len();\n"
1407 , name
1408 , (use_runtime_2 ? " if (err_descr) return XER_encode_negtest"
1409 "(err_descr, p_td, p_buf, p_flavor, p_indent, 0);\n" : "")
1410 , unbound_value
1411 );
1412
1413 if (sdef->xerUseTypeAttr) {
1414 src = mputstr(src,
1415 " const boolean e_xer = is_exer(p_flavor);\n"
1416 " char *type_atr = NULL;\n"
1417 " if (e_xer && (p_td.xer_bits & USE_TYPE_ATTR)) {\n"
1418 " char *type_name = 0;\n"
1419 " const namespace_t *control_ns;\n"
1420 " switch (union_selection) {\n");
1421 /* In case of USE-TYPE the first field won't need the type attribute */
1422 int start_at = sdef->xerUseUnion ? 0 : 1;
1423 for (i = start_at; i < sdef->nElements; i++) {
1424 src = mputprintf(src,
1425 " case %s_%s:\n"
1426 " if (%s_xer_.my_module != 0 && %s_xer_.ns_index != -1 &&\n"
1427 " %s_xer_.namelens[1] > 2) {\n"
1428 /* add the namespace prefix to the type attribute (if the name is not empty) */
1429 " const namespace_t *my_ns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
1430 " if (my_ns->px[0] != 0) {\n"
1431 " type_name = mprintf(\"%%s:\", my_ns->px);\n"
1432 " }\n"
1433 " }\n"
1434 " type_name = mputstrn(type_name, %s_xer_.names[1], %s_xer_.namelens[1] - 2);\n"
1435 " %s\n"
1436 , selection_prefix, sdef->elements[i].name
1437 , sdef->elements[i].typegen, sdef->elements[i].typegen
1438 , sdef->elements[i].typegen, sdef->elements[i].typegen
1439 , sdef->elements[i].typegen, sdef->elements[i].typegen
1440 , sdef->elements[i].typegen
1441 , i < sdef->nElements - 1 ? "goto write_atr;" : "" /* no break */
1442 );
1443 }
1444 src = mputprintf(src,
1445 "%s" /* label only if more than two elements total */
1446 " if (mstrlen(type_name) > 0) {\n" /* 38.3.8, no atr if NAME AS "" */
1447 " control_ns = p_td.my_module->get_controlns();\n"
1448 " type_atr = mcopystr(\" \");\n"
1449 " type_atr = mputstr(type_atr, control_ns->px);\n"
1450 " type_atr = mputstr(type_atr, \":type='\");\n"
1451 " type_atr = mputstr(type_atr, type_name);\n"
1452 " type_atr = mputc (type_atr, '\\'');\n"
1453 " Free(type_name);\n"
1454 " }\n"
1455 " break;\n"
1456 " default: break;\n"
1457 " }\n" /* switch */
1458 " p_flavor &= ~XER_RECOF;\n"
1459 " }\n" /* if e_xer */
1460 , (sdef->nElements > start_at + 1 ? "write_atr:\n" : "")
1461
1462
1463 );
1464 } /* if UseTypeAttr */
1465 src = mputprintf(src,
1466 " unsigned int flavor_1 = p_flavor;\n"
1467 " if (is_exer(p_flavor)) flavor_1 &= ~XER_RECOF;\n"
1468 " bool omit_tag = begin_xml(p_td, p_buf, flavor_1, p_indent, false, "
1469 "(collector_fn)&%s::collect_ns%s);\n"
1470 , sdef->name
1471 , sdef->xerUseTypeAttr ? ", type_atr" : "");
1472 src = mputprintf(src,
1473 " unsigned int flavor_0 = (p_flavor & XER_MASK)%s;\n"
1474 " switch (union_selection) {\n"
1475 , sdef->xerUseTypeAttr ? " | USE_TYPE_ATTR" : "");
1476 for (i = 0; i < sdef->nElements; i++) {
1477 src = mputprintf(src, " case %s_%s:\n"
1478 " ec_1.set_msg(\"%s': \");\n"
1479 " field_%s->XER_encode(%s_xer_, p_buf, flavor_0, "
1480 "p_indent + (!p_indent || !omit_tag), 0);\n"
1481 " break;\n",
1482 selection_prefix, sdef->elements[i].name,
1483 sdef->elements[i].dispname,
1484 sdef->elements[i].name, sdef->elements[i].typegen);
1485 }
1486 src = mputprintf(src, " case %s:\n"
1487 " (void)flavor_0;\n" /* warning reduction for empty union */
1488 " break;\n"
1489 " } //switch\n"
1490 , unbound_value);
1491 if (sdef->xerUseTypeAttr) {
1492 src = mputstr(src, " if (p_buf.get_data()[p_buf.get_len()-1] != '\\n') flavor_1 |= SIMPLE_TYPE;\n");
1493 }
1494 src = mputstr(src,
1495 " end_xml(p_td, p_buf, flavor_1, p_indent, 0);\n"
1496 " return (int)p_buf.get_len() - encoded_length;\n"
1497 "}\n\n");
1498
1499 if (use_runtime_2) {
1500 def = mputstr(def,
1501 "int XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
1502 "const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
1503 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const;\n");
1504 src = mputprintf(src, /* XERSTUFF XER_encode for union */
1505 "int %s::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
1506 "const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
1507 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n"
1508 "{\n"
1509 " if (%s==union_selection) {\n"
1510 " TTCN_error(\"Attempt to XER-encode an unbound union value.\");\n"
1511 " return 0;\n"
1512 " }\n"
1513 " TTCN_EncDec_ErrorContext ec_0(\"Alternative '\");\n"
1514 " TTCN_EncDec_ErrorContext ec_1;\n"
1515 " int encoded_length=(int)p_buf.get_len();\n"
1516 , name
1517 , unbound_value
1518 );
1519 if (sdef->xerUseTypeAttr) {
1520 src = mputstr(src,
1521 " const boolean e_xer = is_exer(p_flavor);\n"
1522 " char *type_atr = NULL;\n"
1523 " if (e_xer && (p_td.xer_bits & USE_TYPE_ATTR)) {\n"
1524 " char *type_name = 0;\n"
1525 " const namespace_t *control_ns;\n"
1526 " switch (union_selection) {\n");
1527 int start_at = sdef->xerUseUnion ? 0 : 1;
1528 for (i = start_at; i < sdef->nElements; i++) {
1529 src = mputprintf(src,
1530 " case %s_%s:\n"
1531 " if (%s_xer_.my_module != 0 && %s_xer_.ns_index != -1 &&\n"
1532 " %s_xer_.namelens[1] > 2) {\n"
1533 /* add the namespace prefix to the type attribute (if the name is not empty) */
1534 " const namespace_t *my_ns = %s_xer_.my_module->get_ns(%s_xer_.ns_index);\n"
1535 " if (my_ns->px[0] != 0) {\n"
1536 " type_name = mprintf(\"%%s:\", my_ns->px);\n"
1537 " }\n"
1538 " }\n"
1539 " type_name = mputstrn(type_name, %s_xer_.names[1], %s_xer_.namelens[1] - 2);\n"
1540 " %s\n"
1541 , selection_prefix, sdef->elements[i].name
1542 , sdef->elements[i].typegen, sdef->elements[i].typegen
1543 , sdef->elements[i].typegen, sdef->elements[i].typegen
1544 , sdef->elements[i].typegen, sdef->elements[i].typegen
1545 , sdef->elements[i].typegen
1546 , i < sdef->nElements - 1 ? "goto write_atr;" : "" /* no break */
1547 );
1548 }
1549 src = mputprintf(src,
1550 "%s" /* label only if more than two elements total */
1551 " if (mstrlen(type_name) > 0) {\n" /* 38.3.8, no atr if NAME AS "" */
1552 " control_ns = p_td.my_module->get_controlns();\n"
1553 " type_atr = mcopystr(\" \");\n"
1554 " type_atr = mputstr(type_atr, control_ns->px);\n"
1555 " type_atr = mputstr(type_atr, \":type='\");\n"
1556 " type_atr = mputstr(type_atr, type_name);\n"
1557 " type_atr = mputc (type_atr, '\\'');\n"
1558 " Free(type_name);\n"
1559 " }\n"
1560 " break;\n"
1561 " default: break;\n"
1562 " }\n" /* switch */
1563 " p_flavor &= ~XER_RECOF;\n"
1564 " }\n" /* if e_xer */
1565 , (sdef->nElements > start_at + 1 ? "write_atr:\n" : "")
1566 );
1567 } /* if UseTypeAttr */
1568
1569 src = mputprintf(src,
1570 " bool omit_tag = begin_xml(p_td, p_buf, p_flavor, p_indent, false, "
1571 "(collector_fn)&%s::collect_ns%s);\n"
1572 , sdef->name
1573 , sdef->xerUseTypeAttr ? ", type_atr" : "");
1574 /* begin_xml will Free type_atr */
1575 src = mputprintf(src,
1576 " unsigned int flavor_0 = (p_flavor & XER_MASK)%s;\n"
1577 " const Erroneous_values_t* err_vals = NULL;\n"
1578 " const Erroneous_descriptor_t* emb_descr = NULL;\n"
1579 " switch (union_selection) {\n"
1580 , sdef->xerUseTypeAttr ? " | USE_TYPE_ATTR" : "");
1581 for (i = 0; i < sdef->nElements; i++) {
1582 src = mputprintf(src, " case %s_%s:\n"
1583 " err_vals = p_err_descr->get_field_err_values(%lu);\n"
1584 " emb_descr = p_err_descr->get_field_emb_descr(%lu);\n"
1585 " if (err_vals && err_vals->value) {\n"
1586 " if (err_vals->value->errval) {\n"
1587 " ec_1.set_msg(\"%s'(erroneous value): \");\n"
1588 " if (err_vals->value->raw) {\n"
1589 " err_vals->value->errval->encode_raw(p_buf);\n"
1590 " } else {\n"
1591 " if (err_vals->value->type_descr==NULL) TTCN_error"
1592 "(\"internal error: erroneous value typedescriptor missing\");\n"
1593 " else err_vals->value->errval->XER_encode("
1594 "*err_vals->value->type_descr->xer, p_buf, flavor_0, "
1595 "p_indent + (!p_indent || !omit_tag), 0);\n"
1596 " }\n"
1597 " }\n"
1598 " } else {\n"
1599 " ec_1.set_msg(\"%s': \");\n"
1600 " if (emb_descr) field_%s->XER_encode_negtest(emb_descr, "
1601 "%s_xer_, p_buf, flavor_0, p_indent + (!p_indent || !omit_tag), 0);\n"
1602 " else field_%s->XER_encode(%s_xer_, p_buf, flavor_0, "
1603 "p_indent + (!p_indent || !omit_tag), 0);\n"
1604 " }\n"
1605 " break;\n",
1606 selection_prefix, sdef->elements[i].name, /* case label */
1607 (unsigned long)i, (unsigned long)i,
1608 sdef->elements[i].dispname, /* set_msg (erroneous) */
1609 sdef->elements[i].dispname, /* set_msg */
1610 sdef->elements[i].name, sdef->elements[i].typegen,
1611 sdef->elements[i].name, sdef->elements[i].typegen /* field_%s, %s_descr */
1612 );
1613 }
1614 src = mputprintf(src, " case %s:\n"
1615 " (void)flavor_0;\n" /* warning reduction for empty union */
1616 " break;\n"
1617 " } //switch\n"
1618 " end_xml(p_td, p_buf, p_flavor, p_indent, 0);\n"
1619 " return (int)p_buf.get_len() - encoded_length;\n"
1620 "}\n\n"
1621 , unbound_value);
1622 }
1623
1624 #ifndef NDEBUG
1625 src = mputprintf(src, "// %s has%s%s%s%s%s%s%s%s%s\n"
1626 "// written by %s in " __FILE__ " at %d\n"
1627 , name
1628 , (sdef->xerUntagged ? " UNTAGGED" : "")
1629 , (sdef->xerUntaggedOne ? "1" : "")
1630 , (sdef->xerUseNilPossible ? " USE_NIL?" : "")
1631 , (sdef->xerUseOrderPossible ? " USE_ORDER?" : "")
1632 , (sdef->xerUseQName ? " USE_QNAME" : "")
1633 , (sdef->xerUseTypeAttr ? " USE_TYPE_ATTR" : "")
1634 , (sdef->xerUseUnion ? " USE-UNION" : "")
1635 , (sdef->xerHasNamespaces ? " namespace" : "")
1636 , (sdef->xerEmbedValuesPossible ? " EMBED?" : "")
1637 , __FUNCTION__, __LINE__
1638 );
1639 #endif
1640 src = mputprintf(src, /* XERSTUFF decoder functions for union */
1641 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader,"
1642 " unsigned int p_flavor, unsigned int p_flavor2, embed_values_dec_struct_t*)\n"
1643 "{\n"
1644 " int e_xer = is_exer(p_flavor);\n"
1645 " int type = 0;\n" /* None */
1646 " int rd_ok=1, xml_depth=-1;\n"
1647 "%s%s"
1648 " int xerbits = p_td.xer_bits;\n"
1649 " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n"
1650 " if (xerbits & USE_TYPE_ATTR) p_flavor &= ~XER_RECOF;\n"
1651 " boolean own_tag = !(e_xer && ((xerbits & (ANY_ELEMENT | UNTAGGED)) "
1652 "|| (p_flavor & (USE_NIL|(e_xer ? XER_LIST : XER_RECOF)))));\n"
1653 " if ((e_xer || !is_record_of(p_flavor)) && own_tag)\n"
1654 /* Loop until the start tag */
1655 " %sfor (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
1656 " type = p_reader.NodeType();\n"
1657 " if (type == XML_READER_TYPE_ELEMENT) {\n"
1658 " verify_name(p_reader, p_td, e_xer);\n"
1659 " xml_depth = p_reader.Depth();\n"
1660 , name
1661 , sdef->xerUseTypeAttr ? " char * typeatr = 0;\n" : ""
1662 , sdef->xerUseUnion ? " boolean attribute = (p_td.xer_bits & XER_ATTRIBUTE) ? true : false;\n" : ""
1663 , sdef->xerUseUnion ? "if (!attribute) " : ""
1664 );
1665 if (sdef->xerUseTypeAttr) {
1666 src = mputprintf(src,
1667 " int other_attributes = 0;\n"
1668 " if (e_xer) {\n"
1669 " for (rd_ok = p_reader.MoveToFirstAttribute(); rd_ok == 1;"
1670 " rd_ok = p_reader.MoveToNextAttribute()) {\n"
1671 " if (p_reader.IsNamespaceDecl()) continue;\n"
1672 " const char *attr_name = (const char*)p_reader.Name();\n"
1673 " if (!strcmp(attr_name, \"%s:type\"))\n"
1674 " {\n"
1675 " typeatr = mcopystr((const char*)p_reader.Value());\n"
1676 " }\n"
1677 " else ++other_attributes;\n"
1678 " }\n" /* for */
1679 " rd_ok = p_reader.MoveToElement() | 1;\n"
1680 , sdef->control_ns_prefix);
1681 if (!sdef->xerUseUnion) {
1682 /* USE-TYPE: No type attribute means the first alternative */
1683 src = mputprintf(src,
1684 " if (typeatr == NULL) {\n"
1685 " typeatr = mcopystrn(%s_xer_.names[1], %s_xer_.namelens[1] - 2);\n"
1686 " }\n"
1687 , sdef->elements[0].typegen
1688 , sdef->elements[0].typegen);
1689 }
1690 src = mputstr(src,
1691 " }\n" /* if exer */);
1692 }
1693
1694 src = mputprintf(src,
1695 " if (!(e_xer && (p_td.xer_bits & USE_TYPE_ATTR)%s)\n"
1696 " && !p_reader.IsEmptyElement()) rd_ok = p_reader.Read();\n"
1697 " break;\n"
1698 " }\n"
1699 " }\n"
1700 " unsigned int flavor_1 = (p_flavor & XER_MASK);\n" /* also, not toplevel */
1701 /* Loop until the content. Normally an element, unless UNTAGGED
1702 * USE-UNION or some other shenanigans. */
1703 " %s%sfor (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
1704 " type = p_reader.NodeType();\n"
1705 " %sif (type == XML_READER_TYPE_ELEMENT) break;\n"
1706 " else if (type == XML_READER_TYPE_END_ELEMENT) break;\n"
1707 " }\n"
1708 " if (rd_ok) {\n"
1709 " TTCN_EncDec_ErrorContext ec_1(\"Alternative '\");\n"
1710 " TTCN_EncDec_ErrorContext ec_2;\n"
1711 " const char *elem_name;\n"
1712 " const char *ns_uri = 0;\n"
1713 , sdef->xerUseTypeAttr ? " && other_attributes > 0" : ""
1714 , sdef->xerUseTypeAttr ? "if (!e_xer) " : ""
1715 , sdef->xerUseUnion ? "if (!attribute) " : ""
1716 , sdef->xerUseTypeAttr ?
1717 "if (e_xer) { if (type == XML_READER_TYPE_TEXT) break; }\n"
1718 " else " : ""
1719 );
1720
1721 if (sdef->xerUseTypeAttr) {
1722 src = mputstr(src,
1723 " if (e_xer) {\n" /* USE-TYPE => no XML element, use typeatr */
1724 " char *token_1 = strtok(typeatr, \":\");\n" /* extract the namespace (if any) */
1725 " char *token_2 = strtok(NULL, \":\");\n"
1726 " if (token_2) {\n" /* namespace found */
1727 " elem_name = token_2;\n"
1728 " ns_uri = get_ns_uri_from_prefix(token_1, p_td);\n"
1729 " }\n"
1730 " else {\n" /* no namespace */
1731 " elem_name = token_1;\n"
1732 " }\n"
1733 " flavor_1 |= USE_TYPE_ATTR;\n"
1734 " }\n"
1735 " else" /* no newline, gobbles up the next {} */);
1736 }
1737 src = mputstr(src,
1738 " {\n"
1739 " elem_name = (const char*)p_reader.LocalName();\n"
1740 " ns_uri = (const char*)p_reader.NamespaceUri();\n"
1741 " }\n");
1742
1743 if (sdef->xerUseUnion) {
1744 src = mputstr(src,
1745 " int matched = -1;\n"
1746 " if (typeatr == NULL) flavor_1 |= EXIT_ON_ERROR;\n"
1747 " for (;;) {\n");
1748 /* TODO unify the two alternatives */
1749 for (i = 0; i < sdef->nElements; i++) {
1750 src = mputprintf(src,
1751 /* If decoding EXER, there is no tag to apply check_name
1752 *
1753 */
1754 " if ((e_xer && (typeatr == NULL || !(p_td.xer_bits & USE_TYPE_ATTR))) "
1755 "|| can_start(elem_name, ns_uri, %s_xer_, flavor_1)) {\n"
1756 " ec_2.set_msg(\"%s': \");\n"
1757 " if (%s==union_selection) {\n"
1758 " matched = %d;\n"
1759 " %s().XER_decode(%s_xer_, p_reader, flavor_1, p_flavor2, 0);\n"
1760 " }\n"
1761 " if (field_%s->is_bound()) break; else clean_up();\n"
1762 " }\n",
1763 sdef->elements[i].typegen,
1764 sdef->elements[i].dispname,
1765 unbound_value, (int)i,
1766 sdef->elements[i].name, sdef->elements[i].typegen,
1767 sdef->elements[i].name);
1768 }
1769 src = mputstr(src,
1770 " if (typeatr == NULL) {\n"
1771 /* No type attribute found and none of the fields managed to decode the value (USE-UNION only) */
1772 " ec_1.set_msg(\" \");\n"
1773 " ec_2.set_msg(\" \");\n"
1774 " const char* value = (const char*)p_reader.Value();\n"
1775 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1776 " \"'%s' could not be decoded by any of the union's fields.\", value);\n"
1777 " } else if (matched >= 0) {\n"
1778 /* Alternative found, but it couldn't be decoded */
1779 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1780 " \"Failed to decode field.\");\n"
1781 " } else {\n"
1782 /* Type attribute found, but it didn't match any of the fields */
1783 " ec_1.set_msg(\" \");\n"
1784 " ec_2.set_msg(\" \");\n"
1785 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1786 " \"'%s' does not match any alternative.\", elem_name);\n"
1787 " }\n"
1788 " if (xml_depth >= 0) for (; rd_ok == 1 "
1789 "&& p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
1790 " break;\n"
1791 " }\n"); /* for ever */
1792 }
1793 else /* not USE-UNION */
1794 {
1795 if (sdef->exerMaybeEmptyIndex >= 0) {
1796 /* There is a field which can be empty XML. Add code to detect this
1797 * and jump to the appropriate field which can decode "nothing". */
1798 src = mputstr(src,
1799 " if (type!=XML_READER_TYPE_ELEMENT || "
1800 "(own_tag && p_reader.IsEmptyElement())) goto empty_xml;\n");
1801 /* If the choice itself is untagged, then an empty element belongs to
1802 * one of the fields and does not mean that the choice is empty */
1803 }
1804 /* FIXME some hashing should be implemented */
1805 /* The field which can be empty should be checked last, otherwise we create an infinity loop with memory bomb.
1806 * So move that field to the last elseif branch*/
1807 for (i = 0; i < sdef->nElements; i++) {
1808 if(sdef->exerMaybeEmptyIndex != i){
1809 src = mputprintf(src,
1810 " %sif (%s::can_start(elem_name, ns_uri, %s_xer_, flavor_1) || (%s_xer_.xer_bits & ANY_ELEMENT)) {\n"
1811 " ec_2.set_msg(\"%s': \");\n"
1812 " if (e_xer && (%s_xer_.xer_bits & BLOCKED)) {\n"
1813 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1814 " \"Attempting to decode blocked or abstract field.\");\n"
1815 " }\n"
1816 " %s%s().XER_decode(%s_xer_, p_reader, flavor_1, p_flavor2, 0);\n"
1817 " if (!%s%s().is_bound()) {\n"
1818 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, \"Failed to decode field.\");\n"
1819 " }\n"
1820 " }\n",
1821 i && !(i==1 && sdef->exerMaybeEmptyIndex==0) ? "else " : "", /* print "if(" if generate code for the first field or if the first field is the MaybeEmpty field and we generate the code for the second one*/
1822 sdef->elements[i].type, sdef->elements[i].typegen, sdef->elements[i].typegen,
1823 sdef->elements[i].dispname,
1824 sdef->elements[i].typegen,
1825 at_field, sdef->elements[i].name, sdef->elements[i].typegen,
1826 at_field, sdef->elements[i].name);
1827 }
1828 }
1829 if(sdef->exerMaybeEmptyIndex>=0 ){
1830 i=sdef->exerMaybeEmptyIndex;
1831 src = mputprintf(src,
1832 " %sif ((e_xer && (type==XML_READER_TYPE_END_ELEMENT || !own_tag)) || %s::can_start(elem_name, ns_uri, %s_xer_, flavor_1) || (%s_xer_.xer_bits & ANY_ELEMENT)) {\n"
1833 "empty_xml: ec_2.set_msg(\"%s': \");\n"
1834 " if (e_xer && (%s_xer_.xer_bits & BLOCKED)) {\n"
1835 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
1836 " \"Attempting to decode blocked or abstract field.\");\n"
1837 " }\n"
1838 " %s%s().XER_decode(%s_xer_, p_reader, flavor_1, p_flavor2, 0);\n"
1839 " if (!%s%s().is_bound()) {\n"
1840 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, \"Failed to decode field.\");\n"
1841 " }\n"
1842 " }\n",
1843 sdef->nElements>0 ? "else " : "",
1844 sdef->elements[i].type, sdef->elements[i].typegen, sdef->elements[i].typegen,
1845 sdef->elements[i].dispname,
1846 sdef->elements[i].typegen,
1847 at_field, sdef->elements[i].name, sdef->elements[i].typegen,
1848 at_field, sdef->elements[i].name);
1849 }
1850 if (!sdef->isOptional) {
1851 src = mputstr(src,
1852 " else {\n"
1853 " ec_1.set_msg(\" \");\n"
1854 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
1855 "\"'%s' does not match any alternative\", elem_name);\n"
1856 " if (xml_depth >= 0) for (; rd_ok == 1 "
1857 "&& p_reader.Depth() > xml_depth; rd_ok = p_reader.Read()) ;\n"
1858 " }\n"
1859 );
1860 }
1861 }
1862
1863 src = mputprintf(src,
1864 " }\n" /* end if(rd_ok) */
1865 " if (%s(e_xer || !is_record_of(p_flavor)) && own_tag)\n"
1866 " for (; rd_ok == 1; rd_ok = p_reader.Read()) {\n"
1867 " type = p_reader.NodeType();\n"
1868 " if (type == XML_READER_TYPE_END_ELEMENT) {\n"
1869 " verify_end(p_reader, p_td, xml_depth, e_xer);\n"
1870 " rd_ok = p_reader.Read(); // one last time\n"
1871 " break;\n"
1872 " }\n"
1873 " }\n"
1874 "%s"
1875 " return 1;\n"
1876 "}\n\n", sdef->xerUseUnion ? "!attribute && " : "",
1877 sdef->xerUseTypeAttr ? " Free(typeatr);\n" : "");
1878 }
1879 if (json_needed) {
1880 // JSON encode
1881 src = mputprintf(src,
1882 "int %s::JSON_encode(const TTCN_Typedescriptor_t&%s, JSON_Tokenizer& p_tok) const\n"
1883 "{\n", name, use_runtime_2 ? " p_td" : "");
1884 if (use_runtime_2) {
1885 src = mputstr(src, " if (err_descr) return JSON_encode_negtest(err_descr, p_td, p_tok);\n");
1886 }
1887 if (!sdef->jsonAsValue) {
1888 src = mputstr(src, " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n");
1889 } else {
1890 src = mputstr(src, " int enc_len = 0;\n\n");
1891 }
1892 src = mputstr(src, " switch(union_selection) {\n");
1893
1894 for (i = 0; i < sdef->nElements; ++i) {
1895 src = mputprintf(src, " case %s_%s:\n", selection_prefix, sdef->elements[i].name);
1896 if (!sdef->jsonAsValue) {
1897 src = mputprintf(src, " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
1898 , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
1899 }
1900 src = mputprintf(src,
1901 " enc_len += field_%s->JSON_encode(%s_descr_, p_tok);\n"
1902 " break;\n"
1903 , sdef->elements[i].name, sdef->elements[i].typedescrname);
1904 }
1905 src = mputprintf(src,
1906 " default:\n"
1907 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, \n"
1908 " \"Encoding an unbound value of type %s.\");\n"
1909 " return -1;\n"
1910 " }\n\n"
1911 , dispname);
1912 if (!sdef->jsonAsValue) {
1913 src = mputstr(src, " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n");
1914 }
1915 src = mputstr(src,
1916 " return enc_len;\n"
1917 "}\n\n");
1918
1919 if (use_runtime_2) {
1920 // JSON encode for negative testing
1921 def = mputstr(def,
1922 "int JSON_encode_negtest(const Erroneous_descriptor_t*, "
1923 "const TTCN_Typedescriptor_t&, JSON_Tokenizer&) const;\n");
1924 src = mputprintf(src,
1925 "int %s::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr, "
1926 "const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
1927 "{\n", name);
1928 if (!sdef->jsonAsValue) {
1929 src = mputstr(src, " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n");
1930 } else {
1931 src = mputstr(src, " int enc_len = 0;\n\n");
1932 }
1933 src = mputstr(src,
1934 " const Erroneous_values_t* err_vals = NULL;\n"
1935 " const Erroneous_descriptor_t* emb_descr = NULL;\n"
1936 " switch(union_selection) {\n");
1937
1938 for (i = 0; i < sdef->nElements; ++i) {
1939 src = mputprintf(src,
1940 " case %s_%s:\n"
1941 " err_vals = p_err_descr->get_field_err_values(%d);\n"
1942 " emb_descr = p_err_descr->get_field_emb_descr(%d);\n"
1943 " if (NULL != err_vals && NULL != err_vals->value) {\n"
1944 " if (NULL != err_vals->value->errval) {\n"
1945 " if(err_vals->value->raw){\n"
1946 " enc_len += err_vals->value->errval->JSON_encode_negtest_raw(p_tok);\n"
1947 " } else {\n"
1948 " if (NULL == err_vals->value->type_descr) {\n"
1949 " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
1950 " }\n"
1951 , selection_prefix, sdef->elements[i].name, (int)i, (int)i);
1952 if (!sdef->jsonAsValue) {
1953 src = mputprintf(src, " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
1954 , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
1955 }
1956 src = mputstr(src,
1957 " enc_len += err_vals->value->errval->JSON_encode(*err_vals->value->type_descr, p_tok);\n"
1958 " }\n"
1959 " }\n"
1960 " } else {\n");
1961 if (!sdef->jsonAsValue) {
1962 src = mputprintf(src, " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
1963 , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
1964 }
1965 src = mputprintf(src,
1966 " if (NULL != emb_descr) {\n"
1967 " enc_len += field_%s->JSON_encode_negtest(emb_descr, %s_descr_, p_tok);\n"
1968 " } else {\n"
1969 " enc_len += field_%s->JSON_encode(%s_descr_, p_tok);\n"
1970 " }\n"
1971 " }\n"
1972 " break;\n"
1973 , sdef->elements[i].name, sdef->elements[i].typedescrname
1974 , sdef->elements[i].name, sdef->elements[i].typedescrname);
1975 }
1976 src = mputprintf(src,
1977 " default:\n"
1978 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND, \n"
1979 " \"Encoding an unbound value of type %s.\");\n"
1980 " return -1;\n"
1981 " }\n\n"
1982 , dispname);
1983 if (!sdef->jsonAsValue) {
1984 src = mputstr(src, " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n");
1985 }
1986 src = mputstr(src,
1987 " return enc_len;\n"
1988 "}\n\n");
1989 }
1990
1991 // JSON decode
1992 src = mputprintf(src,
1993 "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
1994 "{\n"
1995 " json_token_t j_token = JSON_TOKEN_NONE;\n"
1996 , name);
1997 if (sdef->jsonAsValue) {
1998 src = mputstr(src,
1999 " size_t buf_pos = p_tok.get_buf_pos();\n"
2000 " p_tok.get_next_token(&j_token, NULL, NULL);\n"
2001 " int ret_val = 0;\n"
2002 " switch(j_token) {\n"
2003 " case JSON_TOKEN_NUMBER: {\n");
2004 for (i = 0; i < sdef->nElements; ++i) {
2005 if (JSON_NUMBER & sdef->elements[i].jsonValueType) {
2006 src = mputprintf(src,
2007 " p_tok.set_buf_pos(buf_pos);\n"
2008 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2009 " if (0 <= ret_val) {\n"
2010 " return ret_val;\n"
2011 " }\n"
2012 , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
2013 }
2014 }
2015 src = mputstr(src,
2016 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"number\");\n"
2017 " clean_up();\n"
2018 " return JSON_ERROR_FATAL;\n"
2019 " }\n"
2020 " case JSON_TOKEN_STRING: {\n");
2021 for (i = 0; i < sdef->nElements; ++i) {
2022 if (JSON_STRING & sdef->elements[i].jsonValueType) {
2023 src = mputprintf(src,
2024 " p_tok.set_buf_pos(buf_pos);\n"
2025 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2026 " if (0 <= ret_val) {\n"
2027 " return ret_val;\n"
2028 " }\n"
2029 , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
2030 }
2031 }
2032 src = mputstr(src,
2033 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"string\");\n"
2034 " clean_up();\n"
2035 " return JSON_ERROR_FATAL;\n"
2036 " }\n"
2037 " case JSON_TOKEN_LITERAL_TRUE:\n"
2038 " case JSON_TOKEN_LITERAL_FALSE: {\n");
2039 for (i = 0; i < sdef->nElements; ++i) {
2040 if (JSON_BOOLEAN & sdef->elements[i].jsonValueType) {
2041 src = mputprintf(src,
2042 " p_tok.set_buf_pos(buf_pos);\n"
2043 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2044 " if (0 <= ret_val) {\n"
2045 " return ret_val;\n"
2046 " }\n"
2047 , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
2048 }
2049 }
2050 src = mputstr(src,
2051 " char* literal_str = mprintf(\"literal (%s)\",\n"
2052 " (JSON_TOKEN_LITERAL_TRUE == j_token) ? \"true\" : \"false\");\n"
2053 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, literal_str);\n"
2054 " Free(literal_str);\n"
2055 " clean_up();\n"
2056 " return JSON_ERROR_FATAL;\n"
2057 " }\n"
2058 " case JSON_TOKEN_ARRAY_START: {\n");
2059 for (i = 0; i < sdef->nElements; ++i) {
2060 if (JSON_ARRAY & sdef->elements[i].jsonValueType) {
2061 src = mputprintf(src,
2062 " p_tok.set_buf_pos(buf_pos);\n"
2063 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2064 " if (0 <= ret_val) {\n"
2065 " return ret_val;\n"
2066 " }\n"
2067 , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
2068 }
2069 }
2070 src = mputstr(src,
2071 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"array\");\n"
2072 " clean_up();\n"
2073 " return JSON_ERROR_FATAL;\n"
2074 " }\n"
2075 " case JSON_TOKEN_OBJECT_START: {\n");
2076 for (i = 0; i < sdef->nElements; ++i) {
2077 if (JSON_OBJECT & sdef->elements[i].jsonValueType) {
2078 src = mputprintf(src,
2079 " p_tok.set_buf_pos(buf_pos);\n"
2080 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2081 " if (0 <= ret_val) {\n"
2082 " return ret_val;\n"
2083 " }\n"
2084 , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
2085 }
2086 }
2087 src = mputstr(src,
2088 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_AS_VALUE_ERROR, \"object\");\n"
2089 " clean_up();\n"
2090 " return JSON_ERROR_FATAL;\n"
2091 " }\n"
2092 " case JSON_TOKEN_LITERAL_NULL: {\n");
2093 for (i = 0; i < sdef->nElements; ++i) {
2094 if (JSON_NULL & sdef->elements[i].jsonValueType) {
2095 src = mputprintf(src,
2096 " p_tok.set_buf_pos(buf_pos);\n"
2097 " ret_val = %s%s().JSON_decode(%s_descr_, p_tok, true);\n"
2098 " if (0 <= ret_val) {\n"
2099 " return ret_val;\n"
2100 " }\n"
2101 , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname);
2102 }
2103 }
2104 src = mputstr(src,
2105 " clean_up();\n"
2106 // the caller might be able to decode the null value if it's an optional field
2107 // only return an invalid token error, not a fatal error
2108 " return JSON_ERROR_INVALID_TOKEN;\n"
2109 " }\n"
2110 " case JSON_TOKEN_ERROR:\n"
2111 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
2112 " return JSON_ERROR_FATAL;\n"
2113 " default:\n"
2114 " return JSON_ERROR_INVALID_TOKEN;\n"
2115 " }\n"
2116 " return 0;\n"
2117 "}\n\n");
2118 } else { // not "as value"
2119 src = mputprintf(src,
2120 " int dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
2121 " if (JSON_TOKEN_ERROR == j_token) {\n"
2122 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
2123 " return JSON_ERROR_FATAL;\n"
2124 " }\n"
2125 " else if (JSON_TOKEN_OBJECT_START != j_token) {\n"
2126 " return JSON_ERROR_INVALID_TOKEN;\n"
2127 " }\n\n"
2128 " char* fld_name = 0;\n"
2129 " size_t name_len = 0;\n"
2130 " dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n"
2131 " if (JSON_TOKEN_NAME != j_token) {\n"
2132 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n"
2133 " return JSON_ERROR_FATAL;\n"
2134 " } else {\n"
2135 " union_selection = %s;\n "
2136 , unbound_value);
2137 for (i = 0; i < sdef->nElements; ++i) {
2138 src = mputprintf(src,
2139 "if (0 == strncmp(fld_name, \"%s\", name_len)) {\n"
2140 " int ret_val = %s%s().JSON_decode(%s_descr_, p_tok, p_silent);\n"
2141 " if (0 > ret_val) {\n"
2142 " if (JSON_ERROR_INVALID_TOKEN) {\n"
2143 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n"
2144 " }\n"
2145 " return JSON_ERROR_FATAL;\n"
2146 " } else {\n"
2147 " dec_len += ret_val;\n"
2148 " }\n"
2149 " } else "
2150 , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname
2151 , at_field, sdef->elements[i].name, sdef->elements[i].typedescrname
2152 , sdef->elements[i].dispname);
2153 }
2154 src = mputstr(src,
2155 "{\n"
2156 " char* fld_name2 = mcopystrn(fld_name, name_len);\n"
2157 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, fld_name2);\n"
2158 " Free(fld_name2);\n"
2159 " return JSON_ERROR_FATAL;\n"
2160 " }\n"
2161 " }\n\n"
2162 " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
2163 " if (JSON_TOKEN_OBJECT_END != j_token) {\n"
2164 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n"
2165 " return JSON_ERROR_FATAL;\n"
2166 " }\n\n"
2167 " return dec_len;\n"
2168 "}\n\n");
2169 }
2170 }
2171
2172 /* end of class definition */
2173 def = mputstr(def, "};\n\n");
2174
2175 output->header.class_defs = mputstr(output->header.class_defs, def);
2176 Free(def);
2177
2178 output->source.methods = mputstr(output->source.methods, src);
2179 Free(src);
2180
2181 Free(selection_type);
2182 Free(unbound_value);
2183 Free(selection_prefix);
2184 }
2185
2186
2187 void defUnionTemplate(const struct_def *sdef, output_struct *output)
2188 {
2189 int i;
2190 const char *name = sdef->name, *dispname = sdef->dispname;
2191 const char *at_field = sdef->kind==ANYTYPE ? "AT_" : "";
2192 char *def = NULL, *src = NULL;
2193
2194 char *selection_type, *unbound_value, *selection_prefix;
2195 selection_type = mprintf("%s::union_selection_type", name);
2196 unbound_value = mprintf("%s::UNBOUND_VALUE", name);
2197 selection_prefix = mprintf("%s::ALT", name);
2198
2199 /* template class */
2200
2201 output->header.class_decls = mputprintf(output->header.class_decls,
2202 "class %s_template;\n", name);
2203
2204 /* template class header and data members */
2205 def = mputprintf(def, "class %s_template : public Base_Template {\n"
2206 "union {\n"
2207 "struct {\n"
2208 "%s union_selection;\n"
2209 "union {\n", name, selection_type);
2210 for (i = 0; i < sdef->nElements; i++) {
2211 def = mputprintf(def, "%s_template *field_%s;\n",
2212 sdef->elements[i].type, sdef->elements[i].name);
2213 }
2214 def = mputprintf(def, "};\n"
2215 "} single_value;\n"
2216 "struct {\n"
2217 "unsigned int n_values;\n"
2218 "%s_template *list_value;\n"
2219 "} value_list;\n"
2220 "};\n", name);
2221 if (use_runtime_2) {
2222 def = mputstr(def,
2223 "Erroneous_descriptor_t* err_descr;\n");
2224 }
2225
2226 /* copy_value function */
2227 def = mputprintf(def, "void copy_value(const %s& other_value);\n\n", name);
2228 src = mputprintf(src, "void %s_template::copy_value(const %s& other_value)\n"
2229 "{\n"
2230 "single_value.union_selection = other_value.get_selection();\n"
2231 "switch (single_value.union_selection) {\n", name, name);
2232 for (i = 0; i<sdef->nElements; i++) {
2233 src = mputprintf(src, "case %s_%s:\n"
2234 "single_value.field_%s = new %s_template(other_value.%s%s());\n"
2235 "break;\n", selection_prefix, sdef->elements[i].name,
2236 sdef->elements[i].name, sdef->elements[i].type,
2237 at_field, sdef->elements[i].name);
2238 }
2239 src = mputprintf(src, "default:\n"
2240 "TTCN_error(\"Initializing a template with an unbound value of type "
2241 "%s.\");\n"
2242 "}\n"
2243 "set_selection(SPECIFIC_VALUE);\n"
2244 "%s"
2245 "}\n\n", dispname,
2246 use_runtime_2 ? "err_descr = other_value.get_err_descr();\n" : "");
2247
2248 /* copy_template function */
2249 def = mputprintf(def, "void copy_template(const %s_template& "
2250 "other_value);\n", name);
2251 src = mputprintf(src, "void %s_template::copy_template(const "
2252 "%s_template& other_value)\n"
2253 "{\n"
2254 "switch (other_value.template_selection) {\n"
2255 "case SPECIFIC_VALUE:\n"
2256 "single_value.union_selection = "
2257 "other_value.single_value.union_selection;\n"
2258 "switch (single_value.union_selection) {\n", name, name);
2259 for (i = 0; i < sdef->nElements; i++) {
2260 src = mputprintf(src, "case %s_%s:\n"
2261 "single_value.field_%s = "
2262 "new %s_template(*other_value.single_value.field_%s);\n"
2263 "break;\n", selection_prefix, sdef->elements[i].name,
2264 sdef->elements[i].name, sdef->elements[i].type, sdef->elements[i].name);
2265 }
2266 src = mputprintf(src, "default:\n"
2267 "TTCN_error(\"Internal error: Invalid union selector in a specific value "
2268 "when copying a template of type %s.\");\n"
2269 "}\n"
2270 "case OMIT_VALUE:\n"
2271 "case ANY_VALUE:\n"
2272 "case ANY_OR_OMIT:\n"
2273 "break;\n"
2274 "case VALUE_LIST:\n"
2275 "case COMPLEMENTED_LIST:\n"
2276 "value_list.n_values = other_value.value_list.n_values;\n"
2277 "value_list.list_value = new %s_template[value_list.n_values];\n"
2278 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2279 "list_count++)\n"
2280 "value_list.list_value[list_count].copy_template("
2281 "other_value.value_list.list_value[list_count]);\n"
2282 "break;\n"
2283 "default:\n"
2284 "TTCN_error(\"Copying an uninitialized template of union type %s.\");\n"
2285 "}\n"
2286 "set_selection(other_value);\n"
2287 "%s"
2288 "}\n\n", dispname, name, dispname,
2289 use_runtime_2 ? "err_descr = other_value.err_descr;\n" : "");
2290
2291 /* default constructor */
2292 def = mputprintf(def, "\npublic:\n"
2293 "%s_template();\n", name);
2294 src = mputprintf(src, "%s_template::%s_template()%s\n"
2295 "{\n"
2296 "}\n\n", name, name,
2297 use_runtime_2 ? ": err_descr(NULL)" : "");
2298
2299 /* constructor (template_sel) */
2300 def = mputprintf(def, "%s_template(template_sel other_value);\n", name);
2301 src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n"
2302 " : Base_Template(other_value)%s\n"
2303 "{\n"
2304 "check_single_selection(other_value);\n"
2305 "}\n\n", name, name,
2306 use_runtime_2 ? ", err_descr(NULL)" : "");
2307
2308 /* constructor (value) */
2309 def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name);
2310 src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n"
2311 "{\n"
2312 "copy_value(other_value);\n"
2313 "}\n\n", name, name, name);
2314
2315 /* constructor (optional value) */
2316 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n", name,
2317 name);
2318 src = mputprintf(src, "%s_template::%s_template(const OPTIONAL<%s>& "
2319 "other_value)\n"
2320 "{\n"
2321 "switch (other_value.get_selection()) {\n"
2322 "case OPTIONAL_PRESENT:\n"
2323 "copy_value((const %s&)other_value);\n"
2324 "break;\n"
2325 "case OPTIONAL_OMIT:\n"
2326 "set_selection(OMIT_VALUE);\n"
2327 "%s"
2328 "break;\n"
2329 "default:\n"
2330 "TTCN_error(\"Creating a template of union type %s from an unbound "
2331 "optional field.\");\n"
2332 "}\n"
2333 "}\n\n", name, name, name, name,
2334 use_runtime_2 ? "err_descr = NULL;\n" : "",
2335 dispname);
2336
2337 /* copy constructor */
2338 def = mputprintf(def, "%s_template(const %s_template& other_value);\n", name,
2339 name);
2340 src = mputprintf(src, "%s_template::%s_template(const %s_template& "
2341 "other_value)\n"
2342 ": Base_Template()" /* yes, the base class _default_ constructor */
2343 "{\n"
2344 "copy_template(other_value);\n"
2345 "}\n\n", name, name, name);
2346
2347 /* destructor */
2348 def = mputprintf(def, "~%s_template();\n", name);
2349 src = mputprintf(src, "%s_template::~%s_template()\n"
2350 "{\n"
2351 "clean_up();\n"
2352 "}\n\n", name, name);
2353
2354 /* clean_up function */
2355 def = mputstr(def, "void clean_up();\n");
2356 src = mputprintf(src, "void %s_template::clean_up()\n"
2357 "{\n"
2358 "switch (template_selection) {\n"
2359 "case SPECIFIC_VALUE:\n"
2360 "switch (single_value.union_selection) {\n", name);
2361 for (i = 0; i < sdef->nElements; i++) {
2362 src = mputprintf(src, "case %s_%s:\n"
2363 "delete single_value.field_%s;\n",
2364 selection_prefix, sdef->elements[i].name, sdef->elements[i].name);
2365 if (i < sdef->nElements - 1) src = mputstr(src, "break;\n");
2366 }
2367 src = mputstr(src, "default:\n"
2368 "break;\n"
2369 "}\n"
2370 "break;\n"
2371 "case VALUE_LIST:\n"
2372 "case COMPLEMENTED_LIST:\n"
2373 "delete [] value_list.list_value;\n"
2374 "default:\n"
2375 "break;\n"
2376 "}\n"
2377 "template_selection = UNINITIALIZED_TEMPLATE;\n"
2378 "}\n\n");
2379
2380 /* assignment operator (template_sel) */
2381 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
2382 name);
2383 src = mputprintf(src,
2384 "%s_template& %s_template::operator=(template_sel "
2385 "other_value)\n"
2386 "{\n"
2387 "check_single_selection(other_value);\n"
2388 "clean_up();\n"
2389 "set_selection(other_value);\n"
2390 "%s"
2391 "return *this;\n"
2392 "}\n\n", name, name, use_runtime_2 ? "err_descr = NULL;\n" : "");
2393
2394 /* assignment operator (value) */
2395 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
2396 name, name);
2397 src = mputprintf(src, "%s_template& %s_template::operator=(const %s& "
2398 "other_value)\n"
2399 "{\n"
2400 "clean_up();\n"
2401 "copy_value(other_value);\n"
2402 "return *this;\n"
2403 "}\n\n", name, name, name);
2404
2405 /* assignment operator <- optional value */
2406 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
2407 "other_value);\n", name, name);
2408 src = mputprintf(src,
2409 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
2410 "{\n"
2411 "clean_up();\n"
2412 "switch (other_value.get_selection()) {\n"
2413 "case OPTIONAL_PRESENT:\n"
2414 "copy_value((const %s&)other_value);\n"
2415 "break;\n"
2416 "case OPTIONAL_OMIT:\n"
2417 "set_selection(OMIT_VALUE);\n"
2418 "%s"
2419 "break;\n"
2420 "default:\n"
2421 "TTCN_error(\"Assignment of an unbound optional field to a template of "
2422 "union type %s.\");\n"
2423 "}\n"
2424 "return *this;\n"
2425 "}\n\n", name, name, name, name,
2426 use_runtime_2 ? "err_descr = NULL;\n" : "", dispname);
2427
2428 /* assignment operator (template) */
2429 def = mputprintf(def, "%s_template& operator=(const %s_template& "
2430 "other_value);\n", name, name);
2431 src = mputprintf(src,
2432 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
2433 "{\n"
2434 "if (&other_value != this) {\n"
2435 "clean_up();\n"
2436 "copy_template(other_value);\n"
2437 "}\n"
2438 "return *this;\n"
2439 "}\n\n", name, name, name);
2440
2441 /* match function */
2442 def = mputprintf(def, "boolean match(const %s& other_value, boolean legacy "
2443 "= FALSE) const;\n", name);
2444 src = mputprintf(src, "boolean %s_template::match(const %s& other_value, "
2445 "boolean legacy) const\n"
2446 "{\n"
2447 "if (!other_value.is_bound()) return FALSE;\n"
2448 "switch (template_selection) {\n"
2449 "case ANY_VALUE:\n"
2450 "case ANY_OR_OMIT:\n"
2451 "return TRUE;\n"
2452 "case OMIT_VALUE:\n"
2453 "return FALSE;\n"
2454 "case SPECIFIC_VALUE:\n"
2455 "{\n"
2456 "%s value_selection = other_value.get_selection();\n"
2457 "if (value_selection == %s) return FALSE;\n"
2458 "if (value_selection != single_value.union_selection) return FALSE;\n"
2459 "switch (value_selection) {\n", name, name, selection_type, unbound_value);
2460 for (i = 0; i < sdef->nElements; i++) {
2461 src = mputprintf(src, "case %s_%s:\n"
2462 "return single_value.field_%s->match(other_value.%s%s(), legacy);\n",
2463 selection_prefix, sdef->elements[i].name, sdef->elements[i].name,
2464 at_field, sdef->elements[i].name);
2465 }
2466 src = mputprintf(src, "default:\n"
2467 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
2468 "matching a template of union type %s.\");\n"
2469 "}\n"
2470 "}\n"
2471 "case VALUE_LIST:\n"
2472 "case COMPLEMENTED_LIST:\n"
2473 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2474 "list_count++)\n"
2475 "if (value_list.list_value[list_count].match(other_value, legacy)) "
2476 "return template_selection == VALUE_LIST;\n"
2477 "return template_selection == COMPLEMENTED_LIST;\n"
2478 "default:\n"
2479 "TTCN_error (\"Matching an uninitialized template of union type %s.\");\n"
2480 "}\n"
2481 "return FALSE;\n"
2482 "}\n\n", dispname, dispname);
2483
2484 /* isvalue */
2485 def = mputstr(def, "boolean is_value() const;");
2486 src = mputprintf(src, "boolean %s_template::is_value() const\n"
2487 "{\n"
2488 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) return false;\n"
2489 "switch (single_value.union_selection) {\n"
2490 , name);
2491 for (i = 0; i < sdef->nElements; i++) {
2492 src = mputprintf(src, "case %s_%s:\n"
2493 "return single_value.field_%s->is_value();\n", selection_prefix,
2494 sdef->elements[i].name, sdef->elements[i].name);
2495 }
2496 src = mputprintf(src, "default:\n"
2497 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
2498 "performing is_value operation on a template of union type %s.\");\n"
2499 "}\n"
2500 "}\n\n", dispname);
2501
2502 /* valueof member function */
2503 def = mputprintf(def, "%s valueof() const;\n", name);
2504 src = mputprintf(src, "%s %s_template::valueof() const\n"
2505 "{\n"
2506 "if (template_selection != SPECIFIC_VALUE || is_ifpresent)\n"
2507 "TTCN_error(\"Performing valueof or send operation on a non-specific "
2508 "template of union type %s.\");\n"
2509 "%s ret_val;\n"
2510 "switch (single_value.union_selection) {\n", name, name, dispname, name);
2511 for (i = 0; i < sdef->nElements; i++) {
2512 src = mputprintf(src, "case %s_%s:\n"
2513 "ret_val.%s%s() = single_value.field_%s->valueof();\n"
2514 "break;\n", selection_prefix, sdef->elements[i].name,
2515 at_field, sdef->elements[i].name, sdef->elements[i].name);
2516 }
2517 src = mputprintf(src, "default:\n"
2518 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
2519 "performing valueof operation on a template of union type %s.\");\n"
2520 "}\n"
2521 "%s"
2522 "return ret_val;\n"
2523 "}\n\n", dispname,
2524 use_runtime_2 ? "ret_val.set_err_descr(err_descr);\n" : "");
2525
2526 /* list_item(int) function */
2527 def = mputprintf(def, "%s_template& list_item(unsigned int list_index) "
2528 "const;\n", name);
2529 src = mputprintf(src,
2530 "%s_template& %s_template::list_item(unsigned int list_index) const\n"
2531 "{\n"
2532 "if (template_selection != VALUE_LIST && "
2533 "template_selection != COMPLEMENTED_LIST) TTCN_error(\"Internal error: "
2534 "Accessing a list element of a non-list template of union type %s.\");\n"
2535 "if (list_index >= value_list.n_values) "
2536 "TTCN_error(\"Internal error: Index overflow in a value list template "
2537 "of union type %s.\");\n"
2538 "return value_list.list_value[list_index];\n"
2539 "}\n", name, name, dispname, dispname);
2540
2541 /* void set_type(template_sel, int) function */
2542 def = mputstr(def, "void set_type(template_sel template_type, "
2543 "unsigned int list_length);\n");
2544 src = mputprintf(src,
2545 "void %s_template::set_type(template_sel template_type, "
2546 "unsigned int list_length)\n"
2547 "{\n"
2548 "if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST) "
2549 "TTCN_error (\"Internal error: Setting an invalid list for a template "
2550 "of union type %s.\");\n"
2551 "clean_up();\n"
2552 "set_selection(template_type);\n"
2553 "value_list.n_values = list_length;\n"
2554 "value_list.list_value = new %s_template[list_length];\n"
2555 "}\n\n", name, dispname, name);
2556
2557 /* field access functions */
2558 for (i = 0; i < sdef->nElements; i++) {
2559 def = mputprintf(def, "%s_template& %s%s();\n", sdef->elements[i].type,
2560 at_field, sdef->elements[i].name);
2561 src = mputprintf(src, "%s_template& %s_template::%s%s()\n"
2562 "{\n"
2563 "if (template_selection != SPECIFIC_VALUE || "
2564 "single_value.union_selection != %s_%s) {\n"
2565 "template_sel old_selection = template_selection;\n"
2566 "clean_up();\n"
2567 "if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) "
2568 "single_value.field_%s = new %s_template(ANY_VALUE);\n"
2569 "else single_value.field_%s = new %s_template;\n"
2570 "single_value.union_selection = %s_%s;\n"
2571 "set_selection(SPECIFIC_VALUE);\n"
2572 "}\n"
2573 "return *single_value.field_%s;\n"
2574 "}\n\n", sdef->elements[i].type, name, at_field, sdef->elements[i].name,
2575 selection_prefix, sdef->elements[i].name, sdef->elements[i].name,
2576 sdef->elements[i].type, sdef->elements[i].name, sdef->elements[i].type,
2577 selection_prefix, sdef->elements[i].name, sdef->elements[i].name);
2578
2579 def = mputprintf(def, "const %s_template& %s%s() const;\n",
2580 sdef->elements[i].type, at_field, sdef->elements[i].name);
2581 src = mputprintf(src, "const %s_template& %s_template::%s%s() const\n"
2582 "{\n"
2583 "if (template_selection != SPECIFIC_VALUE) TTCN_error(\"Accessing field "
2584 "%s in a non-specific template of union type %s.\");\n"
2585 "if (single_value.union_selection != %s_%s) "
2586 "TTCN_error(\"Accessing non-selected field %s in a template of union "
2587 "type %s.\");\n"
2588 "return *single_value.field_%s;\n"
2589 "}\n\n", sdef->elements[i].type, name, at_field, sdef->elements[i].name,
2590 sdef->elements[i].dispname, dispname, selection_prefix,
2591 sdef->elements[i].name, sdef->elements[i].dispname, dispname,
2592 sdef->elements[i].name);
2593 }
2594
2595 /* ischosen function */
2596 def = mputprintf(def, "boolean ischosen(%s checked_selection) const;\n",
2597 selection_type);
2598 src = mputprintf(src, "boolean %s_template::ischosen(%s checked_selection) "
2599 "const\n"
2600 "{\n"
2601 "if (checked_selection == %s) TTCN_error(\"Internal error: Performing "
2602 "ischosen() operation on an invalid field of union type %s.\");\n"
2603 "switch (template_selection) {\n"
2604 "case SPECIFIC_VALUE:\n"
2605 "if (single_value.union_selection == %s) TTCN_error(\"Internal error: "
2606 "Invalid selector in a specific value when performing ischosen() "
2607 "operation on a template of union type %s.\");\n"
2608 "return single_value.union_selection == checked_selection;\n"
2609 "case VALUE_LIST:\n"
2610 "{\n"
2611 "if (value_list.n_values < 1)\n"
2612 "TTCN_error(\"Internal error: Performing ischosen() operation on a "
2613 "template of union type %s containing an empty list.\");\n"
2614 "boolean ret_val = "
2615 "value_list.list_value[0].ischosen(checked_selection);\n"
2616 "boolean all_same = TRUE;\n"
2617 "for (unsigned int list_count = 1; list_count < value_list.n_values; "
2618 "list_count++) {\n"
2619 "if (value_list.list_value[list_count].ischosen(checked_selection) != "
2620 "ret_val) {\n"
2621 "all_same = FALSE;\n"
2622 "break;\n"
2623 "}\n"
2624 "}\n"
2625 "if (all_same) return ret_val;\n"
2626 "}\n"
2627 "case ANY_VALUE:\n"
2628 "case ANY_OR_OMIT:\n"
2629 "case OMIT_VALUE:\n"
2630 "case COMPLEMENTED_LIST:\n"
2631 "TTCN_error(\"Performing ischosen() operation on a template of union type "
2632 "%s, which does not determine unambiguously the chosen field of the "
2633 "matching values.\");\n"
2634 "default:\n"
2635 "TTCN_error(\"Performing ischosen() operation on an uninitialized "
2636 "template of union type %s\");\n"
2637 "}\n"
2638 "return FALSE;\n"
2639 "}\n\n", name, selection_type, unbound_value, dispname, unbound_value,
2640 dispname, dispname, dispname, dispname);
2641
2642 if (use_runtime_2) {
2643 def = mputstr(def,
2644 "void set_err_descr(Erroneous_descriptor_t* p_err_descr) { err_descr=p_err_descr; }\n");
2645 /** virtual stuff */
2646 def = mputstr(def,
2647 "void valueofv(Base_Type* value) const;\n"
2648 "void set_value(template_sel other_value);\n"
2649 "void copy_value(const Base_Type* other_value);\n"
2650 "Base_Template* clone() const;\n"
2651 "const TTCN_Typedescriptor_t* get_descriptor() const;\n"
2652 "boolean matchv(const Base_Type* other_value, boolean legacy) const;\n"
2653 "void log_matchv(const Base_Type* match_value, boolean legacy) const;\n");
2654 src = mputprintf(src,
2655 "void %s_template::valueofv(Base_Type* value) const "
2656 "{ *(static_cast<%s*>(value)) = valueof(); }\n"
2657 "void %s_template::set_value(template_sel other_value) "
2658 "{ *this = other_value; }\n"
2659 "void %s_template::copy_value(const Base_Type* other_value) "
2660 "{ *this = *(static_cast<const %s*>(other_value)); }\n"
2661 "Base_Template* %s_template::clone() const "
2662 "{ return new %s_template(*this); }\n"
2663 "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const "
2664 "{ return &%s_descr_; }\n"
2665 "boolean %s_template::matchv(const Base_Type* other_value, "
2666 "boolean legacy) const "
2667 "{ return match(*(static_cast<const %s*>(other_value)), legacy); }\n"
2668 "void %s_template::log_matchv(const Base_Type* match_value, "
2669 "boolean legacy) const "
2670 " { log_match(*(static_cast<const %s*>(match_value)), legacy); }\n",
2671 name, name,
2672 name,
2673 name, name,
2674 name, name,
2675 name, name,
2676 name, name,
2677 name, name);
2678 }
2679
2680 /* log function */
2681 def = mputstr(def, "void log() const;\n");
2682 src = mputprintf(src,"void %s_template::log() const\n"
2683 "{\n"
2684 "switch (template_selection) {\n"
2685 "case SPECIFIC_VALUE:\n"
2686 "switch (single_value.union_selection) {\n", name);
2687 for (i = 0; i < sdef->nElements; i++) {
2688 src = mputprintf(src, "case %s_%s:\n"
2689 "TTCN_Logger::log_event_str(\"{ %s := \");\n"
2690 "single_value.field_%s->log();\n"
2691 "TTCN_Logger::log_event_str(\" }\");\n"
2692 "break;\n", selection_prefix, sdef->elements[i].name,
2693 sdef->elements[i].dispname, sdef->elements[i].name);
2694 }
2695 src = mputstr(src, "default:\n"
2696 "TTCN_Logger::log_event_str(\"<invalid selector>\");\n"
2697 "}\n"
2698 "break;\n"
2699 "case COMPLEMENTED_LIST:\n"
2700 "TTCN_Logger::log_event_str(\"complement \");\n"
2701 "case VALUE_LIST:\n"
2702 "TTCN_Logger::log_char('(');\n"
2703 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2704 "list_count++) {\n"
2705 "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n"
2706 "value_list.list_value[list_count].log();\n"
2707 "}\n"
2708 "TTCN_Logger::log_char(')');\n"
2709 "break;\n"
2710 "default:\n"
2711 "log_generic();\n"
2712 "}\n"
2713 "log_ifpresent();\n");
2714 if (use_runtime_2) {
2715 src = mputstr(src, "if (err_descr) err_descr->log();\n");
2716 }
2717 src = mputstr(src, "}\n\n");
2718
2719 /* log_match function */
2720 def = mputprintf(def, "void log_match(const %s& match_value, "
2721 "boolean legacy = FALSE) const;\n", name);
2722 src = mputprintf(src,
2723 "void %s_template::log_match(const %s& match_value, boolean legacy) const\n"
2724 "{\n"
2725 "if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity() "
2726 "&& match(match_value, legacy)){\n"
2727 "TTCN_Logger::print_logmatch_buffer();\n"
2728 "TTCN_Logger::log_event_str(\" matched\");\n"
2729 "return;\n"
2730 "}\n"
2731 "if (template_selection == SPECIFIC_VALUE && "
2732 "single_value.union_selection == match_value.get_selection()) {\n"
2733 "switch (single_value.union_selection) {\n", name, name);
2734 for (i = 0; i < sdef->nElements; i++) {
2735 src = mputprintf(src, "case %s_%s:\n"
2736 "if(TTCN_Logger::VERBOSITY_COMPACT == TTCN_Logger::get_matching_verbosity()){\n"
2737 "TTCN_Logger::log_logmatch_info(\".%s\");\n"
2738 "single_value.field_%s->log_match(match_value.%s%s(), legacy);\n"
2739 "} else {\n"
2740 "TTCN_Logger::log_event_str(\"{ %s := \");\n"
2741 "single_value.field_%s->log_match(match_value.%s%s(), legacy);\n"
2742 "TTCN_Logger::log_event_str(\" }\");\n"
2743 "}\n"
2744 "break;\n", selection_prefix, sdef->elements[i].name,
2745 sdef->elements[i].dispname,
2746 sdef->elements[i].name, at_field, sdef->elements[i].name,
2747 sdef->elements[i].dispname, sdef->elements[i].name,
2748 at_field, sdef->elements[i].name);
2749 }
2750 src = mputstr(src, "default:\n"
2751 "TTCN_Logger::print_logmatch_buffer();\n"
2752 "TTCN_Logger::log_event_str(\"<invalid selector>\");\n"
2753 "}\n"
2754 "} else {\n"
2755 "TTCN_Logger::print_logmatch_buffer();\n"
2756 "match_value.log();\n"
2757 "TTCN_Logger::log_event_str(\" with \");\n"
2758 "log();\n"
2759 "if (match(match_value, legacy)) TTCN_Logger::log_event_str(\" matched\");\n"
2760 "else TTCN_Logger::log_event_str(\" unmatched\");\n"
2761 "}\n"
2762 "}\n\n");
2763
2764 /* encode_text function */
2765 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
2766 src = mputprintf(src,
2767 "void %s_template::encode_text(Text_Buf& text_buf) const\n"
2768 "{\n"
2769 "encode_text_base(text_buf);\n"
2770 "switch (template_selection) {\n"
2771 "case SPECIFIC_VALUE:\n"
2772 "text_buf.push_int(single_value.union_selection);\n"
2773 "switch (single_value.union_selection) {\n", name);
2774 for (i = 0; i < sdef->nElements; i++) {
2775 src = mputprintf(src, "case %s_%s:\n"
2776 "single_value.field_%s->encode_text(text_buf);\n"
2777 "break;\n", selection_prefix, sdef->elements[i].name,
2778 sdef->elements[i].name);
2779 }
2780 src = mputprintf(src, "default:\n"
2781 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
2782 "encoding a template of union type %s.\");\n"
2783 "}\n"
2784 "case OMIT_VALUE:\n"
2785 "case ANY_VALUE:\n"
2786 "case ANY_OR_OMIT:\n"
2787 "break;\n"
2788 "case VALUE_LIST:\n"
2789 "case COMPLEMENTED_LIST:\n"
2790 "text_buf.push_int(value_list.n_values);\n"
2791 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2792 "list_count++)\n"
2793 "value_list.list_value[list_count].encode_text(text_buf);\n"
2794 "break;\n"
2795 "default:\n"
2796 "TTCN_error(\"Text encoder: Encoding an uninitialized template of type "
2797 "%s.\");\n"
2798 "}\n"
2799 "}\n\n", dispname, dispname);
2800
2801 /* decode_text function */
2802 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
2803 src = mputprintf(src, "void %s_template::decode_text(Text_Buf& text_buf)\n"
2804 "{\n"
2805 "clean_up();\n"
2806 "decode_text_base(text_buf);\n"
2807 "switch (template_selection) {\n"
2808 "case SPECIFIC_VALUE:\n"
2809 "{\n"
2810 "single_value.union_selection = %s;\n"
2811 "%s new_selection = (%s)text_buf.pull_int().get_val();\n"
2812 "switch (new_selection) {\n", name, unbound_value, selection_type,
2813 selection_type);
2814 for (i = 0; i < sdef->nElements; i++) {
2815 src = mputprintf(src, "case %s_%s:\n"
2816 "single_value.field_%s = new %s_template;\n"
2817 "single_value.field_%s->decode_text(text_buf);\n"
2818 "break;\n", selection_prefix, sdef->elements[i].name,
2819 sdef->elements[i].name, sdef->elements[i].type, sdef->elements[i].name);
2820 }
2821 src = mputprintf(src, "default:\n"
2822 "TTCN_error(\"Text decoder: Unrecognized union selector was received for "
2823 "a template of type %s.\");\n"
2824 "}\n"
2825 "single_value.union_selection = new_selection;\n"
2826 "}\n"
2827 "case OMIT_VALUE:\n"
2828 "case ANY_VALUE:\n"
2829 "case ANY_OR_OMIT:\n"
2830 "break;\n"
2831 "case VALUE_LIST:\n"
2832 "case COMPLEMENTED_LIST:\n"
2833 "value_list.n_values = text_buf.pull_int().get_val();\n"
2834 "value_list.list_value = new %s_template[value_list.n_values];\n"
2835 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
2836 "list_count++)\n"
2837 "value_list.list_value[list_count].decode_text(text_buf);\n"
2838 "break;\n"
2839 "default:\n"
2840 "TTCN_error(\"Text decoder: Unrecognized selector was received in a "
2841 "template of type %s.\");\n"
2842 "}\n"
2843 "}\n\n", dispname, name, dispname);
2844
2845 /* TTCN-3 ispresent() function */
2846 def = mputstr(def, "boolean is_present(boolean legacy = FALSE) const;\n");
2847 src = mputprintf(src,
2848 "boolean %s_template::is_present(boolean legacy) const\n"
2849 "{\n"
2850 "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n"
2851 "return !match_omit(legacy);\n"
2852 "}\n\n", name);
2853
2854 /* match_omit() */
2855 def = mputstr(def, "boolean match_omit(boolean legacy = FALSE) const;\n");
2856 src = mputprintf(src,
2857 "boolean %s_template::match_omit(boolean legacy) const\n"
2858 "{\n"
2859 "if (is_ifpresent) return TRUE;\n"
2860 "switch (template_selection) {\n"
2861 "case OMIT_VALUE:\n"
2862 "case ANY_OR_OMIT:\n"
2863 "return TRUE;\n"
2864 "case VALUE_LIST:\n"
2865 "case COMPLEMENTED_LIST:\n"
2866 "if (legacy) {\n"
2867 "for (unsigned int v_idx=0; v_idx<value_list.n_values; v_idx++)\n"
2868 "if (value_list.list_value[v_idx].match_omit())\n"
2869 "return template_selection==VALUE_LIST;\n"
2870 "return template_selection==COMPLEMENTED_LIST;\n"
2871 "} // else fall through\n"
2872 "default:\n"
2873 "return FALSE;\n"
2874 "}\n"
2875 "return FALSE;\n"
2876 "}\n\n", name);
2877
2878 /* set_param() */
2879 def = mputstr(def, "void set_param(Module_Param& param);\n");
2880 src = mputprintf(src,
2881 "void %s_template::set_param(Module_Param& param)\n"
2882 "{\n"
2883 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
2884 " param.get_id()->next_name()) {\n"
2885 // Haven't reached the end of the module parameter name
2886 // => the name refers to one of the fields, not to the whole union
2887 " char* param_field = param.get_id()->get_current_name();\n"
2888 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
2889 " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n"
2890 " \" name for union template type `%s'\");\n"
2891 " }\n"
2892 " ", name, dispname);
2893 for (i = 0; i < sdef->nElements; i++) {
2894 src = mputprintf(src,
2895 "if (strcmp(\"%s\", param_field) == 0) {\n"
2896 " %s%s().set_param(param);\n"
2897 " return;\n"
2898 " } else ",
2899 sdef->elements[i].dispname, at_field, sdef->elements[i].name);
2900 }
2901 src = mputprintf(src,
2902 "param.error(\"Field `%%s' not found in union template type `%s'\", param_field);\n"
2903 " }\n"
2904 " param.basic_check(Module_Param::BC_TEMPLATE, \"union template\");\n"
2905 " Module_Param_Ptr m_p = &param;\n"
2906 " if (param.get_type() == Module_Param::MP_Reference) {\n"
2907 " m_p = param.get_referenced_param();\n"
2908 " }\n"
2909 " switch (m_p->get_type()) {\n"
2910 " case Module_Param::MP_Omit:\n"
2911 " *this = OMIT_VALUE;\n"
2912 " break;\n"
2913 " case Module_Param::MP_Any:\n"
2914 " *this = ANY_VALUE;\n"
2915 " break;\n"
2916 " case Module_Param::MP_AnyOrNone:\n"
2917 " *this = ANY_OR_OMIT;\n"
2918 " break;\n"
2919 " case Module_Param::MP_List_Template:\n"
2920 " case Module_Param::MP_ComplementList_Template: {\n"
2921 " %s_template new_temp;\n"
2922 " new_temp.set_type(m_p->get_type()==Module_Param::MP_List_Template ? "
2923 "VALUE_LIST : COMPLEMENTED_LIST, m_p->get_size());\n"
2924 " for (size_t p_i=0; p_i<m_p->get_size(); p_i++) {\n"
2925 " new_temp.list_item(p_i).set_param(*m_p->get_elem(p_i));\n"
2926 " }\n"
2927 " *this = new_temp;\n"
2928 " break; }\n"
2929 " case Module_Param::MP_Value_List:\n"
2930 " if (m_p->get_size()==0) break;\n" /* for backward compatibility */
2931 " param.type_error(\"union template\", \"%s\");\n"
2932 " break;\n"
2933 " case Module_Param::MP_Assignment_List: {\n"
2934 " Module_Param* mp_last = m_p->get_elem(m_p->get_size()-1);\n",
2935 dispname, name, dispname);
2936 for (i = 0; i < sdef->nElements; i++) {
2937 src = mputprintf(src,
2938 " if (!strcmp(mp_last->get_id()->get_name(), \"%s\")) {\n"
2939 " %s%s().set_param(*mp_last);\n"
2940 " break;\n"
2941 " }\n", sdef->elements[i].dispname, at_field, sdef->elements[i].name);
2942 }
2943 src = mputprintf(src,
2944 " mp_last->error(\"Field %%s does not exist in type %s.\", mp_last->get_id()->get_name());\n"
2945 " } break;\n"
2946 " default:\n"
2947 " param.type_error(\"union template\", \"%s\");\n"
2948 " }\n"
2949 " is_ifpresent = param.get_ifpresent() || m_p->get_ifpresent();\n"
2950 "}\n\n", dispname, dispname);
2951
2952 /* get_param() */
2953 def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
2954 src = mputprintf(src,
2955 "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n"
2956 "{\n"
2957 " if (param_name.next_name()) {\n"
2958 // Haven't reached the end of the module parameter name
2959 // => the name refers to one of the fields, not to the whole union
2960 " char* param_field = param_name.get_current_name();\n"
2961 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
2962 " TTCN_error(\"Unexpected array index in module parameter reference, \"\n"
2963 " \"expected a valid field name for union template type `%s'\");\n"
2964 " }\n"
2965 " ", name, dispname);
2966 for (i = 0; i < sdef->nElements; i++) {
2967 src = mputprintf(src,
2968 "if (strcmp(\"%s\", param_field) == 0) {\n"
2969 " return %s%s().get_param(param_name);\n"
2970 " } else ",
2971 sdef->elements[i].dispname, at_field, sdef->elements[i].name);
2972 }
2973 src = mputprintf(src,
2974 "TTCN_error(\"Field `%%s' not found in union type `%s'\", param_field);\n"
2975 " }\n"
2976 " Module_Param* m_p = NULL;\n"
2977 " switch (template_selection) {\n"
2978 " case UNINITIALIZED_TEMPLATE:\n"
2979 " m_p = new Module_Param_Unbound();\n"
2980 " break;\n"
2981 " case OMIT_VALUE:\n"
2982 " m_p = new Module_Param_Omit();\n"
2983 " break;\n"
2984 " case ANY_VALUE:\n"
2985 " m_p = new Module_Param_Any();\n"
2986 " break;\n"
2987 " case ANY_OR_OMIT:\n"
2988 " m_p = new Module_Param_AnyOrNone();\n"
2989 " break;\n"
2990 " case SPECIFIC_VALUE: {\n"
2991 " Module_Param* mp_field = NULL;\n"
2992 " switch(single_value.union_selection) {\n"
2993 , name);
2994 for (i = 0; i < sdef->nElements; ++i) {
2995 src = mputprintf(src,
2996 " case %s_%s:\n"
2997 " mp_field = single_value.field_%s->get_param(param_name);\n"
2998 " mp_field->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n"
2999 " break;\n"
3000 , selection_prefix, sdef->elements[i].name
3001 , sdef->elements[i].name, sdef->elements[i].dispname);
3002 }
3003 src = mputstr(src,
3004 " default:\n"
3005 " break;\n"
3006 " }\n"
3007 " m_p = new Module_Param_Assignment_List();\n"
3008 " m_p->add_elem(mp_field);\n"
3009 " break; }\n"
3010 " case VALUE_LIST:\n"
3011 " case COMPLEMENTED_LIST: {\n"
3012 " if (template_selection == VALUE_LIST) {\n"
3013 " m_p = new Module_Param_List_Template();\n"
3014 " }\n"
3015 " else {\n"
3016 " m_p = new Module_Param_ComplementList_Template();\n"
3017 " }\n"
3018 " for (size_t i_i = 0; i_i < value_list.n_values; ++i_i) {\n"
3019 " m_p->add_elem(value_list.list_value[i_i].get_param(param_name));\n"
3020 " }\n"
3021 " break; }\n"
3022 " default:\n"
3023 " break;\n"
3024 " }\n"
3025 " if (is_ifpresent) {\n"
3026 " m_p->set_ifpresent();\n"
3027 " }\n"
3028 " return m_p;\n"
3029 "}\n\n");
3030
3031 /* check template restriction */
3032 def = mputstr(def, "void check_restriction(template_res t_res, "
3033 "const char* t_name=NULL, boolean legacy = FALSE) const;\n");
3034 src = mputprintf(src,
3035 "void %s_template::check_restriction("
3036 "template_res t_res, const char* t_name, boolean legacy) const\n"
3037 "{\n"
3038 "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
3039 "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
3040 "case TR_OMIT:\n"
3041 "if (template_selection==OMIT_VALUE) return;\n"
3042 "case TR_VALUE:\n"
3043 "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n"
3044 "switch (single_value.union_selection) {\n"
3045 , name);
3046 for (i = 0; i < sdef->nElements; i++) {
3047 src = mputprintf(src, "case %s_%s:\n"
3048 "single_value.field_%s->check_restriction("
3049 "t_res, t_name ? t_name : \"%s\");\n"
3050 "return;\n",
3051 selection_prefix, sdef->elements[i].name,
3052 sdef->elements[i].name, dispname);
3053 }
3054 src = mputprintf(src, "default:\n"
3055 "TTCN_error(\"Internal error: Invalid selector in a specific value when "
3056 "performing check_restriction operation on a template of union type %s.\");\n"
3057 "}\n"
3058 "case TR_PRESENT:\n"
3059 "if (!match_omit(legacy)) return;\n"
3060 "break;\n"
3061 "default:\n"
3062 "return;\n"
3063 "}\n"
3064 "TTCN_error(\"Restriction `%%s' on template of type %%s violated.\", "
3065 "get_res_name(t_res), t_name ? t_name : \"%s\");\n"
3066 "}\n\n", dispname, dispname);
3067
3068 def = mputstr(def, "};\n\n");
3069
3070 output->header.class_defs = mputstr(output->header.class_defs, def);
3071 Free(def);
3072
3073 output->source.methods = mputstr(output->source.methods, src);
3074 Free(src);
3075
3076 Free(selection_type);
3077 Free(unbound_value);
3078 Free(selection_prefix);
3079 }
This page took 0.172005 seconds and 5 git commands to generate.