67b7e96e5c86b8dafd2fb8c781aff85d82e58b83
[deliverable/titan.core.git] / compiler2 / record.c
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 Ericsson Telecom AB
3 // All rights reserved. This program and the accompanying materials
4 // are made available under the terms of the Eclipse Public License v1.0
5 // which accompanies this distribution, and is available at
6 // http://www.eclipse.org/legal/epl-v10.html
7 ///////////////////////////////////////////////////////////////////////////////
8 #include <string.h>
9 #include "datatypes.h"
10 #include "../common/memory.h"
11 #include "record.h"
12 #include "encdec.h"
13
14 #include "main.hh"
15 #include "error.h"
16 #include "ttcn3/compiler.h"
17
18 static void defEmptyRecordClass(const struct_def *sdef,
19 output_struct *output);
20
21 static void defEmptyRecordTemplate(const char *name, const char *dispname,
22 output_struct *output);
23
24 /** this is common code for both empty and non-empty cases, called from
25 * both functions for template generation */
26 static void defCommonRecordTemplate(const char *name,
27 char **def, char **src);
28
29 /** code generation for original runtime */
30 static void defRecordClass1(const struct_def *sdef, output_struct *output);
31 static void defRecordTemplate1(const struct_def *sdef, output_struct *output);
32 /** code generation for alternative runtime (TITAN_RUNTIME_2) */
33 static void defRecordClass2(const struct_def *sdef, output_struct *output);
34 static void defRecordTemplate2(const struct_def *sdef, output_struct *output);
35
36 void defRecordClass(const struct_def *sdef, output_struct *output)
37 {
38 if (use_runtime_2) defRecordClass2(sdef, output);
39 else defRecordClass1(sdef, output);
40 }
41
42 void defRecordTemplate(const struct_def *sdef, output_struct *output)
43 {
44 if (use_runtime_2) defRecordTemplate2(sdef, output);
45 else defRecordTemplate1(sdef, output);
46 }
47
48 struct raw_option_struct {
49 boolean lengthto; /* indicates whether this field contains a length */
50 int lengthof; /* how many length indicators this field counted in */
51 int *lengthoffield; /* the list of length indicator field indices */
52 boolean pointerto;
53 int pointerof;
54 boolean ptrbase;
55 int extbitgroup;
56 int tag_type;
57 boolean delayed_decode; /* indicates whether the field has to be decoded
58 out of order (later) */
59 int nof_dependent_fields; /* list of fields that are to be decoded */
60 int *dependent_fields; /* after this field */
61 };
62
63 static char *genRawFieldDecodeLimit(char *src, const struct_def *sdef,
64 int i, const struct raw_option_struct *raw_options);
65
66 static char *genRawDecodeRecordField(char *src, const struct_def *sdef,
67 int i, const struct raw_option_struct *raw_options, boolean delayed_decode,
68 int *prev_ext_group);
69
70 static void set_raw_options(const struct_def *sdef,
71 struct raw_option_struct *raw_options, boolean* haslengthto,
72 boolean* haspointer, boolean* hascrosstag, boolean* has_ext_bit);
73
74 static char *generate_raw_coding(char *src,
75 const struct_def *sdef, struct raw_option_struct *raw_options,
76 boolean haspointer, boolean hascrosstag, boolean has_ext_bit);
77 static char *generate_raw_coding_negtest(char *src,
78 const struct_def *sdef, struct raw_option_struct *raw_options);
79
80 void set_raw_options(const struct_def *sdef,
81 struct raw_option_struct *raw_options, boolean *haslengthto,
82 boolean *haspointer, boolean *hascrosstag, boolean *has_ext_bit)
83 {
84 int i;
85 for (i = 0; i < sdef->nElements; i++) {
86 raw_options[i].lengthto = FALSE;
87 raw_options[i].lengthof = 0;
88 raw_options[i].lengthoffield = NULL;
89 raw_options[i].pointerto = FALSE;
90 raw_options[i].pointerof = 0;
91 raw_options[i].ptrbase = FALSE;
92 raw_options[i].extbitgroup = 0;
93 raw_options[i].tag_type = 0;
94 raw_options[i].delayed_decode = FALSE;
95 raw_options[i].nof_dependent_fields = 0;
96 raw_options[i].dependent_fields = NULL;
97 }
98 *haslengthto = FALSE;
99 *haspointer = FALSE;
100 *hascrosstag = FALSE;
101 *has_ext_bit = sdef->hasRaw && sdef->raw.extension_bit!=XDEFNO &&
102 sdef->raw.extension_bit!=XDEFDEFAULT;
103 for(i=0;i<sdef->nElements;i++){
104 if(sdef->elements[i].hasRaw &&
105 sdef->elements[i].raw.crosstaglist.nElements){
106 *hascrosstag = TRUE;
107 break;
108 }
109 }
110 if(sdef->hasRaw){ /* fill tag_type. 0-No tag, >0 index of the tag + 1 */
111 for(i=0;i<sdef->raw.taglist.nElements;i++){
112 raw_options[sdef->raw.taglist.list[i].fieldnum].tag_type= i+1;
113 }
114 for(i=0;i<sdef->raw.ext_bit_goup_num;i++){
115 int k;
116 for(k=sdef->raw.ext_bit_groups[i].from;
117 k<=sdef->raw.ext_bit_groups[i].to;k++)
118 raw_options[k].extbitgroup=i+1;
119 }
120 }
121 for(i=0;i<sdef->nElements;i++){
122 if (sdef->elements[i].hasRaw && sdef->elements[i].raw.lengthto_num > 0) {
123 int j;
124 *haslengthto = TRUE;
125 raw_options[i].lengthto = TRUE;
126 for(j = 0; j < sdef->elements[i].raw.lengthto_num; j++) {
127 int field_index = sdef->elements[i].raw.lengthto[j];
128 raw_options[field_index].lengthoffield = (int*)
129 Realloc(raw_options[field_index].lengthoffield,
130 (raw_options[field_index].lengthof + 1) * sizeof(int));
131 raw_options[field_index].lengthoffield[
132 raw_options[field_index].lengthof] = i;
133 raw_options[field_index].lengthof++;
134 }
135 }
136 if(sdef->elements[i].hasRaw && sdef->elements[i].raw.pointerto!=-1){
137 raw_options[i].pointerto = TRUE;
138 raw_options[sdef->elements[i].raw.pointerto].pointerof=i+1;
139 *haspointer = TRUE;
140 raw_options[sdef->elements[i].raw.pointerbase].ptrbase = TRUE;
141 }
142 }
143 if (sdef->kind == RECORD && *hascrosstag) {
144 /* looking for fields that require delayed decoding because of
145 forward references in CROSSTAG */
146 for (i = 0; i < sdef->nElements; i++) {
147 int j;
148 /* we are looking for a field index that is greater than i */
149 size_t max_index = i;
150 if (!sdef->elements[i].hasRaw) continue;
151 for (j = 0; j < sdef->elements[i].raw.crosstaglist.nElements; j++) {
152 int k;
153 rawAST_coding_taglist *crosstag =
154 sdef->elements[i].raw.crosstaglist.list + j;
155 for (k = 0; k < crosstag->nElements; k++) {
156 rawAST_coding_field_list *keyid = crosstag->fields + k;
157 if (keyid->nElements >= 1) {
158 int field_index = keyid->fields[0].nthfield;
159 if (field_index > max_index) max_index = field_index;
160 }
161 }
162 }
163 if (max_index > i) {
164 raw_options[i].delayed_decode = TRUE;
165 raw_options[max_index].nof_dependent_fields++;
166 raw_options[max_index].dependent_fields = (int*)
167 Realloc(raw_options[max_index].dependent_fields,
168 raw_options[max_index].nof_dependent_fields *
169 sizeof(*raw_options[max_index].dependent_fields));
170 raw_options[max_index].dependent_fields[
171 raw_options[max_index].nof_dependent_fields - 1] = i;
172 }
173 }
174 }
175 }
176
177 char* generate_raw_coding(char* src,
178 const struct_def *sdef, struct raw_option_struct *raw_options,
179 boolean haspointer, boolean hascrosstag, boolean has_ext_bit)
180 {
181 int i;
182 const char *name = sdef->name;
183
184 if (sdef->kind == SET) { /* set decoder start */
185 size_t mand_num = 0;
186 for (i = 0; i < sdef->nElements; i++) {
187 if (!sdef->elements[i].isOptional) mand_num++;
188 }
189 src = mputprintf(src, "int %s::RAW_decode(const TTCN_Typedescriptor_t& "
190 "p_td, TTCN_Buffer& p_buf, int limit, raw_order_t top_bit_ord, "
191 "boolean, int, boolean)\n"
192 "{\n"
193 "bound_flag = TRUE;\n"
194 "int prepaddlength = p_buf.increase_pos_padd(p_td.raw->prepadding);\n"
195 "limit -= prepaddlength;\n"
196 "int decoded_length = 0;\n"
197 "int field_map[%lu];\n"
198 "memset(field_map, 0, sizeof(field_map));\n",
199 name, (unsigned long) sdef->nElements);
200 if (mand_num > 0)
201 src = mputstr(src, "size_t nof_mand_fields = 0;\n");
202 for (i = 0; i < sdef->nElements; i++) {
203 if (sdef->elements[i].isOptional)
204 src = mputprintf(src, "field_%s = OMIT_VALUE;\n",
205 sdef->elements[i].name);
206 }
207 src = mputstr(src,
208 "raw_order_t local_top_order;\n"
209 "if (p_td.raw->top_bit_order == TOP_BIT_INHERITED) "
210 "local_top_order = top_bit_ord;\n"
211 "else if (p_td.raw->top_bit_order == TOP_BIT_RIGHT) "
212 "local_top_order = ORDER_MSB;\n"
213 "else local_top_order = ORDER_LSB;\n"
214 "while (limit > 0) {\n"
215 "size_t fl_start_pos = p_buf.get_pos_bit();\n"
216 );
217 for (i = 0; i < sdef->nElements; i++) { /* decoding fields with tag */
218 if (raw_options[i].tag_type &&
219 sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements > 0) {
220 rawAST_coding_taglist* cur_choice =
221 sdef->raw.taglist.list + raw_options[i].tag_type - 1;
222 size_t j;
223 boolean has_fixed = FALSE, has_variable = FALSE, flag_needed = FALSE;
224 for (j = 0; j < cur_choice->nElements; j++) {
225 if (cur_choice->fields[j].start_pos >= 0) {
226 if (has_fixed || has_variable) flag_needed = TRUE;
227 has_fixed = TRUE;
228 } else {
229 if (has_fixed) flag_needed = TRUE;
230 has_variable = TRUE;
231 }
232 if (has_fixed && has_variable) break;
233 }
234 src = mputprintf(src, "if (field_map[%lu] == 0) {\n",
235 (unsigned long) i);
236 if (flag_needed)
237 src = mputstr(src, "boolean already_failed = FALSE;\n");
238 if (has_fixed) {
239 /* first check the fields we can precode
240 * try to decode those key variables whose position we know
241 * this way we might be able to step over bad values faster
242 */
243 boolean first_fixed = TRUE;
244 src = mputstr(src, "raw_order_t temporal_top_order;\n"
245 "int temporal_decoded_length;\n");
246 for (j = 0; j < cur_choice->nElements; j++) {
247 size_t k;
248 rawAST_coding_field_list *cur_field_list = cur_choice->fields + j;
249 if (cur_field_list->start_pos < 0) continue;
250 if (!first_fixed) src = mputstr(src, "if (!already_failed) {\n");
251 for (k = cur_field_list->nElements - 1; k > 0; k--) {
252 src = mputprintf(src, "if (%s_descr_.raw->top_bit_order == "
253 "TOP_BIT_RIGHT) temporal_top_order = ORDER_MSB;\n"
254 "else if (%s_descr_.raw->top_bit_order == TOP_BIT_LEFT) "
255 "temporal_top_order = ORDER_LSB;\n"
256 "else ", cur_field_list->fields[k - 1].typedescr,
257 cur_field_list->fields[k - 1].typedescr);
258 }
259 src = mputprintf(src, "temporal_top_order = top_bit_ord;\n"
260 "%s temporal_%lu;\n"
261 "p_buf.set_pos_bit(fl_start_pos + %d);\n"
262 "temporal_decoded_length = temporal_%lu.RAW_decode(%s_descr_, "
263 "p_buf, limit, temporal_top_order, TRUE);\n"
264 "p_buf.set_pos_bit(fl_start_pos);\n"
265 "if (temporal_decoded_length > 0 && temporal_%lu == %s) {\n"
266 "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, "
267 "p_buf, limit, local_top_order, TRUE);\n"
268 "if (decoded_field_length %s 0 && (",
269 cur_field_list->fields[cur_field_list->nElements - 1].type,
270 (unsigned long) j, cur_field_list->start_pos, (unsigned long) j,
271 cur_field_list->fields[cur_field_list->nElements - 1].typedescr,
272 (unsigned long) j, cur_field_list->value,
273 sdef->elements[i].name,
274 sdef->elements[i].isOptional ? "()" : "",
275 sdef->elements[i].typedescrname,
276 sdef->elements[i].isOptional ? ">" : ">=");
277 src = genRawFieldChecker(src, cur_choice, TRUE);
278 src = mputstr(src, ")) {\n"
279 "decoded_length += decoded_field_length;\n"
280 "limit -= decoded_field_length;\n");
281 if (!sdef->elements[i].isOptional)
282 src = mputstr(src, "nof_mand_fields++;\n");
283 src = mputprintf(src, "field_map[%lu] = 1;\n"
284 "continue;\n"
285 "} else {\n"
286 "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i);
287 if (sdef->elements[i].isOptional)
288 src = mputprintf(src, "field_%s = OMIT_VALUE;\n",
289 sdef->elements[i].name);
290 if (flag_needed) src = mputstr(src, "already_failed = TRUE;\n");
291 src = mputstr(src, "}\n"
292 "}\n");
293 if (first_fixed) first_fixed = FALSE;
294 else src = mputstr(src, "}\n");
295 }
296 }
297 if (has_variable) {
298 /* if there is one tag key whose position we don't know
299 * and we couldn't decide yet if element can be decoded or not
300 * than we have to decode it.
301 */
302 if (flag_needed) src = mputstr(src, "if (!already_failed) {\n");
303 src = mputprintf(src, "int decoded_field_length = "
304 "field_%s%s.RAW_decode(%s_descr_, p_buf, limit, "
305 "local_top_order, TRUE);\n"
306 "if (decoded_field_length %s 0 && (",
307 sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "",
308 sdef->elements[i].typedescrname,
309 sdef->elements[i].isOptional ? ">" : ">=");
310 src = genRawFieldChecker(src, cur_choice, TRUE);
311 src = mputstr(src, ")) {\n"
312 "decoded_length += decoded_field_length;\n"
313 "limit -= decoded_field_length;\n");
314 if (!sdef->elements[i].isOptional)
315 src = mputstr(src, "nof_mand_fields++;\n");
316 src = mputprintf(src, "field_map[%lu] = 1;\n"
317 "continue;\n"
318 "} else {\n"
319 "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i);
320 if (sdef->elements[i].isOptional)
321 src = mputprintf(src, "field_%s = OMIT_VALUE;\n",
322 sdef->elements[i].name);
323 src = mputstr(src, "}\n");
324 if (flag_needed) src = mputstr(src, "}\n");
325 }
326 src = mputstr(src, "}\n");
327 }
328 }
329 for (i = 0; i < sdef->nElements; i++) {
330 /* decoding fields without TAG */
331 if (!raw_options[i].tag_type) {
332 boolean repeatable;
333 if (sdef->elements[i].of_type && sdef->elements[i].hasRaw &&
334 sdef->elements[i].raw.repeatable == XDEFYES) repeatable = TRUE;
335 else {
336 repeatable = FALSE;
337 src = mputprintf(src, "if (field_map[%lu] == 0) ",
338 (unsigned long) i);
339 }
340 src = mputprintf(src, "{\n"
341 "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, "
342 "p_buf, limit, local_top_order, TRUE",
343 sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "",
344 sdef->elements[i].typedescrname);
345 if (repeatable)
346 src = mputprintf(src, ", -1, field_map[%lu] == 0",
347 (unsigned long) i);
348 src = mputprintf(src, ");\n"
349 "if (decoded_field_length %s 0) {\n"
350 "decoded_length += decoded_field_length;\n"
351 "limit -= decoded_field_length;\n",
352 sdef->elements[i].isOptional ? ">" : ">=");
353 if (repeatable) {
354 if (!sdef->elements[i].isOptional) src = mputprintf(src,
355 "if (field_map[%lu] == 0) nof_mand_fields++;\n",
356 (unsigned long) i);
357 src = mputprintf(src, "field_map[%lu]++;\n", (unsigned long) i);
358 } else {
359 if (!sdef->elements[i].isOptional)
360 src = mputstr(src, "nof_mand_fields++;\n");
361 src = mputprintf(src, "field_map[%lu] = 1;\n", (unsigned long) i);
362 }
363 src = mputstr(src, "continue;\n"
364 "} else {\n"
365 "p_buf.set_pos_bit(fl_start_pos);\n");
366 if (sdef->elements[i].isOptional) {
367 if (repeatable)
368 src = mputprintf(src, "if (field_map[%lu] == 0) ",
369 (unsigned long) i);
370 src = mputprintf(src, "field_%s = OMIT_VALUE;\n",
371 sdef->elements[i].name);
372 }
373 src = mputstr(src, "}\n"
374 "}\n");
375 }
376 }
377 for (i = 0; i < sdef->nElements; i++){
378 /* decoding fields with tag OTHERWISE */
379 if (raw_options[i].tag_type &&
380 sdef->raw.taglist.list[raw_options[i].tag_type-1].nElements == 0) {
381 src = mputprintf(src, "if (field_map[%lu] == 0) {\n"
382 "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, "
383 "p_buf, limit, local_top_order, TRUE);\n"
384 "if (decoded_field_length %s 0) {\n"
385 "decoded_length += decoded_field_length;\n"
386 "limit -= decoded_field_length;\n", (unsigned long) i,
387 sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "",
388 sdef->elements[i].typedescrname,
389 sdef->elements[i].isOptional ? ">" : ">=");
390 if (!sdef->elements[i].isOptional)
391 src = mputstr(src, "nof_mand_fields++;\n");
392 src = mputprintf(src, "field_map[%lu] = 1;\n"
393 "continue;\n"
394 "} else {\n"
395 "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i);
396 if (sdef->elements[i].isOptional)
397 src = mputprintf(src, "field_%s = OMIT_VALUE;\n",
398 sdef->elements[i].name);
399 src = mputstr(src, "}\n"
400 "}\n");
401 }
402 }
403 src = mputstr(src, "break;\n" /* no field decoded successfully, quit */
404 "}\n");
405 if (mand_num > 0) src = mputprintf(src,
406 "if (nof_mand_fields != %lu) return limit ? -1 : -TTCN_EncDec::ET_INCOMPL_MSG;\n",
407 (unsigned long) mand_num);
408 /* If not all required fields were decoded and there are no bits left,
409 * that means that the last field was decoded successfully but used up
410 * the buffer. Signal "incomplete". If there were bits left, that means that
411 * no field could be decoded from them; signal an error.
412 */
413 src = mputstr(src, "return decoded_length + prepaddlength + "
414 "p_buf.increase_pos_padd(p_td.raw->padding);\n"
415 "}\n\n");
416 } else {
417 /* set decoder end, record decoder start */
418 int prev_ext_group = 0;
419 src = mputprintf(src,
420 "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, "
421 "TTCN_Buffer& p_buf, int limit, raw_order_t top_bit_ord, boolean no_err, "
422 "int, boolean)\n"
423 "{ (void)no_err;\n"
424 " bound_flag = TRUE;\n"
425 " int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n"
426 " limit-=prepaddlength;\n"
427 " size_t last_decoded_pos = p_buf.get_pos_bit();\n"
428 " int decoded_length = 0;\n"
429 " int decoded_field_length = 0;\n"
430 " raw_order_t local_top_order;\n"
431 , name);
432 if (hascrosstag) {
433 src = mputstr(src, " int selected_field = -1;\n");
434 }
435 if (sdef->raw.ext_bit_goup_num) {
436 src=mputstr(src, " int group_limit = 0;\n");
437 }
438 src=mputstr(src,
439 " if(p_td.raw->top_bit_order==TOP_BIT_INHERITED)"
440 "local_top_order=top_bit_ord;\n"
441 " else if(p_td.raw->top_bit_order==TOP_BIT_RIGHT)local_top_order"
442 "=ORDER_MSB;\n"
443 " else local_top_order=ORDER_LSB;\n"
444 );
445 if(has_ext_bit){
446 src=mputstr(src,
447 " {\n"
448 " cbyte* data=p_buf.get_read_data();\n"
449 " int count=1;\n"
450 " unsigned mask = 1 << (local_top_order==ORDER_LSB ? 0 : 7);\n"
451 " if(p_td.raw->extension_bit==EXT_BIT_YES){\n"
452 " while((data[count-1] & mask)==0 && count*8<(int)limit) count++;\n"
453 " }\n"
454 " else{\n"
455 " while((data[count-1] & mask)!=0 && count*8<(int)limit) count++;\n"
456 " }\n"
457 " if(limit) limit=count*8;\n"
458 " }\n"
459 );
460 }
461 if(haspointer)
462 src=mputstr(src,
463 " int end_of_available_data=last_decoded_pos+limit;\n");
464 for(i=0;i<sdef->nElements;i++){
465 if(raw_options[i].pointerof)
466 src=mputprintf(src,
467 " int start_of_field%lu=-1;\n"
468 ,(unsigned long) i
469 );
470 if(raw_options[i].ptrbase)
471 src=mputprintf(src,
472 " int start_pos_of_field%lu=-1;\n"
473 ,(unsigned long) i
474 );
475 if(raw_options[i].lengthto)
476 src=mputprintf(src,
477 " int value_of_length_field%lu = 0;\n"
478 ,(unsigned long) i
479 );
480 }
481 for(i=0;i<sdef->nElements;i++){ /* decoding fields */
482 if (raw_options[i].delayed_decode) {
483 int j;
484 /* checking whether there are enough bits in the buffer to decode
485 the field */
486 src = mputstr(src, " if (");
487 src = genRawFieldDecodeLimit(src, sdef, i, raw_options);
488 src = mputprintf(src, " < %d) return -TTCN_EncDec::ET_LEN_ERR;\n",
489 sdef->elements[i].raw.length);
490 /* skipping over the field that has to be decoded later because of
491 forward referencing in CROSSTAG */
492 src = mputprintf(src,
493 " size_t start_of_field%lu = p_buf.get_pos_bit();\n"
494 " p_buf.set_pos_bit(start_of_field%lu + %d);\n"
495 " decoded_length += %d;\n"
496 " last_decoded_pos += %d;\n"
497 " limit -= %d;\n",
498 (unsigned long) i, (unsigned long) i, sdef->elements[i].raw.length,
499 sdef->elements[i].raw.length,
500 sdef->elements[i].raw.length, sdef->elements[i].raw.length);
501 for (j = 0; j < raw_options[i].lengthof; j++) {
502 src = mputprintf(src,
503 " value_of_length_field%d -= %d;\n",
504 raw_options[i].lengthoffield[j], sdef->elements[i].raw.length);
505 }
506 } else {
507 src = genRawDecodeRecordField(src, sdef, i, raw_options, FALSE,
508 &prev_ext_group);
509 if (raw_options[i].nof_dependent_fields > 0) {
510 int j;
511 for (j = 0; j < raw_options[i].nof_dependent_fields; j++) {
512 int dependent_field_index = raw_options[i].dependent_fields[j];
513 /* seek to the beginning of the dependent field */
514 src = mputprintf(src,
515 " p_buf.set_pos_bit(start_of_field%d);\n",
516 dependent_field_index);
517 /* decode the dependent field */
518 src = genRawDecodeRecordField(src, sdef, dependent_field_index,
519 raw_options, TRUE, &prev_ext_group);
520 }
521 if (i < sdef->nElements - 1) {
522 /* seek back if there are more regular fields to decode */
523 src = mputstr(src,
524 " p_buf.set_pos_bit(last_decoded_pos);\n");
525 }
526 }
527 }
528 } /* decoding fields*/
529
530 if(sdef->hasRaw && sdef->raw.presence.nElements > 0)
531 {
532 src = mputstr(src, " if (");
533 src = genRawFieldChecker(src, &sdef->raw.presence, FALSE);
534 src = mputstr(src, ") return -1;\n");
535 }
536
537 src=mputstr(src,
538 " p_buf.set_pos_bit(last_decoded_pos);\n"
539 " return decoded_length+prepaddlength+"
540 "p_buf.increase_pos_padd(p_td.raw->padding);\n}\n\n");
541 } /* record decoder end */
542
543 src = mputprintf(src, /* encoder */
544 "int %s::RAW_encode(const TTCN_Typedescriptor_t&%s, "
545 "RAW_enc_tree& myleaf) const {\n", name,
546 use_runtime_2 ? " p_td" : "");
547 if (use_runtime_2) {
548 src = mputstr(src, " if (err_descr) return RAW_encode_negtest(err_descr, p_td, myleaf);\n");
549 }
550 src = mputprintf(src,
551 " if (!is_bound()) TTCN_EncDec_ErrorContext::error"
552 "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
553 " int encoded_length = 0;\n"
554 " myleaf.isleaf = false;\n"
555 " myleaf.body.node.num_of_nodes = %lu;\n"
556 " myleaf.body.node.nodes = init_nodes_of_enc_tree(%lu);\n",
557 (unsigned long)sdef->nElements, (unsigned long)sdef->nElements);
558 /* init nodes */
559 for (i = 0; i < sdef->nElements; i++) {
560 if (sdef->elements[i].isOptional) {
561 src = mputprintf(src,
562 " if (field_%s.ispresent()) {\n", sdef->elements[i].name);
563 }
564 src = mputprintf(src,
565 " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(true, &myleaf, "
566 "&(myleaf.curr_pos), %lu, %s_descr_.raw);\n",
567 (unsigned long)i, (unsigned long)i, sdef->elements[i].typedescrname);
568 if (sdef->elements[i].isOptional) {
569 src = mputprintf(src,
570 " }\n"
571 " else myleaf.body.node.nodes[%lu] = NULL;\n", (unsigned long)i);
572 }
573 }
574 for (i = 0; i < sdef->raw.ext_bit_goup_num; i++) {
575 if (sdef->raw.ext_bit_groups[i].ext_bit != XDEFNO) {
576 src = mputprintf(src,
577 " {\n"
578 " int node_idx = %d;\n"
579 " while (node_idx <= %d && myleaf.body.node.nodes[node_idx] == NULL) node_idx++;\n"
580 " if (myleaf.body.node.nodes[node_idx]) {\n"
581 " myleaf.body.node.nodes[node_idx]->ext_bit_handling = 1;\n"
582 " myleaf.body.node.nodes[node_idx]->ext_bit = %s;\n }\n"
583 " node_idx = %d;\n"
584 " while (node_idx >= %d && myleaf.body.node.nodes[node_idx] == NULL) node_idx--;\n"
585 " if (myleaf.body.node.nodes[node_idx]) myleaf.body.node.nodes[node_idx]"
586 "->ext_bit_handling += 2;\n"
587 " }\n",
588 sdef->raw.ext_bit_groups[i].from,
589 sdef->raw.ext_bit_groups[i].to,
590 sdef->raw.ext_bit_groups[i].ext_bit == XDEFYES ? "EXT_BIT_YES" : "EXT_BIT_REVERSE",
591 sdef->raw.ext_bit_groups[i].to,
592 sdef->raw.ext_bit_groups[i].from);
593 }
594 }
595 for (i = 0; i < sdef->nElements; i++) {
596 /* encoding fields */
597 if (sdef->elements[i].isOptional) {
598 src = mputprintf(src,
599 " if (field_%s.ispresent()) {\n", sdef->elements[i].name);
600 }
601 if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex == NULL
602 && sdef->elements[i].raw.union_member_num == 0) {
603 /* encoding of lenghto fields */
604 int a;
605 src = mputprintf(src,
606 " encoded_length += %d;\n"
607 " myleaf.body.node.nodes[%lu]->calc = CALC_LENGTH;\n"
608 " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n"
609 " myleaf.body.node.nodes[%lu]->calcof.lengthto.num_of_fields = %d;\n"
610 " myleaf.body.node.nodes[%lu]->calcof.lengthto.unit = %d;\n"
611 " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields = "
612 "init_lengthto_fields_list(%d);\n"
613 " myleaf.body.node.nodes[%lu]->length = %d;\n",
614 sdef->elements[i].raw.fieldlength, (unsigned long)i,
615 (unsigned long)i, sdef->elements[i].typedescrname,
616 (unsigned long)i, sdef->elements[i].raw.lengthto_num,
617 (unsigned long)i, sdef->elements[i].raw.unit,
618 (unsigned long)i, sdef->elements[i].raw.lengthto_num,
619 (unsigned long)i, sdef->elements[i].raw.fieldlength);
620 for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) {
621 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
622 src = mputprintf(src,
623 " if (field_%s.ispresent()) {\n",
624 sdef->elements[sdef->elements[i].raw.lengthto[a]].name);
625 }
626 src = mputprintf(src,
627 " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].level = "
628 "myleaf.body.node.nodes[%d]->curr_pos.level;\n"
629 " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].pos = "
630 "myleaf.body.node.nodes[%d]->curr_pos.pos;\n",
631 (unsigned long)i, a, sdef->elements[i].raw.lengthto[a],
632 (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]);
633 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
634 src = mputprintf(src,
635 " } else {\n"
636 " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].level = 0;\n"
637 " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].pos = 0;\n"
638 " }\n", (unsigned long)i, a, (unsigned long)i, a);
639 }
640 }
641 } else if (raw_options[i].pointerto) {
642 /* encoding of pointerto fields */
643 if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) {
644 src = mputprintf(src,
645 " if (field_%s.ispresent()) {\n",
646 sdef->elements[sdef->elements[i].raw.pointerto].name);
647 }
648 src = mputprintf(src,
649 " encoded_length += %d;\n"
650 " myleaf.body.node.nodes[%lu]->calc = CALC_POINTER;\n"
651 " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n"
652 " myleaf.body.node.nodes[%lu]->calcof.pointerto.unit = %d;\n"
653 " myleaf.body.node.nodes[%lu]->calcof.pointerto.ptr_offset = %d;\n"
654 " myleaf.body.node.nodes[%lu]->calcof.pointerto.ptr_base = %d;\n"
655 " myleaf.body.node.nodes[%lu]->calcof.pointerto.target.level = "
656 "myleaf.body.node.nodes[%d]->curr_pos.level;\n"
657 " myleaf.body.node.nodes[%lu]->calcof.pointerto.target.pos = "
658 "myleaf.body.node.nodes[%d]->curr_pos.pos;\n"
659 " myleaf.body.node.nodes[%lu]->length = %d;\n",
660 sdef->elements[i].raw.fieldlength,(unsigned long)i,
661 (unsigned long)i, sdef->elements[i].typedescrname,
662 (unsigned long)i, sdef->elements[i].raw.unit,
663 (unsigned long)i, sdef->elements[i].raw.ptroffset,
664 (unsigned long)i, sdef->elements[i].raw.pointerbase,
665 (unsigned long)i, sdef->elements[i].raw.pointerto,
666 (unsigned long)i, sdef->elements[i].raw.pointerto,
667 (unsigned long)i, sdef->elements[i].raw.fieldlength);
668 if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) {
669 src = mputprintf(src,
670 " } else {\n"
671 " INTEGER atm;\n"
672 " atm = 0;\n"
673 " encoded_length += atm.RAW_encode(%s_descr_"
674 ", *myleaf.body.node.nodes[%lu]);\n"
675 " }\n",
676 sdef->elements[i].typedescrname, (unsigned long)i);
677 }
678 } else {
679 /* encoding of normal fields */
680 src = mputprintf(src,
681 " encoded_length += field_%s%s.RAW_encode(%s_descr_"
682 ", *myleaf.body.node.nodes[%lu]);\n",
683 sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "",
684 sdef->elements[i].typedescrname, (unsigned long)i);
685 }
686 if (sdef->elements[i].isOptional) {
687 src = mputstr(src, " }\n");
688 }
689 }
690 for (i = 0; i < sdef->nElements; i++) {
691 /* fill presence, tag and crosstag */
692 if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex) {
693 /* encoding of lenghto fields */
694 int a;
695 if (sdef->elements[i].isOptional) {
696 src = mputprintf(src,
697 " if (field_%s.ispresent()) {\n",
698 sdef->elements[i].name);
699 }
700 src = mputprintf(src,
701 " if (myleaf.body.node.nodes[%lu]->body.node.nodes[%d]) {\n"
702 " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->"
703 "calc = CALC_LENGTH;\n"
704 " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->"
705 "coding_descr = &%s_descr_;\n"
706 " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->"
707 "calcof.lengthto.num_of_fields = %d;\n"
708 " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->"
709 "calcof.lengthto.unit = %d;\n"
710 " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->"
711 "calcof.lengthto.fields = "
712 "init_lengthto_fields_list(%d);\n",
713 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
714 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
715 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
716 sdef->elements[i].raw.lengthindex->typedescr,
717 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
718 sdef->elements[i].raw.lengthto_num,
719 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
720 sdef->elements[i].raw.unit,
721 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
722 sdef->elements[i].raw.lengthto_num);
723 for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) {
724 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
725 src = mputprintf(src,
726 " if (field_%s.ispresent()) {\n",
727 sdef->elements[sdef->elements[i].raw.lengthto[a]].name);
728 }
729 src = mputprintf(src,
730 " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]"
731 "->calcof.lengthto.fields[%d].level = "
732 "myleaf.body.node.nodes[%d]->curr_pos.level;\n"
733 " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]"
734 "->calcof.lengthto.fields[%d].pos = "
735 "myleaf.body.node.nodes[%d]->curr_pos.pos;\n",
736 (unsigned long)i,sdef->elements[i].raw.lengthindex->nthfield,
737 a, sdef->elements[i].raw.lengthto[a],
738 (unsigned long)i,sdef->elements[i].raw.lengthindex->nthfield,
739 a, sdef->elements[i].raw.lengthto[a]);
740 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
741 src = mputprintf(src,
742 " } else {\n"
743 " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->"
744 "calcof.lengthto.fields[%d].level = 0;\n"
745 " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->"
746 "calcof.lengthto.fields[%d].pos = 0;\n"
747 " }\n",
748 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a,
749 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a);
750 }
751 }
752 src = mputstr(src, " }\n");
753 if (sdef->elements[i].isOptional) {
754 src = mputstr(src, " }\n");
755 }
756 }
757 if (raw_options[i].lengthto && sdef->elements[i].raw.union_member_num) {
758 /* encoding of lenghto fields */
759 int a;
760 if (sdef->elements[i].isOptional) {
761 src = mputprintf(src,
762 " if (field_%s.ispresent()) ", sdef->elements[i].name);
763 }
764
765 src = mputprintf(src,
766 " {\n"
767 " int sel_field = 0;\n"
768 " while (myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field] == NULL) "
769 "{ sel_field++; }\n"
770 " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->"
771 "calc = CALC_LENGTH;\n"
772 " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->"
773 "calcof.lengthto.num_of_fields = %d;\n"
774 " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->"
775 "calcof.lengthto.unit = %d;\n"
776 " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->"
777 "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n",
778 (unsigned long)i,(unsigned long)i,
779 (unsigned long)i,sdef->elements[i].raw.lengthto_num,
780 (unsigned long)i,sdef->elements[i].raw.unit,
781 (unsigned long)i,sdef->elements[i].raw.lengthto_num);
782 for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) {
783 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
784 src = mputprintf(src,
785 " if (field_%s.ispresent()) {\n",
786 sdef->elements[sdef->elements[i].raw.lengthto[a]].name);
787 }
788 src = mputprintf(src,
789 " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]"
790 "->calcof.lengthto.fields[%d].level = "
791 "myleaf.body.node.nodes[%d]->curr_pos.level;\n"
792 " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]"
793 "->calcof.lengthto.fields[%d].pos = "
794 "myleaf.body.node.nodes[%d]->curr_pos.pos;\n",
795 (unsigned long)i, a, sdef->elements[i].raw.lengthto[a],
796 (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]);
797 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
798 src = mputprintf(src,
799 " }else{\n"
800 " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]"
801 "->calcof.lengthto.fields[%d].level = 0;\n"
802 " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]"
803 "->calcof.lengthto.fields[%d].pos = 0;\n"
804 " }\n",
805 (unsigned long)i, a,
806 (unsigned long)i, a);
807 }
808 }
809 src = mputstr(src,
810 " }\n");
811 }
812 if (raw_options[i].tag_type && sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements) {
813 /* tag */
814 rawAST_coding_taglist *cur_choice =
815 sdef->raw.taglist.list + raw_options[i].tag_type - 1;
816 src = mputstr(src, " if (");
817 if (sdef->elements[i].isOptional) {
818 src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name);
819 }
820 src = genRawFieldChecker(src, cur_choice, FALSE);
821 if (sdef->elements[i].isOptional) src = mputstr(src, ")");
822 src = mputstr(src,") {\n");
823 src = genRawTagChecker(src, cur_choice);
824 src=mputstr(src," }\n");
825 }
826 if (sdef->elements[i].hasRaw && sdef->elements[i].raw.presence.nElements) {
827 /* presence */
828 src = mputstr(src, " if (");
829 if (sdef->elements[i].isOptional) {
830 src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name);
831 }
832 src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, FALSE);
833 if (sdef->elements[i].isOptional) src = mputstr(src, ")");
834 src = mputstr(src, ") {\n");
835 src = genRawTagChecker(src, &sdef->elements[i].raw.presence);
836 src = mputstr(src," }\n");
837 }
838 if (sdef->elements[i].hasRaw &&
839 sdef->elements[i].raw.crosstaglist.nElements) {
840 /* crosstag */
841 int a;
842 if (sdef->elements[i].isOptional) {
843 src = mputprintf(src,
844 " if (field_%s.ispresent()) {\n",
845 sdef->elements[i].name);
846 }
847 src = mputprintf(src,
848 " switch (field_%s%s.get_selection()) {\n",
849 sdef->elements[i].name,sdef->elements[i].isOptional ? "()" : "");
850 for (a = 0; a < sdef->elements[i].raw.crosstaglist.nElements; a++) {
851 rawAST_coding_taglist *cur_choice =
852 sdef->elements[i].raw.crosstaglist.list + a;
853 if (cur_choice->nElements > 0) {
854 src = mputprintf(src, " case %s%s%s:\n"
855 " if (", sdef->elements[i].type,
856 "::ALT_", cur_choice->fieldName);
857 src = genRawFieldChecker(src, cur_choice, FALSE);
858 src = mputstr(src, ") {\n");
859 if (!strcmp(cur_choice->fields[0].value, "OMIT_VALUE")) {
860 if (cur_choice->fields[0].nElements != 1)
861 NOTSUPP("omit value with multiple fields in CROSSTAG");
862 /* eliminating the corresponding encoded leaf, which will have
863 the same effect as if the referred field had been omit */
864 src = mputprintf(src,
865 " encoded_length -= myleaf.body.node.nodes[%d]->length;\n"
866 " delete myleaf.body.node.nodes[%d];\n"
867 " myleaf.body.node.nodes[%d] = NULL;\n",
868 cur_choice->fields[0].fields[0].nthfield,
869 cur_choice->fields[0].fields[0].nthfield,
870 cur_choice->fields[0].fields[0].nthfield);
871 } else {
872 int ll;
873 src = mputprintf(src,
874 " RAW_enc_tr_pos pr_pos;\n"
875 " pr_pos.level = myleaf.curr_pos.level + %d;\n"
876 " int new_pos[] = { ",
877 cur_choice->fields[0].nElements);
878 for (ll = 0; ll < cur_choice->fields[0].nElements; ll++) {
879 if (ll > 0) src = mputstr(src, ", ");
880 src = mputprintf(src, "%d",
881 cur_choice->fields[0].fields[ll].nthfield);
882 }
883 src = mputprintf(src, " };\n"
884 " pr_pos.pos = init_new_tree_pos(myleaf.curr_pos, %d, "
885 "new_pos);\n",
886 cur_choice->fields[0].nElements);
887 if (cur_choice->fields[0].value[0] == ' ') {
888 /* the value is a string literal (the encoder can be called
889 on that object directly */
890 src = mputprintf(src,
891 " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n"
892 " if (temp_leaf != NULL)\n"
893 " %s.RAW_encode(%s_descr_,*temp_leaf);\n"
894 " else\n"
895 " TTCN_EncDec_ErrorContext::error\n"
896 " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged,"
897 " but omitted value.\");\n",
898 cur_choice->fields[0].value,
899 cur_choice->fields[0].fields[
900 cur_choice->fields[0].nElements - 1].typedescr);
901 } else {
902 /* a temporary object needs to be created for encoding */
903 src = mputprintf(src,
904 " %s new_val(%s);\n"
905 " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n"
906 " if (temp_leaf != NULL)\n"
907 " new_val.RAW_encode(%s_descr_,*temp_leaf);\n"
908 " else\n"
909 " TTCN_EncDec_ErrorContext::error\n"
910 " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged,"
911 " but omitted value.\");\n",
912 cur_choice->fields[0].fields[
913 cur_choice->fields[0].nElements - 1].type,
914 cur_choice->fields[0].value,
915 cur_choice->fields[0].fields[
916 cur_choice->fields[0].nElements - 1].typedescr);
917 }
918 src = mputstr(src, " free_tree_pos(pr_pos.pos);\n");
919 }
920 src = mputstr(src, " }\n"
921 " break;\n");
922 }
923 }
924 src = mputstr(src, " default:;\n"
925 " }\n");
926 if (sdef->elements[i].isOptional) src = mputstr(src, " }\n");
927 }
928 }
929 /* presence */
930 if (sdef->hasRaw && sdef->raw.presence.nElements > 0) {
931 src = mputstr(src, " if (");
932 src = genRawFieldChecker(src, &sdef->raw.presence, FALSE);
933 src = mputstr(src,") {\n");
934 src = genRawTagChecker(src, &sdef->raw.presence);
935 src = mputstr(src," }\n");
936 }
937 src = mputstr(src, " return myleaf.length = encoded_length;\n}\n\n");
938
939 if (use_runtime_2)
940 src = generate_raw_coding_negtest(src, sdef, raw_options);
941 return src;
942 }
943
944 char *generate_raw_coding_negtest(char *src, const struct_def *sdef,
945 struct raw_option_struct *raw_options)
946 {
947 int i;
948 const char *name = sdef->name;
949 src = mputprintf(src,
950 /* Count the nodes and discover the new node order only. No node creation
951 or encoding. */
952 "int %s::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr, "
953 "const TTCN_Typedescriptor_t& /*p_td*/, RAW_enc_tree& myleaf) const\n"
954 "{\n"
955 " if (!is_bound()) TTCN_EncDec_ErrorContext::error"
956 "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
957 " int idx_map[%lu];\n"
958 " for (int idx_map_idx = 0; idx_map_idx < %lu; ++idx_map_idx)\n"
959 " idx_map[idx_map_idx] = -1;\n"
960 " (void)idx_map;\n"
961 " int encoded_length = 0;\n"
962 " int num_fields = get_count();\n"
963 " myleaf.isleaf = false;\n"
964 " myleaf.body.node.num_of_nodes = 0;\n"
965 " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n"
966 " if ((p_err_descr->omit_before != -1) &&\n"
967 " (field_idx < p_err_descr->omit_before))\n"
968 " continue;\n"
969 " const Erroneous_values_t *err_vals = p_err_descr->get_field_err_values(field_idx);\n"
970 " const Erroneous_descriptor_t *emb_descr = p_err_descr->get_field_emb_descr(field_idx);\n"
971 " if (err_vals && err_vals->before)\n"
972 " ++myleaf.body.node.num_of_nodes;\n"
973 " if (err_vals && err_vals->value) {\n"
974 " if (err_vals->value->errval) {\n"
975 " // Field is modified, but it's still there. Otherwise, it's\n"
976 " // initialized to `-1'.\n"
977 " idx_map[field_idx] = -2;\n"
978 " ++myleaf.body.node.num_of_nodes;\n"
979 " }\n"
980 " } else {\n"
981 " if (emb_descr) idx_map[field_idx] = -2;\n"
982 " else idx_map[field_idx] = myleaf.body.node.num_of_nodes;\n"
983 " ++myleaf.body.node.num_of_nodes;\n"
984 " }\n"
985 " if (err_vals && err_vals->after)\n"
986 " ++myleaf.body.node.num_of_nodes;\n"
987 " if ((p_err_descr->omit_after != -1) &&\n"
988 " (field_idx >= p_err_descr->omit_after))\n"
989 " break;\n"
990 " }\n",
991 name, (unsigned long)sdef->nElements, (unsigned long)sdef->nElements);
992 /* Init nodes. */
993 src = mputprintf(src,
994 " myleaf.body.node.nodes =\n"
995 " init_nodes_of_enc_tree(myleaf.body.node.num_of_nodes);\n"
996 " TTCN_EncDec_ErrorContext e_c;\n"
997 " int node_pos = 0;\n"
998 " int next_optional_idx = 0;\n"
999 " const int *my_optional_indexes = get_optional_indexes();\n"
1000 " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n"
1001 " boolean is_optional_field = my_optional_indexes &&\n"
1002 " (my_optional_indexes[next_optional_idx] == field_idx);\n"
1003 " if ((p_err_descr->omit_before != -1) &&\n"
1004 " (field_idx < p_err_descr->omit_before)) {\n"
1005 " if (is_optional_field) ++next_optional_idx;\n"
1006 " continue;\n"
1007 " }\n"
1008 " const Erroneous_values_t *err_vals =\n"
1009 " p_err_descr->get_field_err_values(field_idx);\n"
1010 " if (err_vals && err_vals->before) {\n"
1011 " if (err_vals->before->errval == NULL)\n"
1012 " TTCN_error(\"internal error: erroneous before value missing\");\n"
1013 " if (err_vals->before->raw) {\n"
1014 " myleaf.body.node.nodes[node_pos] =\n"
1015 " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n"
1016 " node_pos, err_vals->before->errval"
1017 "->get_descriptor()->raw);\n"
1018 " } else {\n"
1019 " if (err_vals->before->type_descr == NULL)\n"
1020 " TTCN_error(\"internal error: erroneous before typedescriptor "
1021 "missing\");\n"
1022 " myleaf.body.node.nodes[node_pos] =\n"
1023 " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n"
1024 " node_pos, err_vals->before->type_descr->raw);\n"
1025 " }\n"
1026 " ++node_pos;\n"
1027 " }\n"
1028 " if (err_vals && err_vals->value) {\n"
1029 " if (err_vals->value->errval) {\n"
1030 " e_c.set_msg(\"'%%s'(erroneous value): \", fld_name(field_idx));\n"
1031 " if (err_vals->value->raw) {\n"
1032 " myleaf.body.node.nodes[node_pos] =\n"
1033 " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n"
1034 " node_pos, err_vals->value->errval"
1035 "->get_descriptor()->raw);\n"
1036 " } else {\n"
1037 " if (err_vals->value->type_descr == NULL)\n"
1038 " TTCN_error(\"internal error: erroneous value typedescriptor "
1039 "missing\");\n"
1040 " myleaf.body.node.nodes[node_pos] =\n"
1041 " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n"
1042 " node_pos, err_vals->value->type_descr->raw);\n"
1043 " }\n"
1044 " ++node_pos;\n"
1045 " }\n"
1046 " } else {\n"
1047 " e_c.set_msg(\"'%%s': \", fld_name(field_idx));\n"
1048 " if (!is_optional_field || get_at(field_idx)->ispresent()) {\n"
1049 " myleaf.body.node.nodes[node_pos] =\n"
1050 " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n"
1051 " node_pos, fld_descr(field_idx)->raw);\n"
1052 " } else {\n"
1053 " // `omitted' field.\n"
1054 " myleaf.body.node.nodes[node_pos] = NULL;\n"
1055 " }\n"
1056 " ++node_pos;\n"
1057 " }\n"
1058 " if (err_vals && err_vals->after) {\n"
1059 " if (err_vals->after->errval == NULL)\n"
1060 " TTCN_error(\"internal error: erroneous before value missing\");\n"
1061 " if (err_vals->after->raw) {\n"
1062 " myleaf.body.node.nodes[node_pos] =\n"
1063 " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n"
1064 " node_pos, err_vals->after->errval"
1065 "->get_descriptor()->raw);\n"
1066 " } else {\n"
1067 " if (err_vals->after->type_descr == NULL)\n"
1068 " TTCN_error(\"internal error: erroneous after typedescriptor "
1069 "missing\");\n"
1070 " myleaf.body.node.nodes[node_pos] =\n"
1071 " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n"
1072 " node_pos, err_vals->after->type_descr->raw);\n"
1073 " }\n"
1074 " ++node_pos;\n"
1075 " }\n"
1076 " if (is_optional_field) ++next_optional_idx;\n"
1077 " if ((p_err_descr->omit_after != -1) &&\n"
1078 " (field_idx >= p_err_descr->omit_after))\n"
1079 " break;\n"
1080 " }\n");
1081 /* Handling of the tricky attributes. A simple integer array will be used
1082 to track changes (field positions) in the record.
1083 int idx_map[n_fields] = {
1084 -1 (= field 0. was omitted),
1085 1 (= field 1. can be found at index 1.),
1086 -2 (= field 2. is still at index 2., but its value has changed) }; */
1087 for (i = 0; i < sdef->raw.ext_bit_goup_num; i++) {
1088 if (sdef->raw.ext_bit_groups[i].ext_bit != XDEFNO) {
1089 src = mputprintf(src,
1090 " {\n"
1091 " bool in_between_modified = false;\n"
1092 " for (int idx_map_idx = %d; idx_map_idx <= %d; ++idx_map_idx)\n"
1093 " if (idx_map[idx_map_idx] < 0) {\n"
1094 " in_between_modified = true;\n"
1095 " break;\n"
1096 " }\n"
1097 " if (idx_map[%d] < 0 || idx_map[%d] < 0 ||\n"
1098 " %d != idx_map[%d] - idx_map[%d] || in_between_modified) {\n"
1099 " e_c.set_msg(\"Field #%d and/or #%d: \");\n"
1100 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1101 " \"Conflicting negative testing attributes, extension bit "
1102 "group #%d will be ignored\");\n"
1103 " } else {\n"
1104 " int node_idx = idx_map[%d];\n"
1105 " while (node_idx <= idx_map[%d] &&\n"
1106 " myleaf.body.node.nodes[node_idx] == NULL)\n"
1107 " node_idx++;\n"
1108 " if (myleaf.body.node.nodes[node_idx]) {\n"
1109 " myleaf.body.node.nodes[node_idx]->ext_bit_handling = 1;\n"
1110 " myleaf.body.node.nodes[node_idx]->ext_bit = %s;\n"
1111 " }\n"
1112 " node_idx = idx_map[%d];\n"
1113 " while (node_idx >= idx_map[%d] &&\n"
1114 " myleaf.body.node.nodes[node_idx] == NULL)\n"
1115 " node_idx--;\n"
1116 " if (myleaf.body.node.nodes[node_idx])\n"
1117 " myleaf.body.node.nodes[node_idx]->ext_bit_handling += 2;\n"
1118 " }\n"
1119 " }\n",
1120 sdef->raw.ext_bit_groups[i].from,
1121 sdef->raw.ext_bit_groups[i].to,
1122 sdef->raw.ext_bit_groups[i].from,
1123 sdef->raw.ext_bit_groups[i].to,
1124 sdef->raw.ext_bit_groups[i].to - sdef->raw.ext_bit_groups[i].from,
1125 sdef->raw.ext_bit_groups[i].to,
1126 sdef->raw.ext_bit_groups[i].from,
1127 sdef->raw.ext_bit_groups[i].from,
1128 sdef->raw.ext_bit_groups[i].to, i,
1129 sdef->raw.ext_bit_groups[i].from,
1130 sdef->raw.ext_bit_groups[i].to,
1131 sdef->raw.ext_bit_groups[i].ext_bit == XDEFYES ? "EXT_BIT_YES" : "EXT_BIT_REVERSE",
1132 sdef->raw.ext_bit_groups[i].to,
1133 sdef->raw.ext_bit_groups[i].from);
1134 }
1135 }
1136 for (i = 0; i < sdef->nElements; i++) {
1137 if (sdef->elements[i].isOptional) {
1138 src = mputprintf(src,
1139 " if (field_%s.ispresent()) {\n",
1140 sdef->elements[i].name);
1141 }
1142 if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex == NULL
1143 && sdef->elements[i].raw.union_member_num == 0) {
1144 /* Encoding of lenghto fields. */
1145 int a;
1146 src = mputprintf(src,
1147 " if (idx_map[%lu] < 0) {\n"
1148 " e_c.set_msg(\"Field '%s': \");\n"
1149 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1150 " \"Conflicting negative testing attributes, LENGTHTO "
1151 "attribute will be ignored\");\n"
1152 " } else {\n"
1153 " bool negtest_confl_lengthto = false;\n",
1154 (unsigned long)i, sdef->elements[i].name);
1155 for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) {
1156 src = mputprintf(src,
1157 " if (idx_map[%lu] < 0) {\n"
1158 " negtest_confl_lengthto = true;\n"
1159 " e_c.set_msg(\"Field '%s': \");\n"
1160 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1161 " \"Conflicting negative testing attributes, LENGTHTO "
1162 "attribute will be ignored\");\n"
1163 " }\n",
1164 (unsigned long)sdef->elements[i].raw.lengthto[a],
1165 sdef->elements[sdef->elements[i].raw.lengthto[a]].name);
1166 }
1167 src = mputprintf(src,
1168 " if (!negtest_confl_lengthto) {\n"
1169 " encoded_length += %d;\n"
1170 " myleaf.body.node.nodes[idx_map[%lu]]->calc = CALC_LENGTH;\n"
1171 " myleaf.body.node.nodes[idx_map[%lu]]->coding_descr = &%s_descr_;\n"
1172 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.num_of_fields = %d;\n"
1173 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.unit = %d;\n"
1174 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields = "
1175 "init_lengthto_fields_list(%d);\n"
1176 " myleaf.body.node.nodes[idx_map[%lu]]->length = %d;\n",
1177 sdef->elements[i].raw.fieldlength, (unsigned long)i,
1178 (unsigned long)i, sdef->elements[i].typedescrname,
1179 (unsigned long)i, sdef->elements[i].raw.lengthto_num,
1180 (unsigned long)i, sdef->elements[i].raw.unit,
1181 (unsigned long)i, sdef->elements[i].raw.lengthto_num,
1182 (unsigned long)i, sdef->elements[i].raw.fieldlength);
1183 for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) {
1184 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
1185 src = mputprintf(src,
1186 " if (field_%s.ispresent()) {\n",
1187 sdef->elements[sdef->elements[i].raw.lengthto[a]].name);
1188 }
1189 src = mputprintf(src,
1190 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields[%lu].level = "
1191 "myleaf.body.node.nodes[idx_map[%lu]]->curr_pos.level;\n"
1192 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields[%lu].pos = "
1193 "myleaf.body.node.nodes[idx_map[%lu]]->curr_pos.pos;\n",
1194 (unsigned long)i, (unsigned long)a,
1195 (unsigned long)sdef->elements[i].raw.lengthto[a],
1196 (unsigned long)i, (unsigned long)a,
1197 (unsigned long)sdef->elements[i].raw.lengthto[a]);
1198 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
1199 src = mputprintf(src,
1200 " } else {\n"
1201 " myleaf.body.node.nodes[idx_map[%lu]]->"
1202 "calcof.lengthto.fields[%lu].level = 0;\n"
1203 " myleaf.body.node.nodes[idx_map[%lu]]->"
1204 "calcof.lengthto.fields[%lu].pos = 0;\n"
1205 " }\n",
1206 (unsigned long)i, (unsigned long)a,
1207 (unsigned long)i, (unsigned long)a);
1208 }
1209 }
1210 /* Closing inner index check. */
1211 src = mputstr(src,
1212 " }\n");
1213 /* Closing outer index check. */
1214 src = mputstr(src,
1215 " }\n");
1216 } else if (raw_options[i].pointerto) {
1217 /* Encoding of pointerto fields. */
1218 if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) {
1219 src = mputprintf(src,
1220 " if (field_%s.ispresent()) {\n",
1221 sdef->elements[sdef->elements[i].raw.pointerto].name);
1222 }
1223 src = mputprintf(src,
1224 " bool in_between_modified_pointerto_%s = false;\n"
1225 " for (int idx_map_idx = %d; idx_map_idx <= %d; ++idx_map_idx) {\n"
1226 " if (idx_map[idx_map_idx] < 0) {\n"
1227 " in_between_modified_pointerto_%s = true;\n"
1228 " break;\n"
1229 " }\n"
1230 " }\n"
1231 " if (idx_map[%lu] < 0 || idx_map[%lu] < 0 ||\n"
1232 " %lu != idx_map[%lu] - idx_map[%lu] || in_between_modified_pointerto_%s) {\n"
1233 " e_c.set_msg(\"Field '%s' and/or '%s': \");\n"
1234 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1235 " \"Conflicting negative testing attributes, POINTERTO "
1236 "attribute will be ignored\");\n"
1237 " } else {\n"
1238 " encoded_length += %d;\n"
1239 " myleaf.body.node.nodes[idx_map[%lu]]->calc = CALC_POINTER;\n"
1240 " myleaf.body.node.nodes[idx_map[%lu]]->coding_descr = &%s_descr_;\n"
1241 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.unit = %d;\n"
1242 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.ptr_offset = %d;\n"
1243 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.ptr_base = %d;\n"
1244 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.target.level = "
1245 "myleaf.body.node.nodes[%d]->curr_pos.level;\n"
1246 " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.target.pos = "
1247 "myleaf.body.node.nodes[%d]->curr_pos.pos;\n"
1248 " myleaf.body.node.nodes[idx_map[%lu]]->length = %d;\n"
1249 " }\n",
1250 sdef->elements[i].name,
1251 i, sdef->elements[i].raw.pointerto,
1252 sdef->elements[i].name, (unsigned long)i,
1253 (unsigned long)sdef->elements[i].raw.pointerto,
1254 (unsigned long)sdef->elements[i].raw.pointerto - (unsigned long)i,
1255 (unsigned long)sdef->elements[i].raw.pointerto, (unsigned long)i,
1256 sdef->elements[i].name, sdef->elements[i].name,
1257 sdef->elements[sdef->elements[i].raw.pointerto].name,
1258 sdef->elements[i].raw.fieldlength, (unsigned long)i,
1259 (unsigned long)i, sdef->elements[i].typedescrname,
1260 (unsigned long)i, sdef->elements[i].raw.unit,
1261 (unsigned long)i, sdef->elements[i].raw.ptroffset,
1262 (unsigned long)i, sdef->elements[i].raw.pointerbase,
1263 (unsigned long)i, sdef->elements[i].raw.pointerto,
1264 (unsigned long)i, sdef->elements[i].raw.pointerto,
1265 (unsigned long)i, sdef->elements[i].raw.fieldlength);
1266 if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) {
1267 src = mputprintf(src,
1268 " } else {\n"
1269 " INTEGER atm;\n"
1270 " atm = 0;\n"
1271 " encoded_length += atm.RAW_encode(%s_descr_, "
1272 "*myleaf.body.node.nodes[idx_map[%lu]]);\n"
1273 " }\n",
1274 sdef->elements[i].typedescrname, (unsigned long)i);
1275 }
1276 } else {
1277 /* Encoding of normal fields with no negative testing. Needed for the
1278 later phase. */
1279 src = mputprintf(src,
1280 " if (idx_map[%lu] >= 0) "
1281 "encoded_length += field_%s%s.RAW_encode(%s_descr_, "
1282 "*myleaf.body.node.nodes[idx_map[%lu]]);\n",
1283 (unsigned long)i, sdef->elements[i].name,
1284 sdef->elements[i].isOptional ? "()" : "",
1285 sdef->elements[i].typedescrname, (unsigned long)i);
1286 }
1287 if (sdef->elements[i].isOptional) {
1288 src = mputstr(src,
1289 " }\n");
1290 }
1291 }
1292 for (i = 0; i < sdef->nElements; i++) {
1293 /* Fill presence, tag and crosstag. */
1294 if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex) {
1295 /* Encoding of lenghto fields with lengthindex. */
1296 int a;
1297 if (sdef->elements[i].isOptional) {
1298 src = mputprintf(src,
1299 " if (field_%s.ispresent()) {\n",
1300 sdef->elements[i].name);
1301 }
1302 src = mputprintf(src,
1303 " if (idx_map[%lu] < 0) {\n"
1304 " e_c.set_msg(\"Field '%s': \");\n"
1305 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1306 " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX "
1307 "attribute will be ignored\");\n"
1308 " } else {\n"
1309 " if (myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]) {\n"
1310 " bool negtest_confl_lengthto = false;\n",
1311 (unsigned long)i, sdef->elements[i].name, (unsigned long)i,
1312 sdef->elements[i].raw.lengthindex->nthfield);
1313 for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) {
1314 src = mputprintf(src,
1315 " if (idx_map[%lu] < 0) {\n"
1316 " negtest_confl_lengthto = true;\n"
1317 " e_c.set_msg(\"Field '%s': \");\n"
1318 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1319 " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX "
1320 "attribute will be ignored\");\n"
1321 " }\n",
1322 (unsigned long)sdef->elements[i].raw.lengthto[a],
1323 sdef->elements[sdef->elements[i].raw.lengthto[a]].name);
1324 }
1325 src = mputprintf(src,
1326 " if (!negtest_confl_lengthto) {\n"
1327 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->"
1328 "calc = CALC_LENGTH;\n"
1329 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->"
1330 "coding_descr = &%s_descr_;\n"
1331 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->"
1332 "calcof.lengthto.num_of_fields = %d;\n"
1333 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->"
1334 "calcof.lengthto.unit = %d;\n"
1335 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->"
1336 "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n",
1337 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
1338 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
1339 sdef->elements[i].raw.lengthindex->typedescr,
1340 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
1341 sdef->elements[i].raw.lengthto_num,
1342 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
1343 sdef->elements[i].raw.unit,
1344 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield,
1345 sdef->elements[i].raw.lengthto_num);
1346 for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) {
1347 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
1348 src = mputprintf(src,
1349 " if (field_%s.ispresent()) {\n",
1350 sdef->elements[sdef->elements[i].raw.lengthto[a]].name);
1351 }
1352 src = mputprintf(src,
1353 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]"
1354 "->calcof.lengthto.fields[%d].level = "
1355 "myleaf.body.node.nodes[idx_map[%d]]->curr_pos.level;\n"
1356 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]"
1357 "->calcof.lengthto.fields[%d].pos = "
1358 "myleaf.body.node.nodes[idx_map[%d]]->curr_pos.pos;\n",
1359 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a,
1360 sdef->elements[i].raw.lengthto[a], (unsigned long)i,
1361 sdef->elements[i].raw.lengthindex->nthfield, a,
1362 sdef->elements[i].raw.lengthto[a]);
1363 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
1364 src = mputprintf(src,
1365 " } else {\n"
1366 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->"
1367 "calcof.lengthto.fields[%d].level = 0;\n"
1368 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->"
1369 "calcof.lengthto.fields[%d].pos = 0;\n"
1370 " }\n",
1371 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a,
1372 (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a);
1373 }
1374 }
1375 /* Closing index check. */
1376 src = mputstr(src,
1377 " }\n");
1378 src = mputstr(src, " }\n }\n");
1379 if (sdef->elements[i].isOptional) {
1380 src = mputstr(src, " }\n");
1381 }
1382 }
1383 if (raw_options[i].lengthto && sdef->elements[i].raw.union_member_num) {
1384 /* Encoding of lenghto fields. */
1385 int a;
1386 if (sdef->elements[i].isOptional) {
1387 src = mputprintf(src,
1388 " if (field_%s.ispresent()) ", sdef->elements[i].name);
1389 }
1390 src = mputprintf(src,
1391 " {\n"
1392 " if (idx_map[%lu] < 0) {\n"
1393 " e_c.set_msg(\"Field '%s': \");\n"
1394 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1395 " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX "
1396 "attribute will be ignored\");\n"
1397 " } else {\n"
1398 " bool negtest_confl_lengthto = false;\n",
1399 (unsigned long)i, sdef->elements[i].name);
1400 for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) {
1401 src = mputprintf(src,
1402 " if (idx_map[%lu] < 0) {\n"
1403 " negtest_confl_lengthto = true;\n"
1404 " e_c.set_msg(\"Field '%s': \");\n"
1405 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1406 " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX "
1407 "attribute will be ignored\");\n"
1408 " }\n",
1409 (unsigned long)sdef->elements[i].raw.lengthto[a],
1410 sdef->elements[sdef->elements[i].raw.lengthto[a]].name);
1411 }
1412 src = mputprintf(src,
1413 " if (!negtest_confl_lengthto) {\n"
1414 " int sel_field = 0;\n"
1415 " while (myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field] == NULL) "
1416 "{ sel_field++; }\n"
1417 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->"
1418 "calc = CALC_LENGTH;\n"
1419 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->"
1420 "calcof.lengthto.num_of_fields = %d;\n"
1421 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->"
1422 "calcof.lengthto.unit = %d;\n"
1423 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->"
1424 "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n",
1425 (unsigned long)i, (unsigned long)i,
1426 (unsigned long)i, sdef->elements[i].raw.lengthto_num,
1427 (unsigned long)i, sdef->elements[i].raw.unit,
1428 (unsigned long)i, sdef->elements[i].raw.lengthto_num);
1429 for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) {
1430 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
1431 src = mputprintf(src,
1432 " if (field_%s.ispresent()) {\n",
1433 sdef->elements[sdef->elements[i].raw.lengthto[a]].name);
1434 }
1435 src = mputprintf(src,
1436 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]"
1437 "->calcof.lengthto.fields[%d].level = "
1438 "myleaf.body.node.nodes[%d]->curr_pos.level;\n"
1439 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]"
1440 "->calcof.lengthto.fields[%d].pos = "
1441 "myleaf.body.node.nodes[%d]->curr_pos.pos;\n",
1442 (unsigned long)i, a, sdef->elements[i].raw.lengthto[a],
1443 (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]);
1444 if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) {
1445 src = mputprintf(src,
1446 " } else {\n"
1447 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]"
1448 "->calcof.lengthto.fields[%d].level = 0;\n"
1449 " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]"
1450 "->calcof.lengthto.fields[%d].pos = 0;\n"
1451 " }\n",
1452 (unsigned long)i, a,
1453 (unsigned long)i, a);
1454 }
1455 }
1456 /* Closing inner index check. */
1457 src = mputstr(src,
1458 " }\n");
1459 /* Closing outer index check. */
1460 src = mputstr(src,
1461 " }\n");
1462 /* Closing ispresent or local block. */
1463 src = mputstr(src,
1464 " }\n");
1465 }
1466 if (raw_options[i].tag_type &&
1467 sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements) {
1468 /* Plain, old tag. */
1469 rawAST_coding_taglist *cur_choice =
1470 sdef->raw.taglist.list + raw_options[i].tag_type - 1;
1471 src = mputprintf(src,
1472 " bool negtest_confl_tag_%s = false;\n"
1473 " if (idx_map[%lu] < 0) {\n"
1474 " negtest_confl_tag_%s = true;\n"
1475 " e_c.set_msg(\"Field '%s': \");\n"
1476 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1477 " \"Conflicting negative testing attributes, TAG attribute will "
1478 "be ignored\");\n"
1479 " }\n",
1480 sdef->elements[i].name, (unsigned long)i, sdef->elements[i].name,
1481 sdef->elements[i].name);
1482 src = mputprintf(src, " if (!negtest_confl_tag_%s && (",
1483 sdef->elements[i].name);
1484 if (sdef->elements[i].isOptional) {
1485 src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name);
1486 }
1487 src = genRawFieldChecker(src, cur_choice, FALSE);
1488 if (sdef->elements[i].isOptional) src = mputstr(src, ")");
1489 src = mputstr(src,")) {\n");
1490 src = genRawTagChecker(src, cur_choice);
1491 src = mputstr(src," }\n");
1492 }
1493 if (sdef->elements[i].hasRaw && sdef->elements[i].raw.presence.nElements) {
1494 /* Presence attribute for fields. */
1495 int taglist_idx, field_idx;
1496 /* The optional field itself. */
1497 src = mputprintf(src,
1498 " bool negtest_confl_presence_%s = false;\n"
1499 " if (idx_map[%lu] < 0) {\n"
1500 " negtest_confl_presence_%s = true;\n"
1501 " e_c.set_msg(\"Field '%s': \");\n"
1502 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1503 " \"Conflicting negative testing attributes, PRESENCE attribute "
1504 "will be ignored\");\n"
1505 " }\n",
1506 sdef->elements[i].name, (unsigned long)i, sdef->elements[i].name,
1507 sdef->elements[i].name);
1508 /* Check the referenced fields. */
1509 for (taglist_idx = 0;
1510 taglist_idx < sdef->elements[i].raw.presence.nElements; ++taglist_idx) {
1511 rawAST_coding_field_list *fields =
1512 sdef->elements[i].raw.presence.fields + taglist_idx;
1513 for (field_idx = 0; field_idx < fields->nElements; ++field_idx) {
1514 /* The top level field is enough. >0 index is for subrefs. */
1515 if (field_idx == 0) {
1516 rawAST_coding_fields *field = fields->fields + field_idx;
1517 src = mputprintf(src,
1518 " if (idx_map[%d] < 0) {\n"
1519 " negtest_confl_presence_%s = true;\n"
1520 " e_c.set_msg(\"Field '%s': \");\n"
1521 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1522 " \"Conflicting negative testing attributes, PRESENCE attribute "
1523 "will be ignored\");\n"
1524 " }\n",
1525 field->nthfield, sdef->elements[i].name, field->nthfieldname);
1526 } else {
1527 /* Subrefs. */
1528 break;
1529 }
1530 }
1531 }
1532 src = mputprintf(src, " if (!negtest_confl_presence_%s && (",
1533 sdef->elements[i].name);
1534 if (sdef->elements[i].isOptional) {
1535 src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name);
1536 }
1537 src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, FALSE);
1538 if (sdef->elements[i].isOptional) src = mputstr(src, ")");
1539 src = mputstr(src, ")) {\n");
1540 src = genRawTagChecker(src, &sdef->elements[i].raw.presence);
1541 src = mputstr(src, " }\n");
1542 }
1543 if (sdef->elements[i].hasRaw &&
1544 sdef->elements[i].raw.crosstaglist.nElements) {
1545 /* crosstag */
1546 int a;
1547 /* The union field itself. */
1548 src = mputprintf(src,
1549 " if (idx_map[%lu] < 0) {\n"
1550 " e_c.set_msg(\"Field '%s': \");\n"
1551 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1552 " \"Conflicting negative testing attributes, CROSSTAG attribute "
1553 "will be ignored\");\n"
1554 " } else {\n",
1555 (unsigned long)i, sdef->elements[i].name);
1556 if (sdef->elements[i].isOptional) {
1557 src = mputprintf(src,
1558 " if (field_%s.ispresent()) {\n",
1559 sdef->elements[i].name);
1560 }
1561 src = mputprintf(src,
1562 " switch (field_%s%s.get_selection()) {\n",
1563 sdef->elements[i].name,sdef->elements[i].isOptional ? "()" : "");
1564 for (a = 0; a < sdef->elements[i].raw.crosstaglist.nElements; a++) {
1565 rawAST_coding_taglist *cur_choice =
1566 sdef->elements[i].raw.crosstaglist.list + a;
1567 if (cur_choice->nElements > 0) {
1568 int taglist_idx, field_idx;
1569 src = mputprintf(src,
1570 " case %s%s%s: {\n"
1571 " bool negtest_confl_crosstag = false;\n",
1572 sdef->elements[i].type, "::ALT_",
1573 cur_choice->fieldName);
1574 for (taglist_idx = 0;
1575 taglist_idx < cur_choice->nElements; ++taglist_idx) {
1576 rawAST_coding_field_list *fields = cur_choice->fields + taglist_idx;
1577 for (field_idx = 0; field_idx < fields->nElements; ++field_idx) {
1578 rawAST_coding_fields *field = fields->fields + field_idx;
1579 if (field_idx == 0) {
1580 src = mputprintf(src,
1581 " if (idx_map[%d] < 0) {\n"
1582 " negtest_confl_crosstag = true;\n"
1583 " e_c.set_msg(\"Field '%s': \");\n"
1584 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1585 " \"Conflicting negative testing attributes, CROSSTAG attribute "
1586 "will be ignored\");\n"
1587 " }\n",
1588 field->nthfield, field->nthfieldname);
1589 } else {
1590 break;
1591 }
1592 }
1593 }
1594 src = mputstr(src, " if (!negtest_confl_crosstag && (");
1595 src = genRawFieldChecker(src, cur_choice, FALSE);
1596 src = mputstr(src, ")) {\n");
1597 if (!strcmp(cur_choice->fields[0].value, "OMIT_VALUE")) {
1598 if (cur_choice->fields[0].nElements != 1)
1599 NOTSUPP("omit value with multiple fields in CROSSTAG");
1600 /* eliminating the corresponding encoded leaf, which will have
1601 the same effect as if the referred field had been omit */
1602 src = mputprintf(src,
1603 " encoded_length -= myleaf.body.node.nodes[%d]->length;\n"
1604 " delete myleaf.body.node.nodes[%d];\n"
1605 " myleaf.body.node.nodes[%d] = NULL;\n",
1606 cur_choice->fields[0].fields[0].nthfield,
1607 cur_choice->fields[0].fields[0].nthfield,
1608 cur_choice->fields[0].fields[0].nthfield);
1609 } else {
1610 int ll;
1611 src = mputprintf(src,
1612 " RAW_enc_tr_pos pr_pos;\n"
1613 " pr_pos.level = myleaf.curr_pos.level + %d;\n"
1614 " int new_pos[] = { ",
1615 cur_choice->fields[0].nElements);
1616 for (ll = 0; ll < cur_choice->fields[0].nElements; ll++) {
1617 if (ll > 0) src = mputstr(src, ", ");
1618 src = mputprintf(src, "%d",
1619 cur_choice->fields[0].fields[ll].nthfield);
1620 }
1621 src = mputprintf(src, " };\n"
1622 " pr_pos.pos = init_new_tree_pos(myleaf.curr_pos, %d, "
1623 "new_pos);\n",
1624 cur_choice->fields[0].nElements);
1625 if (cur_choice->fields[0].value[0] == ' ') {
1626 /* the value is a string literal (the encoder can be called
1627 on that object directly */
1628 src = mputprintf(src,
1629 " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n"
1630 " if (temp_leaf != NULL)\n"
1631 " %s.RAW_encode(%s_descr_, *temp_leaf);\n"
1632 " else\n"
1633 " TTCN_EncDec_ErrorContext::error\n"
1634 " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged, "
1635 "but omitted value.\");\n",
1636 cur_choice->fields[0].value,
1637 cur_choice->fields[0].fields[
1638 cur_choice->fields[0].nElements - 1].typedescr);
1639 } else {
1640 /* a temporary object needs to be created for encoding */
1641 src = mputprintf(src,
1642 " %s new_val(%s);\n"
1643 " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n"
1644 " if (temp_leaf != NULL)\n"
1645 " new_val.RAW_encode(%s_descr_, *temp_leaf);\n"
1646 " else\n"
1647 " TTCN_EncDec_ErrorContext::error\n"
1648 " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged, "
1649 "but omitted value.\");\n",
1650 cur_choice->fields[0].fields[
1651 cur_choice->fields[0].nElements - 1].type,
1652 cur_choice->fields[0].value,
1653 cur_choice->fields[0].fields[
1654 cur_choice->fields[0].nElements - 1].typedescr);
1655 }
1656 src = mputstr(src, " free_tree_pos(pr_pos.pos);\n");
1657 }
1658 src = mputstr(src, " }\n"
1659 " break; }\n");
1660 }
1661 }
1662 src = mputstr(src, " default:;\n"
1663 " }\n");
1664 if (sdef->elements[i].isOptional) src = mputstr(src, " }\n");
1665 src = mputstr(src, " }\n");
1666 }
1667 }
1668 src = mputprintf(src,
1669 " node_pos = 0;\n"
1670 " next_optional_idx = 0;\n"
1671 " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n"
1672 " boolean is_optional_field = my_optional_indexes &&\n"
1673 " (my_optional_indexes[next_optional_idx] == field_idx);\n"
1674 " if ((p_err_descr->omit_before != -1) &&\n"
1675 " (field_idx < p_err_descr->omit_before)) {\n"
1676 " if (is_optional_field) ++next_optional_idx;\n"
1677 " continue;\n"
1678 " }\n"
1679 " const Erroneous_values_t *err_vals = p_err_descr->get_field_err_values(field_idx);\n"
1680 " const Erroneous_descriptor_t *emb_descr = p_err_descr->get_field_emb_descr(field_idx);\n"
1681 " if (err_vals && err_vals->before) {\n"
1682 " if (err_vals->before->errval == NULL)\n"
1683 " TTCN_error(\"internal error: erroneous before value missing\");\n"
1684 " if (err_vals->before->raw) {\n"
1685 " encoded_length += err_vals->before->errval->"
1686 "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n"
1687 " } else {\n"
1688 " if (err_vals->before->type_descr == NULL)\n"
1689 " TTCN_error(\"internal error: erroneous before typedescriptor missing\");\n"
1690 " encoded_length += err_vals->before->errval->RAW_encode(*(err_vals->before->type_descr),\n"
1691 " *myleaf.body.node.nodes[node_pos++]);\n"
1692 " }\n"
1693 " }\n"
1694 " if (err_vals && err_vals->value) {\n"
1695 " if (err_vals->value->errval) {\n"
1696 " e_c.set_msg(\"'%%s'(erroneous value): \", fld_name(field_idx));\n"
1697 " if (err_vals->value->raw) {\n"
1698 " encoded_length += err_vals->value->errval->"
1699 "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n"
1700 " } else {\n"
1701 " if (err_vals->value->type_descr == NULL)\n"
1702 " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n"
1703 " encoded_length += err_vals->value->errval->"
1704 "RAW_encode(*(err_vals->value->type_descr), *myleaf.body.node.nodes[node_pos++]);\n"
1705 " }\n"
1706 " }\n"
1707 " } else {\n"
1708 " e_c.set_msg(\"'%%s': \", fld_name(field_idx));\n"
1709 " if (!is_optional_field || get_at(field_idx)->ispresent()) {\n"
1710 " const Base_Type *curr_field = is_optional_field "
1711 "? get_at(field_idx)->get_opt_value() : get_at(field_idx);\n"
1712 " if (emb_descr) {\n"
1713 " encoded_length += curr_field\n"
1714 " ->RAW_encode_negtest(emb_descr, *fld_descr(field_idx),\n"
1715 " *myleaf.body.node.nodes[node_pos]);\n"
1716 " }\n"
1717 " } else {\n"
1718 " // `omitted' field.\n"
1719 " myleaf.body.node.nodes[node_pos] = NULL;\n"
1720 " }\n"
1721 " ++node_pos;\n"
1722 " }\n"
1723 " if (err_vals && err_vals->after) {\n"
1724 " if (err_vals->after->errval == NULL)\n"
1725 " TTCN_error(\"internal error: erroneous before value missing\");\n"
1726 " if (err_vals->after->raw) {\n"
1727 " encoded_length += err_vals->after->errval->"
1728 "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n"
1729 " } else {\n"
1730 " if (err_vals->after->type_descr == NULL)\n"
1731 " TTCN_error(\"internal error: erroneous after typedescriptor missing\");\n"
1732 " encoded_length += err_vals->after->errval->"
1733 "RAW_encode(*(err_vals->after->type_descr), *myleaf.body.node.nodes[node_pos++]);\n"
1734 " }\n"
1735 " }\n"
1736 " if (is_optional_field) ++next_optional_idx;\n"
1737 " if ((p_err_descr->omit_after != -1) &&\n"
1738 " (field_idx >= p_err_descr->omit_after))\n"
1739 " break;\n"
1740 " }\n");
1741 /* Presence for the whole record. */
1742 if (sdef->hasRaw && sdef->raw.presence.nElements > 0) {
1743 /* Check the referenced fields. */
1744 int taglist_idx, field_idx;
1745 src = mputstr(src, " bool negtest_confl_presence = false;\n");
1746 for (taglist_idx = 0; taglist_idx < sdef->raw.presence.nElements; ++taglist_idx) {
1747 rawAST_coding_field_list *fields =
1748 sdef->raw.presence.fields + taglist_idx;
1749 for (field_idx = 0; field_idx < fields->nElements; ++field_idx) {
1750 if (field_idx == 0) {
1751 rawAST_coding_fields *field = fields->fields + field_idx;
1752 src = mputprintf(src,
1753 " if (idx_map[%d] < 0) {\n"
1754 " negtest_confl_presence = true;\n"
1755 " e_c.set_msg(\"Field '%s': \");\n"
1756 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n"
1757 " \"Conflicting negative testing attributes, PRESENCE attribute "
1758 "will be ignored\");\n"
1759 " }\n",
1760 field->nthfield, field->nthfieldname);
1761 } else {
1762 break;
1763 }
1764 }
1765 }
1766 src = mputstr(src, " if (!negtest_confl_presence && (");
1767 src = genRawFieldChecker(src, &sdef->raw.presence, FALSE);
1768 src = mputstr(src,")) {\n");
1769 src = genRawTagChecker(src, &sdef->raw.presence);
1770 src = mputstr(src," }\n");
1771 }
1772 src = mputstr(src,
1773 " return myleaf.length = encoded_length;\n"
1774 "}\n\n");
1775 return src;
1776 }
1777
1778 void gen_xer(const struct_def *sdef, char **pdef, char **psrc)
1779 { /* XERSTUFF codegen for record/SEQUENCE */
1780 size_t i;
1781 char *def = *pdef, *src = *psrc;
1782 const char * const name = sdef->name;
1783
1784 /*
1785 * NOTE! Decisions based on the coding instructions of the components
1786 * (e.g. number of attributes) can be made at compile time.
1787 * Decisions on coding instructions of the record itself (e.g. D-F-E,
1788 * EMBED-VALUES, USE-NIL, USE-ORDER) __must__ be postponed to run-time,
1789 * because these can be applied to type references,
1790 * which will not be visible when the code is generated.
1791 */
1792
1793 /* Number of fields with ATTRIBUTE, includes ANY-ATTRIBUTES */
1794 size_t num_attributes = 0;
1795
1796 /* index of USE-ORDER member, which may be bumped into second place by EMBED-VALUES */
1797 size_t uo = (sdef->xerEmbedValuesPossible !=0);
1798
1799 /* start_at is the index of the first "real" member of the record */
1800 size_t start_at = uo + (sdef->xerUseOrderPossible != 0);
1801
1802 /* Max. number of EMBED-VALUES strings. The actual number may change
1803 * at runtime: omitted optional (non-attribute) members decrease the
1804 * number of embed strings needed, and xsi:nil=true sets it to zero.*/
1805 size_t max_embed;
1806
1807 /* Number of optional non-attributes */
1808 size_t n_opt_elements = 0;
1809
1810 const boolean want_namespaces = !sdef->isASN1 /* TODO remove this when ASN.1 gets EXER */;
1811
1812 int aa_index = -1;
1813 /* Find the number of attributes (compile time) */
1814 for (i = 0; i < sdef->nElements; ++i) {
1815 if (sdef->elements[i].xerAttribute) {
1816 ++num_attributes;
1817 }
1818 else if (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT) {
1819 ++num_attributes; /* ANY-ATTRIBUTES also included with attributes */
1820 aa_index = i;
1821 /* If the first member is ANY-ATTRIBUTES, then xerEmbedValuesPossible
1822 * is merely an illusion and USE-ORDER is not possible. */
1823 if (i==0) {
1824 start_at = uo = 0;
1825 }
1826 }
1827 else /* not attribute */ if (sdef->elements[i].isOptional) {
1828 ++n_opt_elements;
1829 }
1830 }
1831 max_embed = sdef->nElements - start_at - num_attributes + 1;
1832
1833 /* Write some helper functions */
1834 def = mputstr(def,
1835 "char **collect_ns(const XERdescriptor_t& p_td, size_t& num_ns, bool& def_ns) const;\n");
1836
1837 src = mputprintf(src,
1838 "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num_ns, bool& def_ns) const {\n"
1839 " size_t num_collected;\n"
1840 " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n"
1841 /* The above might throw but then nothing was allocated. */
1842 , name);
1843
1844 /* Collect namespaces from the "non-special" members (incl. attributes) */
1845 if (start_at < sdef->nElements) src = mputstr(src,
1846 " try {\n"
1847 " char **new_ns;\n"
1848 " size_t num_new;\n"
1849 " bool def_ns_1 = false;\n");
1850 for (i = start_at; i < sdef->nElements; ++i) {
1851 src = mputprintf(src,
1852 " new_ns = field_%s.collect_ns(%s_xer_, num_new, def_ns);\n"
1853 " merge_ns(collected_ns, num_collected, new_ns, num_new);\n"
1854 " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */
1855 , sdef->elements[i].name, sdef->elements[i].typegen
1856 );
1857 }
1858 if (sdef->xerUseNilPossible) {
1859 src = mputprintf(src,
1860 " if((p_td.xer_bits & USE_NIL) && !field_%s.ispresent()) {\n" /* "nil" attribute to be written*/
1861 " collected_ns = (char**)Realloc(collected_ns, sizeof(char*) * ++num_collected);\n"
1862 " const namespace_t *c_ns = p_td.my_module->get_controlns();\n"
1863 " collected_ns[num_collected-1] = mprintf(\" xmlns:%%s='%%s'\", c_ns->px, c_ns->ns);\n"
1864 " }\n"
1865 , sdef->elements[sdef->nElements-1].name
1866 );
1867 }
1868 if (start_at < sdef->nElements) src = mputstr(src,
1869 " }\n"
1870 " catch (...) {\n"
1871 /* Probably a TC_Error thrown from field_%s->collect_ns() if e.g.
1872 * encoding an unbound value. */
1873 " while (num_collected > 0) Free(collected_ns[--num_collected]);\n"
1874 " Free(collected_ns);\n"
1875 " throw;\n"
1876 " }\n"
1877 );
1878
1879 src = mputstr(src,
1880 " num_ns = num_collected;\n"
1881 " return collected_ns;\n"
1882 "}\n\n"
1883 );
1884
1885 src = mputprintf(src,
1886 "boolean %s::can_start(const char *name, const char *uri, const XERdescriptor_t& xd, unsigned int flavor) {\n"
1887 " boolean e_xer = is_exer(flavor &= ~XER_RECOF);\n"
1888 " if (!e_xer || !((xd.xer_bits & UNTAGGED) || (flavor & (USE_NIL|XER_RECOF)))) return check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n"
1889 , name
1890 );
1891 for (i = start_at; i < sdef->nElements; ++i) {
1892 src = mputprintf(src,
1893 " else if (%s::can_start(name, uri, %s_xer_, flavor)) return true;\n"
1894 /* Here we know for sure it's exer */
1895 , sdef->elements[i].type
1896 , sdef->elements[i].typegen
1897 );
1898 if (!sdef->elements[i].isOptional) break;
1899 /* The last component with which it can begin is the first non-optional.
1900 * Does that sentence makes sense to you ? */
1901 }
1902 src = mputstr(src, " return false;\n}\n\n");
1903
1904 /* * * * * * * * * * XER_encode * * * * * * * * * * * * * * */
1905 src = mputprintf(src,
1906 "int %s::XER_encode(const XERdescriptor_t& p_td, "
1907 "TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent) const\n"
1908 "{\n"
1909 " if (!is_bound()) TTCN_EncDec_ErrorContext::error"
1910 "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
1911 " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n"
1912 " TTCN_EncDec_ErrorContext ec_1;\n"
1913 " int encoded_length=(int)p_buf.get_len();\n"
1914 " int e_xer = is_exer(p_flavor);\n"
1915 " const boolean omit_tag = e_xer && p_indent "
1916 "&& ((p_td.xer_bits & (UNTAGGED|XER_ATTRIBUTE)) || (p_flavor & (USE_NIL|USE_TYPE_ATTR)));\n"
1917 " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) p_flavor |= XER_CANONICAL;\n"
1918 " int is_indented = !is_canonical(p_flavor);\n"
1919 , name);
1920
1921 if (want_namespaces && !(num_attributes|sdef->xerUseQName)) src = mputstr(src,
1922 " const boolean need_control_ns = (p_td.xer_bits & (USE_NIL));\n");
1923
1924 if (start_at < sdef->nElements) { /* there _are_ non-special members */
1925 src = mputstr(src,
1926 " size_t num_collected = 0;\n"
1927 " char **collected_ns = NULL;\n"
1928 " bool def_ns = false;\n"
1929 " if (e_xer) {\n"
1930 " if (p_indent == 0) {\n" /* top-level */
1931 " collected_ns = collect_ns(p_td, num_collected, def_ns);\n" /* our own ns */
1932 " }\n"
1933 " else if ((p_flavor & DEF_NS_SQUASHED) && p_td.my_module && p_td.ns_index != -1){\n"
1934 " const namespace_t * ns = p_td.my_module->get_ns(p_td.ns_index);\n"
1935 " if (*ns->px == '\\0') {\n"
1936 " collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n"
1937 " }\n"
1938 " }\n"
1939 " }\n"
1940 );
1941 }
1942
1943 if (want_namespaces) {
1944 src = mputstr(src,
1945 " const boolean empty_ns_hack = e_xer && !omit_tag && (p_indent > 0)\n"
1946 " && (p_td.xer_bits & FORM_UNQUALIFIED)\n"
1947 " && p_td.my_module && p_td.ns_index != -1\n"
1948 " && *p_td.my_module->get_ns(p_td.ns_index)->px == '\\0';\n"
1949 );
1950
1951 src = mputstr(src, " const boolean delay_close = e_xer");
1952 if (!(num_attributes | sdef->xerUseQName)) {
1953 src = mputprintf(src, " && (need_control_ns%s || empty_ns_hack)",
1954 (start_at < sdef->nElements) ? " || num_collected" : "");
1955 }
1956 src = mputstr(src, ";\n");
1957 }
1958
1959
1960 { /* write start tag */
1961 /* From "name>\n":
1962 * lose the \n if : not indenting or (single untagged(*) or attributes (*)) AND e_xer
1963 * lose the > if attributes are present (*) AND e_xer
1964 */
1965 src = mputprintf(src,
1966 " size_t chopped_chars = 0;\n"
1967 " if (!omit_tag) {\n"
1968 " if (is_indented) do_indent(p_buf, p_indent);\n"
1969 " p_buf.put_c('<');\n"
1970 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
1971 " p_buf.put_s((size_t)p_td.namelens[e_xer]%s-(!is_indented%s), "
1972 "(cbyte*)p_td.names[e_xer]);\n"
1973 " }\n"
1974 " else if (p_flavor & USE_TYPE_ATTR) {\n"
1975 " size_t buf_len = p_buf.get_len();\n"
1976 " const unsigned char * const buf_data = p_buf.get_data();\n"
1977 " if (buf_data[buf_len-1-chopped_chars] == '\\n') ++chopped_chars;\n"
1978 " if (buf_data[buf_len-1-chopped_chars] == '>' ) ++chopped_chars;\n"
1979 " if (chopped_chars) {\n"
1980 " p_buf.increase_length(-chopped_chars);\n"
1981 " }\n"
1982 " }\n"
1983 , (want_namespaces ? "-(delay_close || (e_xer && (p_td.xer_bits & HAS_1UNTAGGED)))" : "")
1984 , (want_namespaces ? " || delay_close" : ""));
1985 }
1986
1987 src = mputprintf(src,
1988 " int sub_len=0%s;\n"
1989 " p_flavor &= XER_MASK;\n",
1990 num_attributes ? ", tmp_len; (void)tmp_len" : "");
1991
1992 if (sdef->xerUseQName) {
1993 src = mputprintf(src,
1994 " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n"
1995 " if (field_%s.is_value()) {\n"
1996 " p_buf.put_s(11, (cbyte*)\" xmlns:b0='\");\n"
1997 " field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1);\n"
1998 " p_buf.put_c('\\'');\n"
1999 " }\n"
2000 " if (p_td.xer_bits & XER_ATTRIBUTE) begin_attribute(p_td, p_buf);\n"
2001 " else p_buf.put_c('>');\n"
2002 " if (field_%s.is_value()) {\n"
2003 " p_buf.put_s(3, (cbyte*)\"b0:\");\n"
2004 " sub_len += 3;\n"
2005 " }\n"
2006 " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1);\n"
2007 " if (p_td.xer_bits & XER_ATTRIBUTE) p_buf.put_c('\\'');\n"
2008 " } else" /* no newline */
2009 , sdef->elements[0].name
2010 , sdef->elements[0].name, sdef->elements[0].typegen
2011 , sdef->elements[0].name
2012 , sdef->elements[1].name, sdef->elements[1].typegen
2013 );
2014 }
2015 src = mputstr(src, " { // !QN\n");
2016
2017 /* First, the EMBED-VALUES member as an ordinary member if not doing EXER */
2018 if (sdef->xerEmbedValuesPossible) {
2019 src = mputprintf(src,
2020 " int exp_emb = %u;\n"
2021 " if (!e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n"
2022 " ec_1.set_msg(\"%s': \");\n"
2023 " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1);\n"
2024 " }\n"
2025 , (unsigned int)max_embed
2026 , sdef->elements[0].dispname
2027 , sdef->elements[0].name, sdef->elements[0].typegen
2028 );
2029 }
2030 /* Then, the USE-ORDER member as an ordinary member when !EXER */
2031 if (sdef->xerUseOrderPossible) {
2032 src = mputprintf(src,
2033 " if (!e_xer && (p_td.xer_bits & USE_ORDER)) {\n"
2034 " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1);\n"
2035 " }\n"
2036 , sdef->elements[uo].name, sdef->elements[uo].typegen
2037 );
2038 }
2039
2040 if (start_at+num_attributes > sdef->nElements) FATAL_ERROR("defRecordClass1");
2041
2042 if (want_namespaces && (start_at < sdef->nElements)) {
2043 src = mputstr(src,
2044 " if (e_xer && num_collected) {\n"
2045 " size_t num_ns;\n"
2046 " for (num_ns = 0; num_ns < num_collected; ++num_ns) {\n"
2047 " p_buf.put_s(strlen(collected_ns[num_ns]), (cbyte*)collected_ns[num_ns]);\n"
2048 " Free(collected_ns[num_ns]);\n"
2049 " }\n"
2050 " Free(collected_ns);\n"
2051 " }\n\n"
2052 " if (def_ns) {\n"
2053 " p_flavor &= ~DEF_NS_SQUASHED;\n"
2054 " p_flavor |= DEF_NS_PRESENT;\n"
2055 " }\n"
2056 " else if (empty_ns_hack) {\n"
2057 " p_buf.put_s(9, (cbyte*)\" xmlns=''\");\n"
2058 " p_flavor &= ~DEF_NS_PRESENT;\n"
2059 " p_flavor |= DEF_NS_SQUASHED;\n"
2060 " }\n");
2061 }
2062
2063 /* Then, all the attributes (not added to sub_len) */
2064 for ( i = start_at; i < start_at + num_attributes; ++i ) {
2065 /* If the first component is a record-of with ANY-ATTRIBUTES,
2066 * it has been taken care of because it looked like an EMBED-VALUES */
2067 if (i==0 && sdef->xerEmbedValuesPossible && (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) continue ;
2068 src = mputprintf(src,
2069 " ec_1.set_msg(\"%s': \");\n"
2070 " tmp_len = field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1);\n"
2071 " %ssub_len += tmp_len;\n" /* do not add if attribute and EXER */
2072 , sdef->elements[i].dispname
2073 , sdef->elements[i].name, sdef->elements[i].typegen
2074 , sdef->elements[i].xerAttribute ? "if (!e_xer) " : ""
2075 );
2076 }
2077
2078 if (sdef->xerUseNilPossible) {
2079 src = mputprintf(src,
2080 " bool nil_attribute = e_xer && (p_td.xer_bits & USE_NIL) && !field_%s.ispresent();\n"
2081 " if (nil_attribute) {\n"
2082 " const namespace_t *control_ns = p_td.my_module->get_controlns();\n"
2083 " p_buf.put_c(' ');\n"
2084 " p_buf.put_s(strlen(control_ns->px), (cbyte*)control_ns->px);\n"
2085 " p_buf.put_c(':');\n"
2086 " p_buf.put_s(10, (cbyte*)\"nil='true'\");\n"
2087 " }\n"
2088 , sdef->elements[sdef->nElements-1].name
2089 );
2090 }
2091
2092 if (want_namespaces) {
2093 /* there were some attributes. close the start tag left open */
2094 src = mputprintf(src,
2095 " if (delay_close && (!omit_tag || chopped_chars)) p_buf.put_s(1%s, (cbyte*)\">\\n\");\n", /* close the start tag */
2096 (sdef->xerUntaggedOne /*|| sdef->xerUseNil*/) ? "" : "+is_indented"
2097 );
2098 }
2099
2100 if (sdef->xerEmbedValuesPossible) {
2101 size_t op;
2102 src = mputprintf(src,
2103 " ec_1.set_msg(\"%s': \");\n"
2104 " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n"
2105 , sdef->elements[0].dispname
2106 );
2107
2108 if (sdef->xerUseNilPossible) {
2109 src = mputstr(src, /* 25.2.6 a */
2110 " if ((p_td.xer_bits & USE_NIL) && nil_attribute) exp_emb = 0;\n"
2111 " else {\n");
2112 }
2113
2114 for (op = 0; op < sdef->nElements; ++op) {
2115 if (sdef->elements[op].isOptional && !sdef->elements[op].xerAttribute) {
2116 src = mputprintf(src,
2117 " if (!field_%s.ispresent()) --exp_emb;\n"
2118 , sdef->elements[op].name
2119 );
2120 }
2121 }
2122
2123 if (sdef->xerUseNilPossible) src = mputstr(src, " }\n");
2124
2125 src = mputprintf(src,
2126 " if (field_%s.size_of()!=exp_emb) "
2127 "TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, "
2128 "\"Wrong number %%d of EMBED-VALUEs, expected %%d\", field_%s.size_of(), exp_emb);\n"
2129 , sdef->elements[0].name
2130 , sdef->elements[0].name);
2131 /* write the first string (must come AFTER the attributes) */
2132 src = mputprintf(src,
2133 " %ssub_len += field_%s[0].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1);\n"
2134 " }\n"
2135 , (sdef->xerUseNilPossible ? "if (exp_emb > 0) " : "")
2136 , sdef->elements[0].name);
2137 if (want_namespaces) { /* here's another chance */
2138 src = mputprintf(src,
2139 " else if ( !(p_td.xer_bits & EMBED_VALUES)) {\n"
2140 " %sfield_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1);\n"
2141 " }\n"
2142 , ((sdef->elements[0].xerAnyKind & ANY_ATTRIB_BIT) ? "" : "sub_len += " )
2143 , sdef->elements[0].name, sdef->elements[0].typegen
2144 );
2145 }
2146 }
2147
2148 /* Then, all the non-attributes. Structuring the code like this depends on
2149 * all attributes appearing before all non-attributes (excluding
2150 * special members for EMBED-VALUES, USE-ORDER, etc.) */
2151 if (sdef->xerUseOrderPossible) {
2152 int max_ordered = sdef->nElements - start_at - num_attributes;
2153 int min_ordered = max_ordered - n_opt_elements;
2154 size_t offset = 0;
2155 size_t base = i;
2156 size_t limit = sdef->nElements;
2157 /* base and limit are indexes into sdef->elements[] */
2158 src = mputprintf(src,
2159 " int dis_order = e_xer && (p_td.xer_bits & USE_ORDER);\n"
2160 " int to_send = field_%s.lengthof();\n"
2161 " int uo_limit = dis_order ? to_send : %lu;\n"
2162 , sdef->elements[start_at-1].name
2163 , (unsigned long)(limit - base)
2164 );
2165 if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */
2166 base = sdef->nElements;
2167 limit = sdef->totalElements;
2168 min_ordered = max_ordered = limit - base;
2169 src = mputprintf(src,
2170 " if (!nil_attribute) {\n"
2171 "%s"
2172 " if (!e_xer) sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag);\n"
2173 " else" /* no newline */
2174 , (sdef->xerUseNilPossible ? " if (!(p_td.xer_bits & USE_ORDER)) p_flavor |= (p_td.xer_bits & USE_NIL);\n" : "")
2175 /* If USE-ORDER is on, the tag-removing effect of USE-NIL has been
2176 * performed by calling the sub-fields directly. */
2177 , sdef->elements[sdef->nElements-1].name
2178 , sdef->elements[sdef->nElements-1].typegen
2179 );
2180 }
2181
2182 /* check incorrect data */
2183 src = mputprintf(src,
2184 " {\n"
2185 " if (to_send < %d || to_send > %d) {\n"
2186 " ec_1.set_msg(\"%s': \");\n"
2187 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, "
2188 "\"Wrong number of USE-ORDER, %%d instead of %d..%d\", to_send);\n"
2189 " uo_limit = -1;\n" /* squash the loop */
2190 " }\n"
2191 " else {\n" /* check duplicates */
2192 " int *seen = new int [to_send];\n"
2193 " int num_seen = 0;\n"
2194 " for (int ei = 0; ei < to_send; ++ei) {\n"
2195 " int val = field_%s[ei];\n"
2196 " for (int x = 0; x < num_seen; ++x) {\n"
2197 " if (val == seen[x]) { // complain\n"
2198 " ec_1.set_msg(\"%s': \");\n"
2199 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n"
2200 " \"Duplicate value for USE-ORDER\");\n"
2201 " uo_limit = -1; // don't bother sending anything\n"
2202 " goto trouble;\n"
2203 " }\n"
2204 " }\n"
2205 " seen[num_seen++] = val;\n"
2206 " }\n"
2207 "trouble:\n"
2208 " delete [] seen;"
2209 " }\n"
2210 " "
2211 , min_ordered, max_ordered
2212 , sdef->elements[start_at-1].dispname
2213 , min_ordered, max_ordered
2214 , sdef->elements[start_at-1].name
2215 , sdef->elements[start_at-1].dispname
2216 );
2217
2218 src = mputprintf(src,
2219 " for (int i = 0; i < uo_limit; ++i) {\n"
2220 " switch (dis_order ? (int)field_%s[i] : i) {\n"
2221 , sdef->elements[start_at-1].name
2222 );
2223 for ( i = base; i < limit; ++i ) {
2224 src = mputprintf(src,
2225 " case %lu:\n"
2226 " ec_1.set_msg(\"%s': \");\n"
2227 " sub_len += field_%s%s%s%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag);\n"
2228
2229 , (unsigned long)offset++
2230 , sdef->elements[i].dispname
2231 , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name : sdef->elements[i].name)
2232 , (sdef->xerUseNilPossible ? "()." : "")
2233 , (sdef->xerUseNilPossible ? sdef->elements[i].name : "")
2234 , (sdef->xerUseNilPossible ? "()" : "")
2235 , sdef->elements[i].typegen
2236
2237 );
2238
2239 src = mputstr(src, " break;\n");
2240 } /* next element */
2241 src = mputstr(src,
2242 " default:\n"
2243 " TTCN_error(\"Runaway value while encoding USE-ORDER\");\n"
2244 " break;\n" /* cannot happen, complain */
2245 " }\n");
2246
2247 if (sdef->xerEmbedValuesPossible) {
2248 src = mputprintf(src,
2249 " if (e_xer && i+1 < exp_emb && (p_td.xer_bits & EMBED_VALUES)) { // embed-val\n"
2250 " field_%s[i+1].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1);\n"
2251 " }\n"
2252 , sdef->elements[0].name);
2253 }
2254
2255
2256 src = mputstr(src,
2257 " }\n" /* end of loop */
2258 " } // exer\n");
2259 if (sdef->xerUseNilPossible) {
2260 src = mputstr(src, " } // nil_attr\n");
2261 }
2262 }
2263 else /* not USE-ORDER */
2264 for ( /* continue with i */; i < sdef->nElements; ++i ) {
2265 src = mputprintf(src,
2266 " ec_1.set_msg(\"%s': \");\n"
2267 , sdef->elements[i].dispname
2268 );
2269 src = mputprintf(src,
2270 " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor%s, p_indent+!omit_tag);\n"
2271 , sdef->elements[i].name, sdef->elements[i].typegen
2272 , sdef->xerUseNilPossible ? "| (p_td.xer_bits & USE_NIL)" : ""
2273 );
2274
2275 if (sdef->xerEmbedValuesPossible) {
2276 unsigned long idx = i - start_at - num_attributes + 1;
2277 src = mputprintf(src,
2278 " if (e_xer && exp_emb > %lu && (p_td.xer_bits & EMBED_VALUES)) {\n"
2279 " field_%s[%lu].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1);\n"
2280 " }\n"
2281 , idx
2282 , sdef->elements[0].name, idx);
2283 }
2284 } /* next field when not USE-ORDER */
2285
2286 src = mputstr(src, " } // QN?\n");
2287
2288 {
2289 src = mputprintf(src,
2290 " if (!omit_tag) {\n"
2291 " if (sub_len) {\n" /* something was written, now an end tag */
2292 " if (is_indented && !(e_xer && (p_td.xer_bits & (HAS_1UNTAGGED | USE_QNAME)))) {\n"
2293 " switch ((int)(e_xer && (p_td.xer_bits & USE_NIL))) {\n"
2294 " case 1: {\n"
2295 " const unsigned char *buf_end = p_buf.get_data() + (p_buf.get_len()-1);\n"
2296 " if (buf_end[-1] != '>' || *buf_end != '\\n') break;\n"
2297 /* else fall through */
2298 " }\n"
2299 " case 0:\n"
2300 " do_indent(p_buf, p_indent);\n"
2301 " break;\n"
2302 " }\n"
2303 " }\n"
2304 " p_buf.put_c('<');\n"
2305 " p_buf.put_c('/');\n"
2306 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
2307 " p_buf.put_s((size_t)p_td.namelens[e_xer]-!is_indented, (cbyte*)p_td.names[e_xer]);\n"
2308 " } else {\n" /* need to generate an empty element tag */
2309 " p_buf.increase_length(%s-1);\n" /* decrease length */
2310 " p_buf.put_s((size_t)2+is_indented, (cbyte*)\"/>\\n\");\n"
2311 " }}\n"
2312 , (sdef->xerUntaggedOne /*|| sdef->xerUseNil*/) ? "" : "-is_indented"
2313 );
2314 }
2315 src = mputstr(src,
2316 " return (int)p_buf.get_len() - encoded_length;\n"
2317 "}\n\n");
2318
2319 #ifndef NDEBUG
2320 src = mputprintf(src, "// %s has%s%s%s%s%s%s%s%s%s\n"
2321 "// written by %s in " __FILE__ " at %d\n"
2322 , name
2323 , (sdef->xerUntagged ? " UNTAGGED" : "")
2324 , (sdef->xerUntaggedOne ? "1" : "")
2325 , (sdef->xerUseNilPossible ? " USE_NIL?" : "")
2326 , (sdef->xerUseOrderPossible ? " USE_ORDER?" : "")
2327 , (sdef->xerUseQName ? " USE_QNAME" : "")
2328 , (sdef->xerUseTypeAttr ? " USE_TYPE_ATTR" : "")
2329 , (sdef->xerUseUnion ? " USE-UNION" : "")
2330 , (sdef->xerHasNamespaces ? " namespace" : "")
2331 , (sdef->xerEmbedValuesPossible ? " EMBED?" : "")
2332 , __FUNCTION__, __LINE__
2333 );
2334 #endif
2335
2336 src = mputprintf(src, /* XERSTUFF decodegen for record/SEQUENCE*/
2337 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader,"
2338 " unsigned int p_flavor)\n"
2339 "{\n"
2340 " bound_flag = TRUE;\n"
2341 /* Remove XER_LIST, XER_RECOF from p_flavor. This is not required
2342 * for is_exer (which tests another bit), but for subsequent code. */
2343 " int e_xer = is_exer(p_flavor);\n"
2344 " int xerbits = p_td.xer_bits;\n"
2345 " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n"
2346 " const boolean omit_tag = e_xer && ((xerbits & (UNTAGGED|XER_ATTRIBUTE)) "
2347 "|| (p_flavor & (USE_NIL|USE_TYPE_ATTR)));\n"
2348 "%s"
2349 " const boolean parent_tag = e_xer && (p_flavor & (USE_TYPE_ATTR));\n"
2350 " (void)parent_tag;\n"
2351 " p_flavor &= XER_MASK;\n" /* also removes "toplevel" bit */
2352 " int rd_ok, xml_depth=-1, type;\n"
2353 " {\n" /* scope for the error contexts */
2354 , name
2355 , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0)
2356 ? " boolean tag_closed = (p_flavor & PARENT_CLOSED) != 0;\n" : "")
2357 /* tag_closed needed for non-attribute normal members only,
2358 * or if EMBED-VALUES is possible, but isn't. */
2359 );
2360
2361 if (sdef->xerUseNilPossible) src = mputstr(src,
2362 " boolean nil_attribute = FALSE;\n");
2363
2364 src = mputprintf(src,
2365 " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n"
2366 " TTCN_EncDec_ErrorContext ec_1;\n"
2367 " if (!omit_tag) for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n"
2368 " type = p_reader.NodeType();\n"
2369 " if (type==XML_READER_TYPE_ELEMENT) {\n"
2370 " verify_name(p_reader, p_td, e_xer);\n"
2371 " xml_depth = p_reader.Depth();\n"
2372 "%s"
2373 " break;\n"
2374 " }\n"
2375 " }\n"
2376 , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0)
2377 ? " tag_closed = p_reader.IsEmptyElement();\n": "")
2378 );
2379
2380
2381 if (sdef->xerUseQName) {
2382 src = mputprintf(src,
2383 " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n"
2384 " if (p_td.xer_bits & XER_ATTRIBUTE) rd_ok = 1;\n"
2385 " else for (rd_ok = p_reader.Read(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
2386 " type = p_reader.NodeType();\n"
2387 " if (type == XML_READER_TYPE_TEXT) break;\n"
2388 " }\n"
2389 " if (rd_ok==1) {\n"
2390 " xmlChar *new_val = p_reader.NewValue();\n"
2391 " xmlChar *v_npfx = (xmlChar*)strchr((char*)new_val, ':');\n"
2392 " xmlChar *v_pfx;\n"
2393 " if (v_npfx != NULL) {\n"
2394 " *v_npfx++ = '\\0';\n"
2395 " v_pfx = new_val;\n"
2396 " }\n"
2397 " else {\n"
2398 " v_npfx = new_val;\n"
2399 " v_pfx = NULL;\n"
2400 " }\n"
2401 " xmlChar *q_ns = p_reader.LookupNamespace(v_pfx);\n"
2402 " if (q_ns) field_%s = (const char*)q_ns;\n"
2403 " else field_%s = OMIT_VALUE;\n"
2404 " field_%s = (const char*)v_npfx;\n"
2405 " xmlFree(q_ns);\n"
2406 " xmlFree(new_val);\n"
2407 " }\n"
2408 " } else {\n"
2409 , sdef->elements[0].name
2410 , sdef->elements[0].name
2411 , sdef->elements[1].name
2412 );
2413 } /* QName */
2414
2415 if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) {
2416 src = mputstr(src, "if (e_xer) {\n");
2417 }
2418
2419 /* ********************************************************************
2420 * ATTRIBUTES
2421 ***************************/
2422 if (num_attributes || sdef->xerUseNilPossible /* maybe QNAME too ? */) {
2423 size_t aaa;
2424 src = mputstr(src, " if (!omit_tag || parent_tag) {\n");
2425
2426 /* Prepare for attributes not present in the XML.
2427 * Set all attributes with defaultForEmpty to the D-F-E value.
2428 * Set all optional components with ATTRIBUTE to omit.
2429 *
2430 * If EMBED-VALUES is possible, the first component can't be optional.
2431 * The same is true for the USE-ORDER component. Hence start_at. */
2432 for (aaa = start_at; aaa < start_at + num_attributes; ++aaa) {
2433 if (sdef->elements[aaa].xerAttribute) { /* "proper" ATTRIBUTE */
2434 src = mputprintf(src,
2435 " if (%s_xer_.dfeValue) field_%s = "
2436 "*static_cast<const %s*>(%s_xer_.dfeValue);\n"
2437 , sdef->elements[aaa].typegen, sdef->elements[aaa].name
2438 , sdef->elements[aaa].type , sdef->elements[aaa].typegen);
2439 if (sdef->elements[aaa].isOptional) src = mputprintf(src,
2440 " else field_%s = OMIT_VALUE;\n", sdef->elements[aaa].name);
2441 }
2442 else { /* must be the ANY-ATTRIBUTES */
2443 src = mputprintf(src,
2444 " field_%s.set_size(0);\n",
2445 sdef->elements[aaa].name);
2446 }
2447 }
2448
2449 if (num_attributes==0 /* therefore sdef->xerUseNilPossible is true */ ) {
2450 /* Only the "nil" attribute may be present. If there is no USE-NIL,
2451 * then there can be no attributes at all. */
2452 src = mputstr(src,
2453 " if (e_xer && (p_td.xer_bits & (USE_NIL|USE_TYPE_ATTR))) {\n");
2454 }
2455
2456 if (aa_index > -1) src = mputstr(src, " size_t num_aa = 0;\n");
2457 if (sdef->xerUseNilPossible) {
2458 src = mputstr(src,
2459 " static const namespace_t *control_ns = p_td.my_module->get_controlns();\n");
2460 }
2461
2462 src = mputstr(src,
2463 " for (rd_ok = p_reader.MoveToFirstAttribute(); rd_ok==1 && "
2464 "p_reader.NodeType()==XML_READER_TYPE_ATTRIBUTE; "
2465 "rd_ok = p_reader.AdvanceAttribute()) {\n"
2466 " if (p_reader.IsNamespaceDecl()) continue;\n");
2467 /* if the only attribute is ANY-ATTRIBUTE, it doesn't need attr_name */
2468 if (num_attributes==1 && aa_index!=-1 /*&& !sdef->xerUseNilPossible*/) {}
2469 else {
2470 src = mputstr(src,
2471 " const char *attr_name = (const char*)p_reader.LocalName();\n"
2472 " const char *ns_uri = (const char*)p_reader.NamespaceUri();\n");
2473 }
2474
2475 if (sdef->xerUseNilPossible) {
2476 src = mputprintf(src,
2477 " const char *prefix = (const char*)p_reader.Prefix();\n"
2478 /* prefix may be NULL, control_ns->px is never NULL or empty */
2479 " if (prefix && !strcmp(prefix, control_ns->px)\n"
2480 " && !strcmp((const char*)p_reader.LocalName(), \"nil\")){\n"
2481 " const char *value = (const char*)p_reader.Value();\n"
2482 " if (!strcmp(value, \"1\") || !strcmp(value, \"true\")) {\n"
2483 " field_%s = OMIT_VALUE;\n"
2484 " nil_attribute = TRUE;\n"
2485 /* found the "nil" attribute */
2486 " }\n"
2487 " } else"
2488 , sdef->elements[sdef->nElements-1].name);
2489 }
2490
2491 for (i = start_at; i < start_at + num_attributes; ++i) {
2492 if (i == aa_index) continue; /* ANY_ATTR. is handled below */
2493 src = mputprintf(src,
2494 " if (check_name(attr_name, %s_xer_, 1) && check_namespace(ns_uri, %s_xer_)) {\n"
2495 " ec_1.set_msg(\"%s': \");\n"
2496 " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL));\n"
2497 " } else"
2498 , sdef->elements[i].typegen, sdef->elements[i].typegen
2499 , sdef->elements[i].dispname /* set_msg */
2500 , sdef->elements[i].name, sdef->elements[i].typegen
2501 );
2502 }
2503
2504 if (sdef->control_ns_prefix && !(num_attributes==1 && aa_index!=-1)) {
2505 src = mputprintf(src,
2506 " if (parent_tag && !strcmp(attr_name, \"type\") "
2507 "&& !strcmp((const char*)p_reader.Prefix(), \"%s\")) {} else\n"
2508 , sdef->control_ns_prefix);
2509 /* xsi:type; already processed by parent with USE-UNION or USE-TYPE */
2510 }
2511
2512
2513 if (aa_index >= 0) {
2514 /* we are at a dangling else */
2515 src = mputprintf(src,
2516 " {\n"
2517 " TTCN_EncDec_ErrorContext ec_0(\"Attribute %%d: \", (int)num_aa);"
2518 " UNIVERSAL_CHARSTRING& new_elem = field_%s[num_aa++];\n"
2519 /* Construct the AnyAttributeFormat (X.693amd1, 18.2.6) */
2520 " TTCN_Buffer aabuf;\n"
2521 " const xmlChar *x_name = p_reader.LocalName();\n"
2522 " const xmlChar *x_val = p_reader.Value();\n"
2523 " const xmlChar *x_uri = p_reader.NamespaceUri();\n"
2524 " if (%s_xer_.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
2525 " check_namespace_restrictions(%s_xer_, (const char*)x_uri);\n"
2526 " }\n"
2527 /* We don't care about p_reader.Prefix() */
2528 /* Using strlen to count bytes */
2529 " aabuf.put_s(x_uri ? strlen((const char*)x_uri) : 0, x_uri);\n"
2530 " if (x_uri && *x_uri) aabuf.put_c(' ');\n"
2531 " aabuf.put_s(x_name ? strlen((const char*)x_name) : 0, x_name);\n"
2532 " aabuf.put_c('=');\n"
2533 " aabuf.put_c('\"');\n"
2534 " aabuf.put_s(x_val ? strlen((const char*)x_val) : 0, x_val);\n"
2535 " aabuf.put_c('\"');\n"
2536 " new_elem.decode_utf8(aabuf.get_len(), aabuf.get_data());\n"
2537 " } \n"
2538 , sdef->elements[aa_index].name
2539 , sdef->elements[aa_index].typegen, sdef->elements[aa_index].typegen
2540 );
2541 }
2542 else {
2543 /* we are at a dangling else */
2544 src = mputstr(src, " {\n");
2545 if (sdef->control_ns_prefix) {
2546 src = mputprintf(src,
2547 // Lastly check for the xsi:schemaLocation attribute, this does not
2548 // affect TTCN-3, but it shouldn't cause a DTE
2549 " if (!p_reader.LocalName() || strcmp((const char*)p_reader.LocalName(), \"schemaLocation\") ||\n"
2550 " !p_reader.Prefix() || strcmp((const char*)p_reader.Prefix(), \"%s\"))\n"
2551 , sdef->control_ns_prefix);
2552 }
2553 src = mputstr(src,
2554 " {\n"
2555 " ec_0.set_msg(\" \"); ec_1.set_msg(\" \");\n" /* we have no component */
2556 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
2557 "\"Unexpected attribute '%s', ns '%s'\", attr_name, ns_uri ? ns_uri : \"\");\n"
2558 " }\n"
2559 " }\n");
2560 }
2561 src = mputstr(src, " }\n"); /* for */
2562
2563 for (i = start_at; i < start_at + num_attributes; ++i) {
2564 if (sdef->elements[i].isOptional) continue; /* allowed to be missing */
2565 src = mputprintf(src, " if (!field_%s.is_bound()) "
2566 "TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
2567 "\"Missing attribute '%s'\");\n"
2568 , sdef->elements[i].name, sdef->elements[i].dispname);
2569 }
2570
2571 if (num_attributes==0) src = mputstr(src, " }\n"); /* if USE_NIL or USE_TYPE_ATTR */
2572 src = mputstr(src, " }\n"); /* process (attributes) in (own or parent) tag */
2573 } /* * * * * * * * * end if(attributes...) * * * * * * * * * * * * */
2574
2575 src = mputstr(src,
2576 " if ((!omit_tag || parent_tag) && !p_reader.IsEmptyElement()) "
2577 "rd_ok = p_reader.Read();\n");
2578
2579 if (sdef->xerEmbedValuesPossible && num_attributes==0) {
2580 /* EMBED-VALUES possible, but isn't: the first component is a non-special
2581 * record of strings. This means there are no attributes, unless
2582 * the first component is an ATTRIBUTE or ANY-ATTRIBUTES. */
2583 src = mputprintf(src,
2584 " if (!(p_td.xer_bits & EMBED_VALUES)) {\n"
2585 " ec_1.set_msg(\"%s': \");\n"
2586 " field_%s.XER_decode(%s_xer_, p_reader, "
2587 "p_flavor | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0));\n"
2588 " }\n"
2589 , sdef->elements[0].dispname
2590 , sdef->elements[0].name, sdef->elements[0].typegen
2591 );
2592 }
2593
2594 if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) {
2595 src = mputstr(src,
2596 "} else {\n" /* now the non-EXER processing of (would-be) attributes */
2597 " if (!p_reader.IsEmptyElement()) p_reader.Read();\n"
2598 );
2599 }
2600
2601 if (sdef->xerUseOrderPossible) {
2602 src = mputstr(src,
2603 " if (e_xer && p_td.xer_bits & USE_ORDER) ; else {");
2604 }
2605
2606 if (start_at + num_attributes > 0)
2607 {
2608 /* No attributes nor USE-NIL:
2609 * Just decode the specials and would-be attributes. */
2610
2611 // FIXME: WTF is this?
2612 //if (sdef->xerEmbedValuesPossible) {
2613 // /* Only decode the first member if it really is EMBED-VALUES */
2614 // src = mputprintf(src, "if (p_td.xer_bits & EMBED_VALUES) ");
2615 //}
2616 for (i = 0; i < start_at + num_attributes; ++i) {
2617 /* Decode the field */
2618 src = mputprintf(src,
2619 " {\n"
2620 " ec_1.set_msg(\"%s': \");\n"
2621 " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL));\n"
2622 " }\n"
2623 , sdef->elements[i].dispname
2624 , sdef->elements[i].name, sdef->elements[i].typegen
2625 );
2626 } /* next field */
2627
2628 if (sdef->xerUseOrderPossible) {
2629 src = mputstr(src, " }\n");
2630 }
2631 }
2632
2633 if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) {
2634 src = mputstr(src, "}\n");
2635 }
2636
2637 if (sdef->xerUseOrderPossible) {
2638 size_t begin = start_at + num_attributes; /* first non-attribute */
2639 size_t end = sdef->nElements;
2640 size_t n_optionals = 0, n_embed;
2641 int max_ordered = sdef->nElements - start_at - num_attributes;
2642 int min_ordered = max_ordered - n_opt_elements;
2643 if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */
2644 begin = sdef->nElements;
2645 end = sdef->totalElements;
2646 }
2647 n_embed = end - begin;
2648
2649 src = mputstr(src,
2650 " if (e_xer && (p_td.xer_bits & USE_ORDER)) {\n"
2651 );
2652 for (i = begin; i < end; ++i) {
2653 if (sdef->elements[i].isOptional) {
2654 src = mputprintf(src, " field_%s = OMIT_VALUE;\n",
2655 sdef->elements[i].name);
2656 ++n_optionals;
2657 }
2658 }
2659
2660 if (sdef->xerEmbedValuesPossible) { /* EMBED-VALUES with USE-ORDER */
2661 src = mputprintf(src,
2662 " if (p_td.xer_bits & EMBED_VALUES) {\n"
2663 " field_%s.set_size(%lu);\n"
2664 " %s::of_type empty_string(\"\");\n"
2665 " for (int j_j=0; j_j<%lu; ++j_j) {\n"
2666 " field_%s[j_j] = empty_string;\n"
2667 " }\n"
2668 " }\n"
2669 , sdef->elements[0].name
2670 , (unsigned long)(n_embed + 1)
2671 , sdef->elements[0].type
2672 , (unsigned long)(n_embed + 1)
2673 , sdef->elements[0].name
2674 );
2675 }
2676
2677 if (sdef->xerUseNilPossible) { /* USE-NIL and USE-ORDER */
2678 src = mputprintf(src,
2679 " if (nil_attribute) field_%s.set_size(0);\n else"
2680 , sdef->elements[uo].name);
2681 }
2682
2683 src = mputprintf(src,
2684 " {\n"
2685 " field_%s.set_size(0);\n"
2686 " int e_val, num_seen = 0, *seen_f = new int[%lu];\n"
2687 " for (int i=0; i < %lu; ++i) {\n"
2688 " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n"
2689 , sdef->elements[uo].name
2690 , (unsigned long)(n_embed)
2691 , (unsigned long)(n_embed));
2692
2693 if (sdef->xerEmbedValuesPossible) {
2694 /* read and store embedValues text if present */
2695 src = mputprintf(src,
2696 " if ((p_td.xer_bits & EMBED_VALUES) && (p_reader.NodeType()==XML_READER_TYPE_TEXT)) {\n"
2697 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
2698 " field_%s[i] = emb_ustr;\n"
2699 " }\n"
2700 , sdef->elements[0].name);
2701 }
2702
2703 src = mputstr(src,
2704 " type = p_reader.NodeType();\n"
2705 " if (type==XML_READER_TYPE_ELEMENT) break;\n"
2706 " }\n"
2707 " if (rd_ok != 1) break;\n"
2708 " const char * x_name = (const char*)p_reader.LocalName();\n" /* Name or LocalName ? */);
2709
2710
2711 /* * * * * code for USE-ORDER * * * * */
2712
2713 for (i = begin; i < end; ++i) {
2714 // Check non-anyElement fields first
2715 if (!(sdef->elements[i].xerAnyKind & ANY_ELEM_BIT)) {
2716 src = mputprintf(src,
2717 " if (check_name(x_name, %s_xer_, 1)) {\n"
2718 " ec_1.set_msg(\"%s': \");\n"
2719 " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor);\n"
2720 , sdef->elements[i].typegen
2721 , sdef->elements[i].dispname
2722
2723 , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name)
2724 , (sdef->xerUseNilPossible ? "()." : "")
2725 , (sdef->xerUseNilPossible ? sdef->elements[i].name : "")
2726 , (sdef->xerUseNilPossible ? "()" : "")
2727 , sdef->elements[i].typegen
2728 );
2729 src = mputprintf(src,
2730 " field_%s[i] = e_val = %s::of_type::%s;\n"
2731 , sdef->elements[uo].name
2732 , sdef->elements[uo].typegen, sdef->elements[i].name);
2733 src = mputstr(src, " }\n else");
2734 }
2735 }
2736 src = mputstr(src,
2737 " {\n"
2738 " boolean any_found = false;\n"
2739 " if (!any_found)");
2740 for (i = begin; i < end; ++i) {
2741 // Check anyElement fields after all other fields
2742 if (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT) {
2743 src = mputstr(src, " {\n");
2744 src = mputprintf(src,
2745 " e_val = %s::of_type::%s;\n"
2746 , sdef->elements[uo].typegen, sdef->elements[i].name);
2747 src = mputprintf(src,
2748 " boolean next_any = false;\n"
2749 " for (int d_f = 0; d_f < num_seen; ++d_f) {\n"
2750 " if (e_val == seen_f[d_f]) {\n"
2751 " next_any = true;\n"
2752 " }\n"
2753 " }\n"
2754 " if (!next_any) {\n"
2755 " ec_1.set_msg(\"%s': \");\n"
2756 " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor);\n"
2757 " field_%s[i] = e_val;\n"
2758 " any_found = true;\n"
2759 " }\n"
2760 " }\n"
2761 " if (!any_found)"
2762 , sdef->elements[i].dispname
2763 , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name)
2764 , (sdef->xerUseNilPossible ? "()." : "")
2765 , (sdef->xerUseNilPossible ? sdef->elements[i].name : "")
2766 , (sdef->xerUseNilPossible ? "()" : "")
2767 , sdef->elements[i].typegen, sdef->elements[uo].name
2768 );
2769 }
2770 }
2771
2772 src = mputstr(src,
2773 " continue; \n" /* take care of the dangling else */
2774 " }\n"
2775 " for (int d_f = 0; d_f < num_seen; ++d_f)\n"
2776 " if (e_val == seen_f[d_f])\n"
2777 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Duplicate field\");\n"
2778 " seen_f[num_seen++] = e_val;\n"
2779 " } // next i\n");
2780
2781 if (sdef->xerEmbedValuesPossible) {
2782 /* read and store embedValues text if present */
2783 src = mputprintf(src,
2784 " if ((p_td.xer_bits & EMBED_VALUES) && (p_reader.NodeType()==XML_READER_TYPE_TEXT)) {\n"
2785 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
2786 " field_%s[%lu] = emb_ustr;\n"
2787 " }\n"
2788 , sdef->elements[0].name, (unsigned long)(n_embed));
2789 }
2790
2791 src = mputprintf(src,
2792 " delete [] seen_f;\n"
2793 " }\n"
2794 " int n_collected = field_%s.size_of();\n"
2795 " if (p_td.xer_bits & USE_NIL) {\n"
2796 " ;\n"
2797 " } else {\n"
2798 " if (n_collected < %d || n_collected > %d) {\n"
2799 " ec_0.set_msg(\" \");\n"
2800 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Wrong number of elements\");\n"
2801 " }\n"
2802 " }\n"
2803 " } else { // !uo\n"
2804 , sdef->elements[uo].dispname
2805 , min_ordered, max_ordered
2806 );
2807 } /* end if(UseOrder possible) */
2808
2809 /* * * * * non-UseOrder code always written, executed when * * * *
2810 * * * * * UseOrder not possible or in the "else" clause * * * * */
2811
2812 if (sdef->xerUseNilPossible) {
2813 /* value absent, nothing more to do */
2814 src = mputstr(src,
2815 " if (nil_attribute) {\n"
2816 " p_reader.MoveToElement();\n"
2817 " } else {\n");
2818 }
2819 /* for all the non-attribute fields... */
2820 for (i = start_at + num_attributes; i < sdef->nElements; ++i) {
2821 if (sdef->xerEmbedValuesPossible) {
2822 /* read and store embedValues text if present */
2823 src = mputprintf(src,
2824 " if ((p_td.xer_bits & EMBED_VALUES) && (p_reader.NodeType()==XML_READER_TYPE_TEXT)) {\n"
2825 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
2826 " field_%s[%lu] = emb_ustr;\n"
2827 " }\n"
2828 , sdef->elements[0].name, (unsigned long)(i-(start_at+num_attributes)));
2829 }
2830 /* The DEFAULT-FOR-EMPTY member can not be involved with EMBED-VALUES,
2831 * so we can use the same pattern: optional "if(...) else" before {}
2832 * XXX check with single-element record where nElements-1 == 0 !! */
2833 if (sdef->kind == RECORD && i == sdef->nElements-1) {
2834 src = mputprintf(src,
2835 " if (e_xer && p_td.dfeValue && p_reader.IsEmptyElement()) {\n"
2836 " field_%s = *static_cast<const %s*>(p_td.dfeValue);\n"
2837 " }\n"
2838 " else"
2839 , sdef->elements[i].name, sdef->elements[i].type);
2840 }
2841 /* Decode the field */
2842 src = mputprintf(src,
2843 " {\n"
2844 " ec_1.set_msg(\"%s': \");\n"
2845 , sdef->elements[i].dispname);
2846
2847 if ( (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT)
2848 && !strcmp(sdef->elements[i].type,"UNIVERSAL_CHARSTRING") ) {
2849 // In case the field is an optional anyElement -> check if it should be omitted
2850 if (sdef->elements[i].isOptional) {
2851 src = mputprintf(src,
2852 " if (field_%s.XER_check_any_elem(p_reader, \"%s\", tag_closed))\n "
2853 , sdef->elements[i].name
2854 , (i == sdef->nElements - 1) ? "NULL" : sdef->elements[i + 1].name);
2855 } else {
2856 // If the record is emptyElement, there's no way it will have an anyElement field
2857 src = mputstr(src, " if (tag_closed) p_reader.Read(); \n");
2858 }
2859 }
2860
2861 src = mputprintf(src,
2862 " field_%s.XER_decode(%s_xer_, p_reader, p_flavor"
2863 " | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0));\n"
2864 " }\n"
2865 , sdef->elements[i].name, sdef->elements[i].typegen);
2866 } /* next field */
2867
2868 if (sdef->xerUseNilPossible) {
2869 src = mputstr(src, " } // use_nil\n");
2870 }
2871
2872 if (sdef->xerEmbedValuesPossible) {
2873 /* read and store embedValues text if present */
2874 src = mputprintf(src,
2875 " if ((p_td.xer_bits & EMBED_VALUES) && (p_reader.NodeType()==XML_READER_TYPE_TEXT)) {\n"
2876 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
2877 " field_%s[%lu] = emb_ustr;\n"
2878 " }\n"
2879 , sdef->elements[0].name, (unsigned long)(i-(start_at+num_attributes)));
2880 }
2881
2882 if (sdef->xerEmbedValuesPossible) {
2883 size_t op;
2884 src = mputprintf(src,
2885 /* Set the embed-values member to the correct nr of strings */
2886 " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n"
2887 " int exp_embed = %lu;\n"
2888 , (unsigned long)max_embed
2889 );
2890
2891 if (sdef->xerUseNilPossible) {
2892 src = mputstr(src,
2893 " if (nil_attribute) exp_embed = 0;\n"
2894 " else {");
2895 }
2896
2897 for (op = 0; op < sdef->nElements; ++op) {
2898 if (sdef->elements[op].isOptional && !sdef->elements[op].xerAttribute) {
2899 src = mputprintf(src,
2900 " if (!field_%s.ispresent()) --exp_embed;\n"
2901 , sdef->elements[op].name
2902 );
2903 }
2904 }
2905
2906 if (sdef->xerUseNilPossible) src = mputstr(src, " }\n");
2907
2908 src = mputprintf(src,
2909 " field_%s.set_size(exp_embed);//normal\n"
2910 " %s::of_type empty_string(\"\");\n"
2911 " for (int j_j=0; j_j<exp_embed; ++j_j) {\n"
2912 " if (!field_%s[j_j].is_bound()) field_%s[j_j] = empty_string;\n"
2913 " }\n"
2914 " }"
2915 , sdef->elements[0].name
2916 , sdef->elements[0].type
2917 , sdef->elements[0].name
2918 , sdef->elements[0].name
2919 );
2920 }
2921
2922 if (sdef->xerUseOrderPossible) {
2923 src = mputstr(src, " } // uo\n");
2924 }
2925
2926 if (sdef->xerUseQName) {
2927 src = mputstr(src, " } // qn\n");
2928 }
2929
2930 src = mputstr(src,
2931 " } // errorcontext\n" /* End scope for error context objects */
2932 " if (!omit_tag) {\n"
2933 " int current_depth;\n"
2934 " for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
2935 " type = p_reader.NodeType();\n"
2936 " if ((current_depth = p_reader.Depth()) > xml_depth) {\n"
2937 " if (XML_READER_TYPE_ELEMENT == type) {\n"
2938 /* An element deeper than our start tag has not been processed */
2939 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG,\n"
2940 " \"Unprocessed XML tag `%s'\", (const char *)p_reader.Name());\n"
2941 " }\n"
2942 " continue;\n"
2943 " }\n"
2944 " else if (current_depth == xml_depth) {\n"
2945 " if (XML_READER_TYPE_ELEMENT == type) {\n"
2946 " verify_name(p_reader, p_td, e_xer);\n"
2947 " if (p_reader.IsEmptyElement()) {\n"
2948 " p_reader.Read();\n" /* advance one more time */
2949 " break;\n"
2950 " }\n"
2951 " }\n"
2952 " else if (XML_READER_TYPE_END_ELEMENT == type) {\n"
2953 " verify_end(p_reader, p_td, xml_depth, e_xer);\n"
2954 " rd_ok = p_reader.Read();\n"
2955 " break;\n"
2956 " }\n"
2957 " }\n"
2958 " else break;" /* depth is less, we are in trouble... */
2959 " }\n"
2960 " }\n"
2961 " return 1;\n}\n\n");
2962
2963 *pdef = def;
2964 *psrc = src;
2965 }
2966
2967 void defRecordClass1(const struct_def *sdef, output_struct *output)
2968 {
2969 size_t i;
2970 size_t mandatory_fields_count;
2971 const char *name = sdef->name, *dispname = sdef->dispname;
2972 const char* kind_str = sdef->kind == SET ? "set" : "record";
2973 char *def = NULL, *src = NULL;
2974 boolean ber_needed = sdef->isASN1 && enable_ber();
2975 boolean raw_needed = sdef->hasRaw && enable_raw();
2976 boolean text_needed = sdef->hasText && enable_text();
2977 boolean xer_needed = sdef->hasXer && enable_xer();
2978 boolean json_needed = sdef->hasJson && enable_json();
2979
2980 /* class declaration code */
2981 output->header.class_decls = mputprintf(output->header.class_decls,
2982 "class %s;\n", name);
2983
2984 if (sdef->nElements <= 0) {
2985 defEmptyRecordClass(sdef, output);
2986 return;
2987 }
2988
2989 /* class definition and source code */
2990 if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) {
2991 def=mputprintf
2992 (def,
2993 #ifndef NDEBUG
2994 "// written by %s in " __FILE__ " at line %d\n"
2995 #endif
2996 "class %s : public Base_Type {\n"
2997 #ifndef NDEBUG
2998 , __FUNCTION__, __LINE__
2999 #endif
3000 , name);
3001 } else {
3002 def=mputprintf(def, "class %s {\n", name);
3003 }
3004
3005 /* fields */
3006 for (i = 0; i < sdef->nElements; i++) {
3007 if(sdef->elements[i].isOptional)
3008 def = mputprintf(def, " OPTIONAL<%s> field_%s;\n",
3009 sdef->elements[i].type,
3010 sdef->elements[i].name);
3011 else
3012 def = mputprintf(def, " %s field_%s;\n",
3013 sdef->elements[i].type, sdef->elements[i].name);
3014 }
3015
3016 /* bound flag */
3017 def = mputstr(def, " boolean bound_flag;\n");
3018
3019 /* default constructor */
3020 def = mputprintf(def, "public:\n"
3021 " %s();\n", name);
3022 src = mputprintf(src, "%s::%s()\n"
3023 "{\n"
3024 " bound_flag = FALSE;\n"
3025 "}\n\n", name, name);
3026
3027 /* constructor by fields */
3028 def = mputprintf(def, " %s(", name);
3029 src = mputprintf(src, "%s::%s(", name, name);
3030
3031 for (i = 0; i < sdef->nElements; i++) {
3032 char *tmp = NULL;
3033 if (i > 0) tmp = mputstr(tmp, ",\n ");
3034 if (sdef->elements[i].isOptional)
3035 tmp = mputprintf
3036 (tmp,
3037 "const OPTIONAL<%s>& par_%s",
3038 sdef->elements[i].type, sdef->elements[i].name);
3039 else
3040 tmp = mputprintf
3041 (tmp,
3042 "const %s& par_%s",
3043 sdef->elements[i].type, sdef->elements[i].name);
3044 def = mputstr(def, tmp);
3045 src = mputstr(src, tmp);
3046 Free(tmp);
3047 }
3048 def = mputstr(def, ");\n");
3049 src = mputstr(src, ")\n"
3050 " : ");
3051 for (i = 0; i < sdef->nElements; i++) {
3052 if (i > 0) src = mputstr(src, ",\n");
3053 src = mputprintf(src, " field_%s(par_%s)", sdef->elements[i].name,
3054 sdef->elements[i].name);
3055 }
3056 src = mputstr(src, "\n"
3057 "{\n"
3058 " bound_flag = TRUE;\n"
3059 "}\n\n");
3060
3061 /* copy constructor */
3062 def = mputprintf(def, " %s(const %s& other_value);\n", name, name);
3063 src = mputprintf(src, "%s::%s(const %s& other_value)\n"
3064 "{\n"
3065 "if(!other_value.is_bound()) "
3066 "TTCN_error(\"Copying an unbound value of type %s.\");\n"
3067 "bound_flag = TRUE;\n",
3068 name, name, name, dispname);
3069 for (i = 0; i < sdef->nElements; i++) {
3070 src = mputprintf(src,
3071 "if (other_value.%s().is_bound()) field_%s = other_value.%s();\n"
3072 "else field_%s.clean_up();\n",
3073 sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name,
3074 sdef->elements[i].name);
3075 }
3076 src = mputstr(src, "}\n\n");
3077
3078 /* not a component */
3079 def = mputstr(def, " inline boolean is_component() { return FALSE; }\n");
3080
3081 /* clean_up */
3082 def = mputstr(def, " void clean_up();\n");
3083 src = mputprintf(src, "void %s::clean_up()\n"
3084 "{\n", name);
3085 for (i = 0; i < sdef->nElements; i++) {
3086 src = mputprintf(src,
3087 "field_%s.clean_up();\n", sdef->elements[i].name);
3088 }
3089 src = mputstr(src,
3090 "bound_flag = FALSE;\n"
3091 "}\n\n");
3092
3093 /* = operator */
3094 def = mputprintf(def, " %s& operator=(const %s& other_value);\n", name, name);
3095 src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n"
3096 "{\n"
3097 "if (this != &other_value) {\n"
3098 " if(!other_value.is_bound()) "
3099 "TTCN_error(\"Assignment of an unbound value of type %s.\");\n"
3100 " bound_flag = TRUE;\n",
3101 name, name, name, dispname);
3102 for (i = 0; i < sdef->nElements; i++) {
3103 src = mputprintf(src,
3104 " if (other_value.%s().is_bound()) field_%s = other_value.%s();\n"
3105 " else field_%s.clean_up();\n",
3106 sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name,
3107 sdef->elements[i].name);
3108 }
3109 src = mputstr(src,
3110 "}\n"
3111 "return *this;\n"
3112 "}\n\n");
3113
3114 /* == operator */
3115 def = mputprintf(def, " boolean operator==(const %s& other_value) "
3116 "const;\n", name);
3117 src = mputprintf(src,
3118 "boolean %s::operator==(const %s& other_value) const\n"
3119 "{\n"
3120 "if (!is_bound() && !other_value.is_bound()) return TRUE;\n"
3121 "return ", name, name);
3122 for (i = 0; i < sdef->nElements; i++) {
3123 if (i > 0) src = mputstr(src, "\n && ");
3124 src = mputprintf(src, "field_%s==other_value.field_%s",
3125 sdef->elements[i].name, sdef->elements[i].name);
3126 }
3127 src = mputstr(src, ";\n}\n\n");
3128
3129 /* != and () operator */
3130 def = mputprintf(def,
3131 " inline boolean operator!=(const %s& other_value) const\n"
3132 " { return !(*this == other_value); }\n\n", name);
3133
3134 /* is_bound */
3135 def = mputprintf(def,
3136 " boolean is_bound() const;\n\n");
3137 src = mputprintf(src,
3138 "boolean %s::is_bound() const\n"
3139 "{\n"
3140 "if (bound_flag) return TRUE;\n", name);
3141 for(i=0; i < sdef->nElements; i++) {
3142 if(sdef->elements[i].isOptional) {
3143 src = mputprintf(src,
3144 "if(OPTIONAL_OMIT == field_%s.get_selection() || field_%s.is_bound()) return TRUE;\n",
3145 sdef->elements[i].name, sdef->elements[i].name);
3146 } else {
3147 src = mputprintf(src,
3148 "if(field_%s.is_bound()) return TRUE;\n",
3149 sdef->elements[i].name);
3150 }
3151 }
3152 src = mputprintf(src,
3153 "return FALSE;\n"
3154 "}\n");
3155
3156 /* is_present */
3157 def = mputstr(def,
3158 "inline boolean is_present() const { return is_bound(); }\n");
3159
3160 /* is_value */
3161 def = mputprintf(def,
3162 " boolean is_value() const;\n\n");
3163 src = mputprintf(src,
3164 "boolean %s::is_value() const\n"
3165 "{\n"
3166 "if (!is_bound()) return FALSE;\n", name);
3167 for(i=0; i < sdef->nElements; i++) {
3168 if(sdef->elements[i].isOptional) {
3169 src = mputprintf(src,
3170 "if(OPTIONAL_OMIT != field_%s.get_selection() && !field_%s.is_value()) return FALSE;\n",
3171 sdef->elements[i].name, sdef->elements[i].name);
3172 } else {
3173 src = mputprintf(src,
3174 "if(!field_%s.is_value()) return FALSE;\n",
3175 sdef->elements[i].name);
3176 }
3177 }
3178 src = mputprintf(src,
3179 "return TRUE;\n}\n");
3180
3181 /* field accessor methods */
3182 for (i = 0; i < sdef->nElements; i++) {
3183 if(sdef->elements[i].isOptional)
3184 def = mputprintf
3185 (def,
3186 " inline OPTIONAL<%s>& %s()\n"
3187 " {return field_%s;}\n"
3188 " inline const OPTIONAL<%s>& %s() const\n"
3189 " {return field_%s;}\n",
3190 sdef->elements[i].type, sdef->elements[i].name,
3191 sdef->elements[i].name,
3192 sdef->elements[i].type, sdef->elements[i].name,
3193 sdef->elements[i].name);
3194 else def = mputprintf
3195 (def,
3196 " inline %s& %s()\n"
3197 " {return field_%s;}\n"
3198 " inline const %s& %s() const\n"
3199 " {return field_%s;}\n",
3200 sdef->elements[i].type, sdef->elements[i].name,
3201 sdef->elements[i].name, sdef->elements[i].type,
3202 sdef->elements[i].name, sdef->elements[i].name);
3203
3204 }
3205
3206 /* sizeof operation */
3207 mandatory_fields_count = 0;
3208 for (i = 0; i < sdef->nElements; i++)
3209 if (!sdef->elements[i].isOptional) mandatory_fields_count++;
3210
3211 def = mputstr(def, " int size_of() const;\n");
3212 src = mputprintf(src,
3213 "int %s::size_of() const\n"
3214 "{\n"
3215 " if (!is_bound()) "
3216 "TTCN_error(\"Calculating the size of an unbound record/set value of type %s\");\n"
3217 , name, dispname);
3218 if (sdef->nElements == mandatory_fields_count) {
3219 src = mputprintf(src, " return %lu;\n", (unsigned long) mandatory_fields_count);
3220 }
3221 else {
3222 src = mputprintf(src, " int ret_val = %lu;\n",
3223 (unsigned long) mandatory_fields_count);
3224 for (i = 0; i < sdef->nElements; i++)
3225 if (sdef->elements[i].isOptional)
3226 src = mputprintf(src,
3227 " if (field_%s.ispresent()) ret_val++;\n",
3228 sdef->elements[i].name);
3229 src = mputstr(src, " return ret_val;\n");
3230 }
3231 src = mputstr(src, "}\n\n");
3232
3233 /* log function */
3234 def = mputstr(def, " void log() const;\n");
3235 src = mputprintf(src,
3236 "void %s::log() const\n{\n"
3237 "if (!is_bound()) {\n"
3238 "TTCN_Logger::log_event_unbound();\n"
3239 "return;\n"
3240 "}\n", name);
3241 for (i = 0; i < sdef->nElements; i++) {
3242 src = mputstr(src, "TTCN_Logger::log_event_str(\"");
3243 if (i == 0) src = mputc(src, '{');
3244 else src = mputc(src, ',');
3245 src = mputprintf(src, " %s := \");\n"
3246 "field_%s.log();\n",
3247 sdef->elements[i].dispname, sdef->elements[i].name);
3248 }
3249 src = mputstr(src, "TTCN_Logger::log_event_str(\" }\");\n}\n\n");
3250
3251 /* set param function */
3252 def = mputstr(def, " void set_param(Module_Param& param);\n");
3253 src = mputprintf
3254 (src,
3255 "void %s::set_param(Module_Param& param)\n{\n"
3256 " bound_flag = TRUE;\n"
3257 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
3258 " param.get_id()->next_name()) {\n"
3259 // Haven't reached the end of the module parameter name
3260 // => the name refers to one of the fields, not to the whole record
3261 " char* param_field = param.get_id()->get_current_name();\n"
3262 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
3263 " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n"
3264 " \" name for %s type `%s'\");\n"
3265 " }\n"
3266 " ", name, kind_str, dispname);
3267 for (i = 0; i < sdef->nElements; i++) {
3268 src = mputprintf(src,
3269 "if (strcmp(\"%s\", param_field) == 0) {\n"
3270 " %s().set_param(param);\n"
3271 " return;\n"
3272 " } else ",
3273 sdef->elements[i].dispname, sdef->elements[i].name);
3274 }
3275 src = mputprintf(src,
3276 "param.error(\"Field `%%s' not found in %s type `%s'\", param_field);\n"
3277 " }\n"
3278 " param.basic_check(Module_Param::BC_VALUE, \"%s value\");\n"
3279 " switch (param.get_type()) {\n"
3280 " case Module_Param::MP_Value_List:\n"
3281 " if (%lu<param.get_size()) {\n"
3282 " param.error(\"%s value of type %s has %lu fields but list value has %%d fields\", (int)param.get_size());\n"
3283 " }\n",
3284 kind_str, dispname, kind_str, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements);
3285
3286 for (i = 0; i < sdef->nElements; ++i) {
3287 src = mputprintf(src,
3288 " if (param.get_size()>%lu && param.get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*param.get_elem(%lu));\n",
3289 (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i);
3290 }
3291 src = mputstr(src,
3292 " break;\n"
3293 " case Module_Param::MP_Assignment_List: {\n"
3294 " Vector<bool> value_used(param.get_size());\n"
3295 " value_used.resize(param.get_size(), false);\n");
3296 for (i = 0; i < sdef->nElements; ++i) {
3297 src = mputprintf(src,
3298 " for (size_t val_idx=0; val_idx<param.get_size(); val_idx++) {\n"
3299 " Module_Param* const curr_param = param.get_elem(val_idx);\n"
3300 " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n"
3301 " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n"
3302 " %s().set_param(*curr_param);\n"
3303 " }\n"
3304 " value_used[val_idx]=true;\n"
3305 " }\n"
3306 " }\n"
3307 , sdef->elements[i].dispname, sdef->elements[i].name);
3308 }
3309 src = mputprintf(src,
3310 " for (size_t val_idx=0; val_idx<param.get_size(); val_idx++) if (!value_used[val_idx]) {\n"
3311 " param.get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", param.get_elem(val_idx)->get_id()->get_name());\n"
3312 " break;\n"
3313 " }\n"
3314 " } break;\n"
3315 " default:\n"
3316 " param.type_error(\"%s value\", \"%s\");\n"
3317 " }\n"
3318 "}\n\n", dispname, kind_str, dispname);
3319
3320 /* set implicit omit function, recursive */
3321 def = mputstr(def, " void set_implicit_omit();\n");
3322 src = mputprintf(src, "void %s::set_implicit_omit()\n{\n", name);
3323 for (i = 0; i < sdef->nElements; i++) {
3324 if (sdef->elements[i].isOptional) {
3325 src = mputprintf(src,
3326 "if (!%s().is_bound()) %s() = OMIT_VALUE;\n"
3327 "else %s().set_implicit_omit();\n",
3328 sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name);
3329 } else {
3330 src = mputprintf(src,
3331 "if (%s().is_bound()) %s().set_implicit_omit();\n",
3332 sdef->elements[i].name, sdef->elements[i].name);
3333 }
3334 }
3335 src = mputstr(src, "}\n\n");
3336
3337 /* text encoder function */
3338 def = mputstr(def, " void encode_text(Text_Buf& text_buf) const;\n");
3339 src = mputprintf(src,
3340 "void %s::encode_text(Text_Buf& text_buf) const\n{\n"
3341 "if (!is_bound()) "
3342 "TTCN_error(\"Text encoder: Encoding an unbound record/set value of type %s.\");\n"
3343 , name, dispname);
3344 for (i = 0; i < sdef->nElements; i++) {
3345 src = mputprintf(src, "field_%s.encode_text(text_buf);\n",
3346 sdef->elements[i].name);
3347 }
3348 src = mputstr(src, "}\n\n");
3349
3350 /* text decoder function */
3351 def = mputstr(def, " void decode_text(Text_Buf& text_buf);\n");
3352 src = mputprintf(src,
3353 "void %s::decode_text(Text_Buf& text_buf)\n{\n"
3354 "bound_flag = TRUE;\n", name);
3355 for (i = 0; i < sdef->nElements; i++) {
3356 src = mputprintf(src, "field_%s.decode_text(text_buf);\n",
3357 sdef->elements[i].name);
3358 }
3359 src = mputstr(src, "}\n\n");
3360
3361 /* The common "classname::encode()" and "classname::decode()" functions */
3362 if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
3363 def_encdec(name, &def, &src, ber_needed, raw_needed,
3364 text_needed, xer_needed, json_needed, FALSE);
3365
3366 /* BER functions */
3367 if(ber_needed) {
3368 /* BER_encode_TLV() */
3369 src=mputprintf
3370 (src,
3371 "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,"
3372 " unsigned p_coding) const\n"
3373 "{\n"
3374 " if (!is_bound()) TTCN_EncDec_ErrorContext::error"
3375 "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
3376 " BER_chk_descr(p_td);\n"
3377 " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
3378 " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n"
3379 " TTCN_EncDec_ErrorContext ec_1;\n"
3380 , name
3381 );
3382 for(i=0; i<sdef->nElements; i++) {
3383 if(!default_as_optional && sdef->elements[i].isDefault) { /* is DEFAULT */
3384 src=mputprintf
3385 (src,
3386 " if(field_%s!=%s) {\n"
3387 " ec_1.set_msg(\"%s': \");\n"
3388 " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_,"
3389 " p_coding));\n"
3390 " }\n"
3391 , sdef->elements[i].name, sdef->elements[i].defvalname
3392 , sdef->elements[i].dispname
3393 , sdef->elements[i].name, sdef->elements[i].typedescrname
3394 );
3395 }
3396 else { /* is not DEFAULT */
3397 src=mputprintf
3398 (src,
3399 " ec_1.set_msg(\"%s': \");\n"
3400 " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_,"
3401 " p_coding));\n"
3402 , sdef->elements[i].dispname
3403 , sdef->elements[i].name, sdef->elements[i].typedescrname
3404 );
3405 } /* !isDefault */
3406 } /* for i */
3407 if(sdef->kind==SET) {
3408 src=mputstr
3409 (src,
3410 " if(p_coding==BER_ENCODE_DER)\n"
3411 " new_tlv->sort_tlvs_tag();\n"
3412 );
3413 }
3414 src=mputstr
3415 (src,
3416 " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
3417 " return new_tlv;\n"
3418 "}\n"
3419 "\n"
3420 );
3421
3422 /* BER_decode_TLV() */
3423 src=mputprintf
3424 (src,
3425 "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,"
3426 " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n"
3427 "{\n"
3428 " bound_flag = TRUE;\n"
3429 " BER_chk_descr(p_td);\n"
3430 " ASN_BER_TLV_t stripped_tlv;\n"
3431 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
3432 " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n"
3433 " stripped_tlv.chk_constructed_flag(TRUE);\n"
3434 " size_t V_pos=0;\n"
3435 " ASN_BER_TLV_t tmp_tlv;\n"
3436 , name, sdef->dispname
3437 );
3438
3439 if(sdef->kind==RECORD)
3440 { /* SEQUENCE decoding */
3441 src=mputstr
3442 (src,
3443 " boolean tlv_present=FALSE;\n"
3444 " {\n"
3445 " TTCN_EncDec_ErrorContext ec_1(\"Component '\");\n"
3446 " TTCN_EncDec_ErrorContext ec_2;\n"
3447 );
3448 for(i=0; i<sdef->nElements; i++) {
3449 src=mputprintf
3450 (src,
3451 " ec_2.set_msg(\"%s': \");\n"
3452 " if(!tlv_present) tlv_present=BER_decode_constdTLV_next"
3453 "(stripped_tlv, V_pos, L_form, tmp_tlv);\n"
3454 , sdef->elements[i].dispname
3455 );
3456 if(sdef->elements[i].isDefault) { /* is DEFAULT */
3457 src=mputprintf
3458 (src,
3459 " if(!tlv_present || !field_%s.BER_decode_isMyMsg(%s_descr_,"
3460 " tmp_tlv))\n"
3461 " field_%s=%s;\n"
3462 " else {\n"
3463 " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv,"
3464 " L_form);\n"
3465 " tlv_present=FALSE;\n"
3466 " }\n"
3467 , sdef->elements[i].name, sdef->elements[i].typedescrname
3468 , sdef->elements[i].name, sdef->elements[i].defvalname
3469 , sdef->elements[i].name, sdef->elements[i].typedescrname
3470 );
3471 }
3472 else if(sdef->elements[i].isOptional) { /* is OPTIONAL */
3473 src=mputprintf
3474 (src,
3475 " if(!tlv_present) field_%s=OMIT_VALUE;\n"
3476 " else {\n"
3477 " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n"
3478 " if(field_%s.ispresent()) tlv_present=FALSE;\n"
3479 " }\n"
3480 , sdef->elements[i].name
3481 , sdef->elements[i].name, sdef->elements[i].typedescrname
3482 , sdef->elements[i].name
3483 );
3484 }
3485 else { /* is not DEFAULT OPTIONAL */
3486 src=mputprintf
3487 (src,
3488 " if(!tlv_present){\n"
3489 " ec_2.error(TTCN_EncDec::ET_INCOMPL_MSG,\"Invalid or incomplete message was received.\");\n"
3490 " return FALSE;\n"
3491 " }\n"
3492 " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n"
3493 " tlv_present=FALSE;\n"
3494 , sdef->elements[i].name, sdef->elements[i].typedescrname
3495 );
3496 } /* !isDefault */
3497 } /* for i */
3498 src=mputstr
3499 (src,
3500 " }\n"
3501 " BER_decode_constdTLV_end(stripped_tlv, V_pos, L_form, tmp_tlv,"
3502 " tlv_present);\n"
3503 );
3504 } /* SEQUENCE decoding */
3505 else { /* SET decoding */
3506 src=mputprintf
3507 (src,
3508 " const char *fld_name[%lu]={"
3509 , (unsigned long) sdef->nElements
3510 );
3511 for(i=0; i<sdef->nElements; i++)
3512 src=mputprintf
3513 (src,
3514 "%s\"%s\""
3515 , i?", ":""
3516 , sdef->elements[i].dispname
3517 );
3518 /* field indicator:
3519 * 0x01: value arrived
3520 * 0x02: is optional / not used :)
3521 * 0x04: has default / not used :)
3522 */
3523 src=mputprintf
3524 (src,
3525 "};\n"
3526 " unsigned char fld_indctr[%lu]={"
3527 , (unsigned long) sdef->nElements
3528 );
3529 for(i=0; i<sdef->nElements; i++)
3530 src=mputprintf
3531 (src,
3532 "%s0"
3533 , i?", ":""
3534 );
3535 src=mputstr
3536 (src,
3537 "};\n"
3538 " size_t fld_curr;\n"
3539 " while(BER_decode_constdTLV_next(stripped_tlv, V_pos,"
3540 " L_form, tmp_tlv)) {\n"
3541 );
3542 for(i=0; i<sdef->nElements; i++)
3543 src=mputprintf
3544 (src,
3545 " %sif(field_%s.BER_decode_isMyMsg(%s_descr_, tmp_tlv)) {\n"
3546 " fld_curr=%lu;\n"
3547 " TTCN_EncDec_ErrorContext ec_1(\"Component '%%s': \","
3548 " fld_name[%lu]);\n"
3549 " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n"
3550 " }\n"
3551 , i?"else ":""
3552 , sdef->elements[i].name, sdef->elements[i].typedescrname
3553 , (unsigned long) i, (unsigned long) i
3554 , sdef->elements[i].name, sdef->elements[i].typedescrname
3555 );
3556 src=mputprintf
3557 (src,
3558 " else {\n"
3559 " /* ellipsis or error... */\n"
3560 " fld_curr=static_cast<size_t>(-1);\n"
3561 " }\n"
3562 " if(fld_curr!=static_cast<size_t>(-1)) {\n"
3563 " if(fld_indctr[fld_curr])\n"
3564 " ec_0.error(TTCN_EncDec::ET_DEC_DUPFLD, \"Duplicated"
3565 " value for component '%%s'.\", fld_name[fld_curr]);\n"
3566 " fld_indctr[fld_curr]=1;\n"
3567 " }\n" /* if != -1 */
3568 " }\n" /* while */
3569 " for(fld_curr=0; fld_curr<%lu; fld_curr++) {\n"
3570 " if(fld_indctr[fld_curr]) continue;\n"
3571 " switch(fld_curr) {\n"
3572 , (unsigned long) sdef->nElements
3573 );
3574 for(i=0; i<sdef->nElements; i++) {
3575 if(sdef->elements[i].isDefault)
3576 src=mputprintf
3577 (src,
3578 " case %lu:\n"
3579 " field_%s=%s;\n"
3580 " break;\n"
3581 , (unsigned long) i
3582 , sdef->elements[i].name, sdef->elements[i].defvalname
3583 );
3584 else if(sdef->elements[i].isOptional)
3585 src=mputprintf
3586 (src,
3587 " case %lu:\n"
3588 " field_%s=OMIT_VALUE;\n"
3589 " break;\n"
3590 , (unsigned long) i
3591 , sdef->elements[i].name
3592 );
3593 } /* for i */
3594 src=mputstr
3595 (src,
3596 " default:\n"
3597 " ec_0.error(TTCN_EncDec::ET_DEC_MISSFLD, \"Missing"
3598 " value for component '%s'.\", fld_name[fld_curr]);\n"
3599 " }\n" /* switch */
3600 " }\n" /* for fld_curr */
3601 );
3602 } /* SET decoding */
3603
3604 if(sdef->opentype_outermost) {
3605 src=mputstr
3606 (src,
3607 " TTCN_EncDec_ErrorContext ec_1(\"While decoding opentypes: \");\n"
3608 " TTCN_Type_list p_typelist;\n"
3609 " BER_decode_opentypes(p_typelist, L_form);\n"
3610 );
3611 } /* if sdef->opentype_outermost */
3612 src=mputstr
3613 (src,
3614 " return TRUE;\n"
3615 "}\n"
3616 "\n"
3617 );
3618
3619 if(sdef->has_opentypes) {
3620 /* BER_decode_opentypes() */
3621 def=mputstr
3622 (def,
3623 "void BER_decode_opentypes(TTCN_Type_list& p_typelist,"
3624 " unsigned L_form);\n");
3625 src=mputprintf
3626 (src,
3627 "void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist,"
3628 " unsigned L_form)\n"
3629 "{\n"
3630 " bound_flag = TRUE;\n"
3631 " p_typelist.push(this);\n"
3632 " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n"
3633 " TTCN_EncDec_ErrorContext ec_1;\n"
3634 , name
3635 );
3636 for(i=0; i<sdef->nElements; i++) {
3637 src=mputprintf
3638 (src,
3639 " ec_1.set_msg(\"%s': \");\n"
3640 " field_%s.BER_decode_opentypes(p_typelist, L_form);\n"
3641 , sdef->elements[i].dispname
3642 , sdef->elements[i].name
3643 );
3644 } /* for i */
3645 src=mputstr
3646 (src,
3647 " p_typelist.pop();\n"
3648 "}\n"
3649 "\n"
3650 );
3651 } /* if sdef->has_opentypes */
3652
3653 } /* if ber_needed */
3654
3655 if(text_needed){
3656 int man_num=0;
3657 int opt_number=0;
3658 int seof=0;
3659 size_t last_man_index=0;
3660 for(i=0;i<sdef->nElements;i++){
3661 if(sdef->elements[i].isOptional) opt_number++;
3662 else {man_num++;last_man_index=i+1;}
3663 if(sdef->elements[i].of_type) seof++;
3664 }
3665
3666 src=mputprintf(src,
3667 "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td,"
3668 " TTCN_Buffer& p_buf) const{\n"
3669 " if (!is_bound()) TTCN_EncDec_ErrorContext::error"
3670 "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
3671 " bool need_separator=false;\n"
3672 " int encoded_length=0;\n"
3673 " if(p_td.text->begin_encode){\n"
3674 " p_buf.put_cs(*p_td.text->begin_encode);\n"
3675 " encoded_length+=p_td.text->begin_encode->lengthof();\n"
3676 " }\n"
3677 ,name
3678 );
3679
3680 for(i=0;i<sdef->nElements;i++){
3681 if(sdef->elements[i].isOptional){
3682 src=mputprintf(src,
3683 " if(field_%s.ispresent()){\n"
3684 ,sdef->elements[i].name
3685 );
3686 }
3687 src=mputprintf(src,
3688 " if(need_separator && p_td.text->separator_encode){\n"
3689 " p_buf.put_cs(*p_td.text->separator_encode);\n"
3690 " encoded_length+=p_td.text->separator_encode->lengthof();\n"
3691 " }\n"
3692 " encoded_length+=field_%s%s.TEXT_encode(%s_descr_,p_buf);\n"
3693 " need_separator=true;\n"
3694 ,sdef->elements[i].name
3695 ,sdef->elements[i].isOptional?"()":"",sdef->elements[i].typedescrname
3696 );
3697 if(sdef->elements[i].isOptional){
3698 src=mputstr(src,
3699 " }\n"
3700 );
3701 }
3702 }
3703
3704 src=mputstr(src,
3705 " if(p_td.text->end_encode){\n"
3706 " p_buf.put_cs(*p_td.text->end_encode);\n"
3707 " encoded_length+=p_td.text->end_encode->lengthof();\n"
3708 " }\n"
3709 " return encoded_length;\n"
3710 "}\n"
3711 );
3712
3713 if(sdef->kind==SET){ /* set decoder start*/
3714 src = mputprintf(src,
3715 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
3716 " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n"
3717 " bound_flag = TRUE;\n"
3718 " int decoded_length=0;\n"
3719 " int decoded_field_length=0;\n"
3720 " size_t pos=p_buf.get_pos();\n"
3721 " boolean sep_found=FALSE;\n"
3722 " int ml=0;\n"
3723 " int sep_length=0;\n"
3724 " int mand_field_num=%d;\n"
3725 " int opt_field_num=%d;\n"
3726 " int loop_detector=1;\n"
3727 " int last_field_num=-1;\n"
3728 " int field_map[%lu];\n"
3729 " memset(field_map, 0, sizeof(field_map));\n"
3730 " if(p_td.text->begin_decode){\n"
3731 " int tl;\n"
3732 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
3733 " if(no_err)return -1;\n"
3734 " TTCN_EncDec_ErrorContext::error\n"
3735 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
3736 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
3737 ", p_td.name);\n"
3738 " return 0;\n"
3739 " }\n"
3740 " decoded_length+=tl;\n"
3741 " p_buf.increase_pos(tl);\n"
3742 " }\n"
3743 " if(p_td.text->end_decode){\n"
3744 " limit.add_token(p_td.text->end_decode);\n"
3745 " ml++;\n"
3746 " }\n"
3747 " if(p_td.text->separator_decode){\n"
3748 " limit.add_token(p_td.text->separator_decode);\n"
3749 " ml++;\n"
3750 " }\n"
3751 ,name,man_num,opt_number,(unsigned long) sdef->nElements
3752 );
3753
3754 if(seof){
3755 int first=0;
3756 src=mputstr(src,
3757 " int has_repeatable=0;\n"
3758 " if("
3759 );
3760 for(i=0;i<sdef->nElements;i++){
3761 if(sdef->elements[i].of_type){
3762 src=mputprintf(src,
3763 "%s%s_descr_.text->val.parameters->decoding_params.repeatable"
3764 ,first?" && ":""
3765 ,sdef->elements[i].typedescrname
3766 );
3767 first=1;
3768 }
3769 }
3770 src=mputstr(src,
3771 ") has_repeatable=1;\n"
3772 );
3773
3774 }
3775 for(i=0;i<sdef->nElements;i++){
3776 if(sdef->elements[i].isOptional){
3777 src=mputprintf(src,
3778 " field_%s=OMIT_VALUE;\n"
3779 ,sdef->elements[i].name
3780 );
3781 }
3782 }
3783 src = mputprintf(src,
3784 " while(mand_field_num+opt_field_num%s){\n"
3785 " loop_detector=1;\n"
3786 " while(TRUE){\n"
3787 ,seof?"+has_repeatable":""
3788 );
3789
3790 for(i=0;i<sdef->nElements;i++){
3791 if(sdef->elements[i].of_type){
3792 src=mputprintf(src,
3793 " if( (%s_descr_.text->val.parameters->decoding_params.repeatable"
3794 " && field_map[%lu]<3) || !field_map[%lu]){\n"
3795 " pos=p_buf.get_pos();\n"
3796 " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf,"
3797 "limit,true,!field_map[%lu]);\n"
3798 " if(decoded_field_length<0){\n"
3799 " p_buf.set_pos(pos);\n"
3800 ,sdef->elements[i].typedescrname,(unsigned long) i,(unsigned long) i
3801 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
3802 ,sdef->elements[i].typedescrname
3803 ,(unsigned long) i
3804 );
3805
3806 if(sdef->elements[i].isOptional){
3807 src=mputprintf(src,
3808 " if(!field_map[%lu]) field_%s=OMIT_VALUE;\n"
3809 ,(unsigned long) i
3810 ,sdef->elements[i].name
3811 );
3812 }
3813 src=mputprintf(src,
3814 " }else{\n"
3815 " loop_detector=0;\n"
3816 " if(!field_map[%lu]) {%s--;field_map[%lu]=1;}\n"
3817 " else field_map[%lu]=2;\n"
3818 " last_field_num=%lu;\n"
3819 " break;\n"
3820 " }\n"
3821 " }\n"
3822 ,(unsigned long) i
3823 ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num"
3824 ,(unsigned long) i,(unsigned long) i,(unsigned long) i
3825 );
3826 } else {
3827 src=mputprintf(src,
3828 " if(!field_map[%lu]){\n"
3829 " pos=p_buf.get_pos();\n"
3830 " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf,"
3831 "limit,true);\n"
3832 " if(decoded_field_length<0){\n"
3833 " p_buf.set_pos(pos);\n"
3834 "%s%s%s"
3835 " }else{\n"
3836 " loop_detector=0;\n"
3837 " field_map[%lu]=1;\n"
3838 " %s--;\n"
3839 " last_field_num=%lu;\n"
3840 " break;\n"
3841 " }\n"
3842 " }\n"
3843 ,(unsigned long) i
3844 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
3845 ,sdef->elements[i].typedescrname
3846 ,sdef->elements[i].isOptional?" field_":""
3847 ,sdef->elements[i].isOptional?sdef->elements[i].name:""
3848 ,sdef->elements[i].isOptional?"=OMIT_VALUE;\n":"",(unsigned long) i
3849 ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num"
3850 ,(unsigned long) i
3851 );
3852 }
3853 }
3854
3855 src = mputstr(src,
3856 " break;\n"
3857 " }\n"
3858 " if(loop_detector) break;\n"
3859 " if(p_td.text->separator_decode){\n"
3860 " int tl;\n"
3861 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
3862 " if(p_td.text->end_decode){\n"
3863 " int tl;\n"
3864 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
3865 " sep_found=FALSE;\n"
3866 " break;\n"
3867 " }\n"
3868 " } else if(limit.has_token(ml)){\n"
3869 " int tl;\n"
3870 " if((tl=limit.match(p_buf,ml))==0){\n"
3871 " sep_found=FALSE;\n"
3872 " break;\n"
3873 " }\n"
3874 " } else break;\n"
3875 " p_buf.set_pos(pos);\n"
3876 " decoded_length-=decoded_field_length;\n"
3877 " field_map[last_field_num]+=2;\n"
3878 );
3879
3880 if(opt_number){
3881 src=mputstr(src,
3882 "switch(last_field_num){\n"
3883 );
3884 for(i=0;i<sdef->nElements;i++){
3885 if(sdef->elements[i].of_type){
3886 if(sdef->elements[i].isOptional){
3887 src=mputprintf(src,
3888 " case %lu:\n"
3889 " if(field_map[%lu]==3){\n"
3890 " field_%s=OMIT_VALUE;\n"
3891 " opt_field_num++;\n"
3892 " }\n"
3893 " break;\n"
3894 ,(unsigned long) i,(unsigned long) i,sdef->elements[i].name
3895 );
3896 } else {
3897 src=mputprintf(src,
3898 " case %lu:\n"
3899 " if(field_map[%lu]==3){\n"
3900 " mand_field_num++;\n"
3901 " }\n"
3902 " break;\n"
3903 ,(unsigned long) i,(unsigned long) i
3904 );
3905 }
3906 } else if(sdef->elements[i].isOptional){
3907 src=mputprintf(src,
3908 " case %lu:\n"
3909 " field_%s=OMIT_VALUE;\n"
3910 " opt_field_num++;\n"
3911 " break;\n"
3912 ,(unsigned long) i,sdef->elements[i].name
3913 );
3914 }
3915 }
3916 src=mputstr(src,
3917 " default:\n"
3918 " mand_field_num++;\n"
3919 " break;\n"
3920 "}\n"
3921 );
3922 }
3923
3924 src = mputprintf(src,
3925 " } else {\n"
3926 " sep_length=tl;\n"
3927 " decoded_length+=tl;\n"
3928 " p_buf.increase_pos(tl);\n"
3929 " for(int a=0;a<%lu;a++) if(field_map[a]>2) field_map[a]-=3;\n"
3930 " sep_found=TRUE;}\n"
3931 " } else if(p_td.text->end_decode){\n"
3932 " int tl;\n"
3933 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
3934 " decoded_length+=tl;\n"
3935 " p_buf.increase_pos(tl);\n"
3936 " limit.remove_tokens(ml);\n"
3937 " if(mand_field_num) return -1;\n"
3938 " return decoded_length;\n"
3939 " }\n"
3940 " } else if(limit.has_token(ml)){\n"
3941 " int tl;\n"
3942 " if((tl=limit.match(p_buf,ml))==0){\n"
3943 " sep_found=FALSE;\n"
3944 " break;\n"
3945 " }\n"
3946 " }\n"
3947 " }\n"
3948 " limit.remove_tokens(ml);\n"
3949 " if(sep_found){\n"
3950 " if(mand_field_num){\n"
3951 " if(no_err)return -1;\n"
3952 " TTCN_EncDec_ErrorContext::error"
3953 "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding '%%s': \","
3954 "p_td.name);\n"
3955 " return decoded_length;\n"
3956 " } else {\n"
3957 " decoded_length-=sep_length;\n"
3958 " p_buf.set_pos(p_buf.get_pos()-sep_length);\n"
3959 " }\n"
3960 " }\n"
3961 " if(p_td.text->end_decode){\n"
3962 " int tl;\n"
3963 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
3964 " if(no_err)return -1;\n"
3965 " TTCN_EncDec_ErrorContext::error"
3966 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
3967 " not found for '%%s': \",(const char*)*(p_td.text->end_decode)"
3968 ",p_td.name);\n"
3969 " return decoded_length;\n"
3970 " }\n"
3971 " decoded_length+=tl;\n"
3972 " p_buf.increase_pos(tl);\n"
3973 " }\n"
3974 " if(mand_field_num) return -1;\n"
3975 " return decoded_length;\n"
3976 "}\n"
3977 ,(unsigned long) sdef->nElements
3978 );
3979 } else { /* record decoder start */
3980 src = mputprintf(src,
3981 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
3982 " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n"
3983 " bound_flag = TRUE;\n"
3984 " int decoded_length=0;\n"
3985 " int decoded_field_length=0;\n"
3986 "%s"
3987 " boolean sep_found=FALSE;\n"
3988 " int sep_length=0;\n"
3989 " int ml=0;\n"
3990 " if(p_td.text->begin_decode){\n"
3991 " int tl;\n"
3992 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
3993 " if(no_err)return -1;\n"
3994 " TTCN_EncDec_ErrorContext::error\n"
3995 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
3996 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
3997 ", p_td.name);\n"
3998 " return 0;\n"
3999 " }\n"
4000 " decoded_length+=tl;\n"
4001 " p_buf.increase_pos(tl);\n"
4002 " }\n"
4003 " if(p_td.text->end_decode){\n"
4004 " limit.add_token(p_td.text->end_decode);\n"
4005 " ml++;\n"
4006 " }\n"
4007 " if(p_td.text->separator_decode){\n"
4008 " limit.add_token(p_td.text->separator_decode);\n"
4009 " ml++;\n"
4010 " }\n"
4011 ,name,opt_number?" size_t pos=p_buf.get_pos();\n":""
4012 );
4013 for(i=0;i<sdef->nElements;i++){
4014 if(sdef->elements[i].isOptional){
4015 src=mputprintf(src,
4016 " field_%s=OMIT_VALUE;\n"
4017 ,sdef->elements[i].name
4018 );
4019 } }
4020 src=mputstr(src,
4021 " while(TRUE){\n"
4022 );
4023 for(i=0;i<sdef->nElements;i++){
4024 if(sdef->elements[i].isOptional){
4025 src=mputstr(src,
4026 " pos=p_buf.get_pos();\n"
4027 );
4028 }
4029 src=mputprintf(src,
4030 " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf"
4031 ",limit,TRUE);\n"
4032 " if(decoded_field_length<0){\n"
4033 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4034 ,sdef->elements[i].typedescrname
4035 );
4036 if(sdef->elements[i].isOptional){
4037 src=mputprintf(src,
4038 " field_%s=OMIT_VALUE;\n"
4039 " p_buf.set_pos(pos);\n"
4040 " } else {\n"
4041 ,sdef->elements[i].name
4042 );
4043 } else {
4044 src=mputprintf(src,
4045 " limit.remove_tokens(ml);\n"
4046 " if(no_err)return -1;\n"
4047 " TTCN_EncDec_ErrorContext::error"
4048 "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding "
4049 "field '%s' for '%%s': \", p_td.name);\n"
4050 " return decoded_length;\n"
4051 " } else {\n"
4052 ,sdef->elements[i].name
4053 );
4054 }
4055 src=mputstr(src,
4056 " decoded_length+=decoded_field_length;\n"
4057 );
4058 if(last_man_index>(i+1)){
4059 src=mputstr(src,
4060 " if(p_td.text->separator_decode){\n"
4061 " int tl;\n"
4062 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
4063 );
4064
4065 if(sdef->elements[i].isOptional){
4066 src=mputprintf(src,
4067 " field_%s=OMIT_VALUE;\n"
4068 " p_buf.set_pos(pos);\n"
4069 " decoded_length-=decoded_field_length;\n"
4070 ,sdef->elements[i].name
4071 );
4072 } else {
4073 src=mputstr(src,
4074 " limit.remove_tokens(ml);\n"
4075 " if(no_err)return -1;\n"
4076 " TTCN_EncDec_ErrorContext::error"
4077 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'"
4078 " not found for '%s': \",(const char*)*(p_td.text->"
4079 "separator_decode),p_td.name);\n"
4080 " return decoded_length;\n"
4081 );
4082 }
4083
4084 src=mputstr(src,
4085 " } else {\n"
4086 " decoded_length+=tl;\n"
4087 " p_buf.increase_pos(tl);\n"
4088 " sep_length=tl;\n"
4089 " sep_found=TRUE;}\n"
4090 " } else sep_found=FALSE;\n"
4091 );
4092 } else if(i==(sdef->nElements-1)){
4093 src=mputstr(src,
4094 " sep_found=FALSE;\n"
4095 );
4096 } else {
4097 src=mputstr(src,
4098 " if(p_td.text->separator_decode){\n"
4099 " int tl;\n"
4100 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
4101 );
4102 if(sdef->elements[i].isOptional){
4103 src=mputprintf(src,
4104 " if(p_td.text->end_decode){\n"
4105 " int tl;\n"
4106 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
4107 " decoded_length+=tl;\n"
4108 " p_buf.increase_pos(tl);\n"
4109 " limit.remove_tokens(ml);\n"
4110 " return decoded_length;\n"
4111 " }\n"
4112 " } else if(limit.has_token(ml)){\n"
4113 " if((tl=limit.match(p_buf,ml))==0){\n"
4114 " sep_found=FALSE;\n"
4115 " break;\n"
4116 " }\n"
4117 " } else break;\n"
4118 " field_%s=OMIT_VALUE;\n"
4119 " p_buf.set_pos(pos);\n"
4120 " decoded_length-=decoded_field_length;\n"
4121 ,sdef->elements[i].name
4122 );
4123 } else {
4124 src=mputstr(src,
4125 " sep_found=FALSE;\n"
4126 " break;\n"
4127 );
4128 }
4129 src=mputstr(src,
4130 " } else {\n"
4131 " decoded_length+=tl;\n"
4132 " p_buf.increase_pos(tl);\n"
4133 " sep_length=tl;\n"
4134 " sep_found=TRUE;}\n"
4135 " } else {\n"
4136 " sep_found=FALSE;\n"
4137 " if(p_td.text->end_decode){\n"
4138 " int tl;\n"
4139 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
4140 " decoded_length+=tl;\n"
4141 " p_buf.increase_pos(tl);\n"
4142 " limit.remove_tokens(ml);\n"
4143 " return decoded_length;\n"
4144 " }\n"
4145 " } else if(limit.has_token(ml)){\n"
4146 " int tl;\n"
4147 " if((tl=limit.match(p_buf,ml))==0){\n"
4148 " sep_found=FALSE;\n"
4149 " break;\n"
4150 " }\n"
4151 " }\n"
4152 " }\n"
4153 );
4154 }
4155 src=mputstr(src,
4156 " }\n"
4157 );
4158 }
4159
4160 src = mputstr(src,
4161 " break;\n"
4162 " }\n"
4163 " limit.remove_tokens(ml);\n"
4164 " if(sep_found){\n"
4165 " p_buf.set_pos(p_buf.get_pos()-sep_length);\n"
4166 " decoded_length-=sep_length;\n"
4167 " }\n"
4168 " if(p_td.text->end_decode){\n"
4169 " int tl;\n"
4170 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
4171 " if(no_err)return -1;\n"
4172 " TTCN_EncDec_ErrorContext::error"
4173 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'"
4174 " not found for '%s': \",(const char*)*(p_td.text->end_decode)"
4175 ",p_td.name);\n"
4176 " return decoded_length;\n"
4177 " }\n"
4178 " decoded_length+=tl;\n"
4179 " p_buf.increase_pos(tl);\n"
4180 " }\n"
4181 " return decoded_length;\n"
4182 "}\n"
4183 );
4184 }
4185 } /* text_needed */
4186
4187 /* RAW functions */
4188 if(raw_needed){
4189 struct raw_option_struct *raw_options;
4190 boolean haslengthto, haspointer, hascrosstag, has_ext_bit;
4191 raw_options = (struct raw_option_struct*)
4192 Malloc(sdef->nElements * sizeof(*raw_options));
4193
4194 set_raw_options(sdef, raw_options, &haslengthto,
4195 &haspointer, &hascrosstag, &has_ext_bit);
4196
4197 src = generate_raw_coding(src, sdef, raw_options, haspointer, hascrosstag,
4198 has_ext_bit);
4199
4200 for (i = 0; i < sdef->nElements; i++) {
4201 Free(raw_options[i].lengthoffield);
4202 Free(raw_options[i].dependent_fields);
4203 }
4204 Free(raw_options);
4205 } /* if raw_needed */
4206
4207 if (xer_needed) gen_xer(sdef, &def, &src);
4208
4209 if (json_needed) {
4210 // JSON encode, RT1
4211 src = mputprintf(src,
4212 "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
4213 "{\n"
4214 " if (!is_bound()) {\n"
4215 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
4216 " \"Encoding an unbound value of type %s.\");\n"
4217 " return -1;\n"
4218 " }\n\n"
4219 " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n"
4220 , name, dispname);
4221 for (i = 0; i < sdef->nElements; ++i) {
4222 if (sdef->elements[i].isOptional && !sdef->elements[i].jsonOmitAsNull) {
4223 src = mputprintf(src,
4224 " if (field_%s.is_present())\n"
4225 , sdef->elements[i].name);
4226 }
4227 src=mputprintf(src,
4228 " {\n"
4229 " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n"
4230 " enc_len += field_%s.JSON_encode(%s_descr_, p_tok);\n"
4231 " }\n\n"
4232 , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname
4233 , sdef->elements[i].name, sdef->elements[i].typedescrname);
4234 }
4235 src = mputstr(src,
4236 " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
4237 " return enc_len;\n"
4238 "}\n\n");
4239
4240 // JSON decode, RT1
4241 src = mputprintf(src,
4242 "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
4243 "{\n"
4244 " json_token_t j_token = JSON_TOKEN_NONE;\n"
4245 " int dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
4246 " if (JSON_TOKEN_ERROR == j_token) {\n"
4247 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
4248 " return JSON_ERROR_FATAL;\n"
4249 " }\n"
4250 " else if (JSON_TOKEN_OBJECT_START != j_token) {\n"
4251 " return JSON_ERROR_INVALID_TOKEN;\n"
4252 " }\n"
4253 " bound_flag = TRUE;\n\n"
4254 // Read name - value token pairs until we reach some other token
4255 " while (true) {\n"
4256 " char* fld_name = 0;\n"
4257 " size_t name_len = 0;\n"
4258 " size_t buf_pos = p_tok.get_buf_pos();\n"
4259 " dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n"
4260 " if (JSON_TOKEN_ERROR == j_token) {\n"
4261 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n"
4262 " return JSON_ERROR_FATAL;\n"
4263 " }\n"
4264 // undo the last action on the buffer
4265 " else if (JSON_TOKEN_NAME != j_token) {\n"
4266 " p_tok.set_buf_pos(buf_pos);\n"
4267 " break;\n"
4268 " }\n"
4269 " else {\n "
4270 , name);
4271 for (i = 0; i < sdef->nElements; ++i) {
4272 src = mputprintf(src,
4273 // check field name
4274 "if (%d == name_len && 0 == strncmp(fld_name, \"%s\", name_len)) {\n"
4275 " int ret_val = field_%s.JSON_decode(%s_descr_, p_tok, p_silent);\n"
4276 " if (0 > ret_val) {\n"
4277 " if (JSON_ERROR_INVALID_TOKEN) {\n"
4278 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n"
4279 " }\n"
4280 " return JSON_ERROR_FATAL;\n"
4281 " }\n"
4282 " dec_len += ret_val;\n"
4283 " } else "
4284 , (int)strlen(sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname)
4285 , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname
4286 , sdef->elements[i].name, sdef->elements[i].typedescrname
4287 , sdef->elements[i].dispname);
4288 }
4289 src = mputstr(src,
4290 "{\n"
4291 // invalid field name
4292 " char* fld_name2 = mcopystrn(fld_name, name_len);\n"
4293 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, fld_name2);\n"
4294 // if this is set to a warning, skip the value of the field
4295 " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
4296 " if (JSON_TOKEN_NUMBER != j_token && JSON_TOKEN_STRING != j_token &&\n"
4297 " JSON_TOKEN_LITERAL_TRUE != j_token && JSON_TOKEN_LITERAL_FALSE != j_token &&\n"
4298 " JSON_TOKEN_LITERAL_NULL != j_token) {\n"
4299 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name2);\n"
4300 " Free(fld_name2);\n"
4301 " return JSON_ERROR_FATAL;\n"
4302 " }\n"
4303 " Free(fld_name2);\n"
4304 " }\n"
4305 " }\n"
4306 " }\n\n"
4307 " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
4308 " if (JSON_TOKEN_OBJECT_END != j_token) {\n"
4309 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_OBJECT_END_TOKEN_ERROR, \"\");\n"
4310 " return JSON_ERROR_FATAL;\n"
4311 " }\n\n");
4312 // Check if every field has been set
4313 for (i = 0; i < sdef->nElements; ++i) {
4314 src = mputprintf(src,
4315 " if (!field_%s.is_bound()) {\n"
4316 , sdef->elements[i].name);
4317 if (sdef->elements[i].jsonDefaultValue) {
4318 src = mputprintf(src,
4319 " field_%s.JSON_decode(%s_descr_, DUMMY_BUFFER, p_silent);\n"
4320 , sdef->elements[i].name, sdef->elements[i].typedescrname);
4321 }
4322 else if (sdef->elements[i].isOptional) {
4323 src = mputprintf(src,
4324 " field_%s = OMIT_VALUE;\n"
4325 , sdef->elements[i].name);
4326 } else {
4327 src = mputprintf(src,
4328 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_MISSING_FIELD_ERROR, \"%s\");\n"
4329 " return JSON_ERROR_FATAL;\n"
4330 , sdef->elements[i].dispname);
4331 }
4332 src = mputstr(src,
4333 " }\n");
4334 }
4335 src = mputstr(src,
4336 "\n return dec_len;\n"
4337 "}\n\n");
4338 }
4339
4340 /* end of class definition */
4341 def = mputstr(def, "};\n\n");
4342
4343 output->header.class_defs = mputstr(output->header.class_defs, def);
4344 Free(def);
4345
4346 output->source.methods = mputstr(output->source.methods, src);
4347 Free(src);
4348 }
4349
4350
4351 static char *genRawFieldDecodeLimit(char *src, const struct_def *sdef,
4352 int i, const struct raw_option_struct *raw_options)
4353 {
4354 /* number of arguments passed to min_of_ints() */
4355 int nof_args = 1;
4356 int j;
4357 for (j = 0; j < raw_options[i].lengthof; j++) {
4358 int field_index = raw_options[i].lengthoffield[j];
4359 if (i > field_index && sdef->elements[field_index].raw.unit!=-1)
4360 nof_args++;
4361 }
4362 if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[
4363 raw_options[i].extbitgroup-1].ext_bit != XDEFNO) nof_args++;
4364 if (nof_args > 1) {
4365 src = mputprintf(src, "min_of_ints(%d, limit", nof_args);
4366 for (j = 0; j < raw_options[i].lengthof; j++) {
4367 int field_index = raw_options[i].lengthoffield[j];
4368 if (i > field_index && sdef->elements[field_index].raw.unit != -1)
4369 src = mputprintf(src, ", value_of_length_field%d", field_index);
4370 }
4371 if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[
4372 raw_options[i].extbitgroup-1].ext_bit != XDEFNO)
4373 src = mputstr(src, ", group_limit");
4374 src = mputc(src, ')');
4375 } else {
4376 src = mputstr(src, "limit");
4377 }
4378 return src;
4379 }
4380
4381 static char *genRawDecodeRecordField(char *src, const struct_def *sdef,
4382 int i, const struct raw_option_struct *raw_options, boolean delayed_decode,
4383 int *prev_ext_group)
4384 {
4385 int a;
4386 if(raw_options[i].ptrbase)
4387 src=mputprintf(src,
4388 " start_pos_of_field%d=p_buf.get_pos_bit();\n"
4389 ,i
4390 );
4391 if (*prev_ext_group != raw_options[i].extbitgroup) {
4392 *prev_ext_group = raw_options[i].extbitgroup;
4393 if(prev_ext_group &&
4394 sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){
4395 if(raw_options[i].pointerof) /* pointed field */
4396 src=mputprintf(src,
4397 " {size_t old_pos=p_buf.get_pos_bit();\n"
4398 " if(start_of_field%d!=-1 && start_pos_of_field%d!=-1){\n"
4399 " start_of_field%d=start_pos_of_field%d"
4400 "+(int)field_%s%s*%d+%d;\n"
4401 " p_buf.set_pos_bit(start_of_field%d);\n"
4402 " limit=end_of_available_data-start_of_field%d;\n"
4403 ,i
4404 ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase
4405 ,i
4406 ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase
4407 ,sdef->elements[raw_options[i].pointerof-1].name
4408 ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":""
4409 ,sdef->elements[raw_options[i].pointerof-1].raw.unit
4410 ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset
4411 ,i,i
4412 );
4413 src=mputprintf(src,
4414 " {\n"
4415 " cbyte* data=p_buf.get_read_data();\n"
4416 " int count=1;\n"
4417 " int rot=local_top_order==ORDER_LSB?0:7;\n"
4418 " while(((data[count-1]>>rot)&0x01)==%d && count*8<"
4419 "(int)limit) count++;\n"
4420 " if(limit) group_limit=count*8;\n"
4421 " }\n"
4422 ,sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit==
4423 XDEFYES?0:1
4424 );
4425 if(raw_options[i].pointerof) /* pointed field */
4426 src=mputstr(src,
4427 " } else group_limit=0;\n"
4428 " p_buf.set_pos_bit(old_pos);\n"
4429 " limit=end_of_available_data-old_pos;}\n"
4430 );
4431 }
4432 }
4433 if(sdef->elements[i].hasRaw && /* check the crosstag */
4434 sdef->elements[i].raw.crosstaglist.nElements){
4435 /* field index of the otherwise rule */
4436 int other = -1;
4437 boolean first_value = TRUE;
4438 int j;
4439 for (j = 0; j < sdef->elements[i].raw.crosstaglist.nElements; j++) {
4440 rawAST_coding_taglist* cur_choice =
4441 sdef->elements[i].raw.crosstaglist.list + j;
4442 if (cur_choice->nElements > 0) {
4443 /* this is a normal rule */
4444 if (first_value) {
4445 src = mputstr(src, " if (");
4446 first_value = FALSE;
4447 } else src = mputstr(src, " else if (");
4448 src = genRawFieldChecker(src, cur_choice, TRUE);
4449 /* set selected_field in the if's body */
4450 src = mputprintf(src, ") selected_field = %d;\n",
4451 cur_choice->fieldnum);
4452 } else {
4453 /* this is an otherwise rule */
4454 other = cur_choice->fieldnum;
4455 }
4456 }
4457 /* set selected_field to the field index of the otherwise rule or -1 */
4458 src = mputprintf(src, " else selected_field = %d;\n", other);
4459 }
4460 /* check the presence of optional field*/
4461 if(sdef->elements[i].isOptional){
4462 /* check if enough bits to decode the field*/
4463 src = mputstr(src, " if (limit > 0");
4464 for (a = 0; a < raw_options[i].lengthof; a++){
4465 int field_index = raw_options[i].lengthoffield[a];
4466 if (i > field_index) src = mputprintf(src,
4467 " && value_of_length_field%d > 0", field_index);
4468 }
4469 if (raw_options[i].extbitgroup &&
4470 sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){
4471 src = mputstr(src, " && group_limit > 0");
4472 }
4473 if(raw_options[i].pointerof){ /* valid pointer?*/
4474 src=mputprintf(src,
4475 " && start_of_field%d!=-1 && start_pos_of_field%d!=-1"
4476 ,i,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase
4477 );
4478 }
4479 if(sdef->elements[i].hasRaw &&
4480 sdef->elements[i].raw.presence.nElements)
4481 {
4482 src = mputstr(src, " && ");
4483 if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, '(');
4484 src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, TRUE);
4485 if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, ')');
4486 }
4487 if(sdef->elements[i].hasRaw &&
4488 sdef->elements[i].raw.crosstaglist.nElements)
4489 {
4490 src=mputstr(src,
4491 "&& selected_field!=-1"
4492 );
4493 }
4494 src=mputstr(src,
4495 "){\n"
4496 );
4497 }
4498 if(raw_options[i].pointerof){ /* pointed field */
4499 src=mputprintf(src,
4500 " start_of_field%d=start_pos_of_field%d"
4501 "+(int)field_%s%s*%d+%d;\n"
4502 ,i
4503 ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase
4504 ,sdef->elements[raw_options[i].pointerof-1].name
4505 ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":""
4506 ,sdef->elements[raw_options[i].pointerof-1].raw.unit
4507 ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset
4508 );
4509 src=mputprintf(src,
4510 " p_buf.set_pos_bit(start_of_field%d);\n"
4511 " limit=end_of_available_data-start_of_field%d;\n"
4512 ,i,i
4513 );
4514 }
4515 /* decoding of normal field */
4516 if (sdef->elements[i].isOptional) src = mputstr(src,
4517 " size_t fl_start_pos = p_buf.get_pos_bit();\n");
4518 src = mputprintf(src,
4519 " decoded_field_length = field_%s%s.RAW_decode(%s_descr_, p_buf, ",
4520 sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "",
4521 sdef->elements[i].typedescrname);
4522 if (delayed_decode) {
4523 /* the fixed field length is used as limit in case of delayed decoding */
4524 src = mputprintf(src, "%d", sdef->elements[i].raw.length);
4525 } else {
4526 src = genRawFieldDecodeLimit(src, sdef, i, raw_options);
4527 }
4528 src = mputprintf(src, ", local_top_order, %s",
4529 sdef->elements[i].isOptional ? "TRUE" : "no_err");
4530 if (sdef->elements[i].hasRaw &&
4531 sdef->elements[i].raw.crosstaglist.nElements > 0)
4532 src = mputstr(src, ", selected_field");
4533 for (a = 0; a < raw_options[i].lengthof; a++) {
4534 int field_index = raw_options[i].lengthoffield[a];
4535 /* number of elements in 'record of' or 'set of' */
4536 if (sdef->elements[field_index].raw.unit == -1) {
4537 src = mputprintf(src, ", value_of_length_field%d", field_index);
4538 break;
4539 }
4540 }
4541 src = mputstr(src, ");\n");
4542 if (delayed_decode) {
4543 src = mputprintf(src, " if (decoded_field_length != %d) return -1;\n",
4544 sdef->elements[i].raw.length);
4545 } else if (sdef->elements[i].isOptional) {
4546 src = mputprintf(src, " if (decoded_field_length < 1) {\n"
4547 " field_%s = OMIT_VALUE;\n" /* transform errors into omit */
4548 " p_buf.set_pos_bit(fl_start_pos);\n"
4549 " } else {\n", sdef->elements[i].name);
4550 } else {
4551 src = mputstr(src, " if (decoded_field_length < 0) return decoded_field_length;\n");
4552 }
4553 if(raw_options[i].tag_type && sdef->raw.taglist.list[raw_options[i].tag_type-1].nElements){
4554 rawAST_coding_taglist* cur_choice=
4555 sdef->raw.taglist.list+raw_options[i].tag_type-1;
4556 src=mputstr(src,
4557 " if(");
4558 src=genRawFieldChecker(src,cur_choice,FALSE);
4559 src=mputstr(src,
4560 ")");
4561 if(sdef->elements[i].isOptional){
4562 src=mputprintf(src,
4563 "{\n field_%s=OMIT_VALUE;\n"
4564 " p_buf.set_pos_bit(fl_start_pos);\n }\n"
4565 " else {\n"
4566 ,sdef->elements[i].name
4567 );
4568 }else src=mputstr(src, " return -1;\n");
4569 }
4570 if (!delayed_decode) {
4571 src=mputstr(src,
4572 " decoded_length+=decoded_field_length;\n"
4573 " limit-=decoded_field_length;\n"
4574 " last_decoded_pos=bigger(last_decoded_pos, p_buf.get_pos_bit());\n"
4575 );
4576 }
4577 if(raw_options[i].extbitgroup &&
4578 sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){
4579 src=mputstr(src,
4580 "group_limit-=decoded_field_length;\n"
4581 );
4582 }
4583 if(raw_options[i].lengthto){ /* if the field is lengthto store the value*/
4584 if(sdef->elements[i].raw.lengthindex){
4585 if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){
4586 src=mputprintf(src,
4587 " if(field_%s%s.%s().ispresent()){\n"
4588 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4589 ,sdef->elements[i].raw.lengthindex->nthfieldname
4590 );
4591 }
4592 src=mputprintf(src,
4593 " value_of_length_field%d+=(int)field_%s%s.%s%s()*%d;\n"
4594 ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4595 ,sdef->elements[i].raw.lengthindex->nthfieldname
4596 ,sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD?"()":""
4597 ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit
4598 );
4599 if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){
4600 src=mputstr(src,
4601 " }\n"
4602 );
4603 }
4604 }
4605 else if(sdef->elements[i].raw.union_member_num){
4606 int m;
4607 src = mputprintf(src, " switch (field_%s%s.get_selection()) {\n",
4608 sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "");
4609 for (m = 1; m < sdef->elements[i].raw.union_member_num + 1; m++) {
4610 src = mputprintf(src, " case %s%s%s:\n"
4611 " value_of_length_field%d += (int)field_%s%s.%s() * %d;\n"
4612 " break;\n", sdef->elements[i].raw.member_name[0],
4613 "::ALT_",
4614 sdef->elements[i].raw.member_name[m], i, sdef->elements[i].name,
4615 sdef->elements[i].isOptional ? "()" : "",
4616 sdef->elements[i].raw.member_name[m],
4617 sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit);
4618 }
4619 src = mputprintf(src, " default:\n"
4620 " value_of_length_field%d = 0;\n"
4621 " }\n", i);
4622 }
4623 else{
4624 src=mputprintf(src,
4625 " value_of_length_field%d+=(int)field_%s%s*%d;\n"
4626 ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4627 ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit
4628 );
4629 }
4630 }
4631 if(raw_options[i].pointerto){ /* store the start of pointed field*/
4632 src=mputprintf(src,
4633 " start_of_field%d=(int)field_%s%s+%d?1:-1;\n"
4634 ,sdef->elements[i].raw.pointerto
4635 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4636 ,sdef->elements[i].raw.ptroffset
4637 );
4638 }
4639 if (!delayed_decode) {
4640 /* mark the used bits in length area*/
4641 for (a = 0; a < raw_options[i].lengthof; a++) {
4642 int field_index = raw_options[i].lengthoffield[a];
4643 src = mputprintf(src,
4644 " value_of_length_field%d -= decoded_field_length;\n", field_index);
4645 if (i == field_index) src = mputprintf(src,
4646 " if (value_of_length_field%d < 0) return -1;\n", field_index);
4647 }
4648 }
4649 if(sdef->elements[i].isOptional){
4650 src=mputprintf(src,
4651 " }\n }\n%s"
4652 " else field_%s=OMIT_VALUE;\n"
4653 ,raw_options[i].tag_type?" }\n":"",sdef->elements[i].name
4654 );
4655 }
4656 return src;
4657 }
4658
4659 #ifdef __SUNPRO_C
4660 #define SUNPRO_PUBLIC "public:\n"
4661 #define SUNPRO_PRIVATE "private:\n"
4662 #else
4663 #define SUNPRO_PUBLIC
4664 #define SUNPRO_PRIVATE
4665 #endif
4666
4667 void defRecordTemplate1(const struct_def *sdef, output_struct *output)
4668 {
4669 int i;
4670 const char *name = sdef->name, *dispname = sdef->dispname;
4671 const char* kind_str = sdef->kind == SET ? "set" : "record";
4672 char *def = NULL, *src = NULL;
4673
4674 size_t mandatory_fields_count;
4675
4676 /* class declaration */
4677 output->header.class_decls = mputprintf(output->header.class_decls,
4678 "class %s_template;\n", name);
4679
4680 if(sdef->nElements <= 0) {
4681 defEmptyRecordTemplate(name, dispname, output);
4682 return;
4683 }
4684
4685 /* template class definition */
4686 def = mputprintf(def, "class %s_template : public Base_Template {\n", name);
4687
4688 /* data members */
4689 def = mputprintf(def,
4690 SUNPRO_PUBLIC
4691 "struct single_value_struct;\n"
4692 SUNPRO_PRIVATE
4693 "union {\n"
4694 "single_value_struct *single_value;\n"
4695 "struct {\n"
4696 "unsigned int n_values;\n"
4697 "%s_template *list_value;\n"
4698 "} value_list;\n"
4699 "};\n\n", name);
4700 /* the definition of single_value_struct must be put into the source file
4701 * because the types of optional fields may be incomplete in this position
4702 * of header file (e.g. due to type recursion) */
4703 src = mputprintf(src, "struct %s_template::single_value_struct {\n", name);
4704 for (i = 0; i < sdef->nElements; i++) {
4705 src = mputprintf(src, "%s_template field_%s;\n",
4706 sdef->elements[i].type, sdef->elements[i].name);
4707 }
4708 src = mputstr(src, "};\n\n");
4709
4710 /* set_specific function (used in field access members) */
4711 def = mputstr(def, "void set_specific();\n");
4712 src = mputprintf(src, "void %s_template::set_specific()\n"
4713 "{\n"
4714 "if (template_selection != SPECIFIC_VALUE) {\n"
4715 "template_sel old_selection = template_selection;\n"
4716 "clean_up();\n"
4717 "single_value = new single_value_struct;\n"
4718 "set_selection(SPECIFIC_VALUE);\n"
4719 "if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {\n",
4720 name);
4721 for (i = 0; i < sdef->nElements; i++) {
4722 src = mputprintf(src, "single_value->field_%s = %s;\n",
4723 sdef->elements[i].name,
4724 sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE");
4725 }
4726 src = mputstr(src, "}\n"
4727 "}\n"
4728 "}\n\n");
4729
4730 /* copy_value function */
4731 def = mputprintf(def, "void copy_value(const %s& other_value);\n", name);
4732 src = mputprintf(src,
4733 "void %s_template::copy_value(const %s& other_value)\n"
4734 "{\n"
4735 "single_value = new single_value_struct;\n", name, name);
4736 for (i = 0; i < sdef->nElements; i++) {
4737 src = mputprintf(src,
4738 "if (other_value.%s().is_bound()) {\n", sdef->elements[i].name);
4739 if (sdef->elements[i].isOptional) {
4740 /* If the value is present, "reach into" the OPTIONAL with operator()
4741 * and pass the contained object to the template's constructor.
4742 * Else set the template to omit. */
4743 src = mputprintf(src,
4744 " if (other_value.%s().ispresent()) single_value->field_%s = "
4745 "other_value.%s()();\n"
4746 " else single_value->field_%s = OMIT_VALUE;\n",
4747 sdef->elements[i].name, sdef->elements[i].name,
4748 sdef->elements[i].name, sdef->elements[i].name);
4749 } else {
4750 src = mputprintf(src,
4751 " single_value->field_%s = other_value.%s();\n",
4752 sdef->elements[i].name, sdef->elements[i].name);
4753 }
4754 src = mputprintf(src, "} else {\n"
4755 " single_value->field_%s.clean_up();\n"
4756 "}\n", sdef->elements[i].name);
4757 }
4758 src = mputstr(src, "set_selection(SPECIFIC_VALUE);\n"
4759 "}\n\n");
4760
4761 /* copy_template function */
4762 def = mputprintf(def, "void copy_template(const %s_template& "
4763 "other_value);\n\n", name);
4764 src = mputprintf(src,
4765 "void %s_template::copy_template(const %s_template& other_value)\n"
4766 "{\n"
4767 "switch (other_value.template_selection) {\n"
4768 "case SPECIFIC_VALUE:\n", name, name);
4769 src = mputstr(src,
4770 "single_value = new single_value_struct;\n");
4771 for (i = 0; i < sdef->nElements; i++) {
4772 src = mputprintf(src,
4773 "if (UNINITIALIZED_TEMPLATE != other_value.%s().get_selection()) {\n",
4774 sdef->elements[i].name);
4775 src = mputprintf(src,
4776 "single_value->field_%s = other_value.%s();\n",
4777 sdef->elements[i].name, sdef->elements[i].name);
4778 src = mputprintf(src, "} else {\n"
4779 "single_value->field_%s.clean_up();\n"
4780 "}\n", sdef->elements[i].name);
4781 }
4782 src = mputprintf(src,
4783 "case OMIT_VALUE:\n"
4784 "case ANY_VALUE:\n"
4785 "case ANY_OR_OMIT:\n"
4786 "break;\n"
4787 "case VALUE_LIST:\n"
4788 "case COMPLEMENTED_LIST:\n"
4789 "value_list.n_values = other_value.value_list.n_values;\n"
4790 "value_list.list_value = new %s_template[value_list.n_values];\n"
4791 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
4792 "list_count++)\n"
4793 "value_list.list_value[list_count].copy_template("
4794 "other_value.value_list.list_value[list_count]);\n"
4795 "break;\n"
4796 "default:\n"
4797 "TTCN_error(\"Copying an uninitialized/unsupported template of type "
4798 "%s.\");\n"
4799 "break;\n"
4800 "}\n"
4801 "set_selection(other_value);\n"
4802 "}\n\n", name, dispname);
4803
4804 /* default constructor */
4805 def = mputprintf(def, "public:\n"
4806 "%s_template();\n", name);
4807 src = mputprintf(src, "%s_template::%s_template()\n"
4808 "{\n"
4809 "}\n\n", name, name);
4810
4811 /* constructor t1_template(template_sel other_value) */
4812 def = mputprintf(def, "%s_template(template_sel other_value);\n", name);
4813 src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n"
4814 " : Base_Template(other_value)\n"
4815 "{\n"
4816 "check_single_selection(other_value);\n"
4817 "}\n\n", name, name);
4818
4819 /* constructor t1_template(const t1& other_value) */
4820 def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name);
4821 src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n"
4822 "{\n"
4823 "copy_value(other_value);\n"
4824 "}\n\n", name, name, name);
4825
4826 /* constructor t1_template(const OPTIONAL<t1>& other_value) */
4827 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n",
4828 name, name);
4829 src = mputprintf(src,
4830 "%s_template::%s_template(const OPTIONAL<%s>& other_value)\n"
4831 "{\n"
4832 "switch (other_value.get_selection()) {\n"
4833 "case OPTIONAL_PRESENT:\n"
4834 "copy_value((const %s&)other_value);\n"
4835 "break;\n"
4836 "case OPTIONAL_OMIT:\n"
4837 "set_selection(OMIT_VALUE);\n"
4838 "break;\n"
4839 "default:\n"
4840 "TTCN_error(\"Creating a template of type %s from an unbound optional "
4841 "field.\");\n"
4842 "}\n"
4843 "}\n\n", name, name, name, name, dispname);
4844
4845 /* copy constructor */
4846 def = mputprintf(def, "%s_template(const %s_template& other_value);\n",
4847 name, name);
4848 src = mputprintf(src, "%s_template::%s_template(const %s_template& "
4849 "other_value)\n"
4850 ": Base_Template()\n" /* yes, the base class _default_ constructor */
4851 "{\n"
4852 "copy_template(other_value);\n"
4853 "}\n\n", name, name, name);
4854
4855 /* destructor */
4856 def = mputprintf(def, "~%s_template();\n", name);
4857 src = mputprintf(src, "%s_template::~%s_template()\n"
4858 "{\n"
4859 "clean_up();\n"
4860 "}\n\n", name, name);
4861
4862 /* assignment operator <- template_sel */
4863 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
4864 name);
4865 src = mputprintf(src,
4866 "%s_template& %s_template::operator=(template_sel other_value)\n"
4867 "{\n"
4868 "check_single_selection(other_value);\n"
4869 "clean_up();\n"
4870 "set_selection(other_value);\n"
4871 "return *this;\n"
4872 "}\n\n", name, name);
4873
4874 /* assignment operator <- value */
4875 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
4876 name, name);
4877
4878 src = mputprintf(src,
4879 "%s_template& %s_template::operator=(const %s& other_value)\n"
4880 "{\n"
4881 "clean_up();\n"
4882 "copy_value(other_value);\n"
4883 "return *this;\n"
4884 "}\n\n", name, name, name);
4885
4886 /* assignment operator <- optional value */
4887 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
4888 "other_value);\n", name, name);
4889
4890 src = mputprintf(src,
4891 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
4892 "{\n"
4893 "clean_up();\n"
4894 "switch (other_value.get_selection()) {\n"
4895 "case OPTIONAL_PRESENT:\n"
4896 "copy_value((const %s&)other_value);\n"
4897 "break;\n"
4898 "case OPTIONAL_OMIT:\n"
4899 "set_selection(OMIT_VALUE);\n"
4900 "break;\n"
4901 "default:\n"
4902 "TTCN_error(\"Assignment of an unbound optional field to a template "
4903 "of type %s.\");\n"
4904 "}\n"
4905 "return *this;\n"
4906 "}\n\n", name, name, name, name, dispname);
4907
4908 /* assignment operator <- template*/
4909 def = mputprintf(def,
4910 "%s_template& operator=(const %s_template& other_value);\n",
4911 name, name);
4912
4913 src = mputprintf(src,
4914 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
4915 "{\n"
4916 "if (&other_value != this) {\n"
4917 "clean_up();\n"
4918 "copy_template(other_value);\n"
4919 "}\n"
4920 "return *this;\n"
4921 "}\n\n", name, name, name);
4922
4923 /* match operation (template matching) */
4924 def = mputprintf(def, "boolean match(const %s& other_value) const;\n",
4925 name);
4926
4927 src = mputprintf(src,
4928 "boolean %s_template::match(const %s& other_value) const\n"
4929 "{\n"
4930 "if (!other_value.is_bound()) return FALSE;\n"
4931 "switch (template_selection) {\n"
4932 "case ANY_VALUE:\n"
4933 "case ANY_OR_OMIT:\n"
4934 "return TRUE;\n"
4935 "case OMIT_VALUE:\n"
4936 "return FALSE;\n"
4937 "case SPECIFIC_VALUE:\n", name, name);
4938 for (i = 0; i < sdef->nElements; i++) {
4939 src = mputprintf(src,"if(!other_value.%s().is_bound()) return FALSE;\n", sdef->elements[i].name);
4940 if (sdef->elements[i].isOptional) src = mputprintf(src,
4941 "if((other_value.%s().ispresent() ? "
4942 "!single_value->field_%s.match((const %s&)other_value.%s()) : "
4943 "!single_value->field_%s.match_omit()))",
4944 sdef->elements[i].name, sdef->elements[i].name,
4945 sdef->elements[i].type, sdef->elements[i].name,
4946 sdef->elements[i].name);
4947 else src = mputprintf(src,
4948 "if(!single_value->field_%s.match(other_value.%s()))",
4949 sdef->elements[i].name, sdef->elements[i].name);
4950 src = mputstr(src, "return FALSE;\n");
4951 }
4952 src = mputprintf(src,
4953 "return TRUE;\n"
4954 "case VALUE_LIST:\n"
4955 "case COMPLEMENTED_LIST:\n"
4956 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
4957 "list_count++)\n"
4958 "if (value_list.list_value[list_count].match(other_value)) "
4959 "return template_selection == VALUE_LIST;\n"
4960 "return template_selection == COMPLEMENTED_LIST;\n"
4961 "default:\n"
4962 "TTCN_error(\"Matching an uninitialized/unsupported template of "
4963 "type %s.\");\n"
4964 "}\n"
4965 "return FALSE;\n"
4966 "}\n\n", dispname);
4967
4968 /* is_bound */
4969 def = mputstr(def, "boolean is_bound() const;\n");
4970
4971 src = mputprintf(src, "boolean %s_template::is_bound() const\n"
4972 "{\n"
4973 "if (template_selection == UNINITIALIZED_TEMPLATE && !is_ifpresent) "
4974 "return FALSE;\n", name);
4975 src = mputstr(src, "if (template_selection != SPECIFIC_VALUE) return TRUE;\n");
4976 for (i = 0; i < sdef->nElements; i++) {
4977 if (sdef->elements[i].isOptional) {
4978 src = mputprintf(src,
4979 "if (single_value->field_%s.is_omit() ||"
4980 " single_value->field_%s.is_bound()) return TRUE;\n",
4981 sdef->elements[i].name, sdef->elements[i].name);
4982 } else {
4983 src = mputprintf(src,
4984 "if (single_value->field_%s.is_bound()) return TRUE;\n",
4985 sdef->elements[i].name);
4986 }
4987 }
4988 src = mputstr(src, "return FALSE;\n"
4989 "}\n\n");
4990
4991 /* is_value */
4992 def = mputstr(def, "boolean is_value() const;\n");
4993
4994 src = mputprintf(src, "boolean %s_template::is_value() const\n"
4995 "{\n"
4996 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) "
4997 "return FALSE;\n", name);
4998 for (i = 0; i < sdef->nElements; i++) {
4999 if (sdef->elements[i].isOptional) {
5000 src = mputprintf(src,
5001 "if (!single_value->field_%s.is_omit() &&"
5002 " !single_value->field_%s.is_value()) return FALSE;\n",
5003 sdef->elements[i].name, sdef->elements[i].name);
5004 } else {
5005 src = mputprintf(src,
5006 "if (!single_value->field_%s.is_value()) return FALSE;\n",
5007 sdef->elements[i].name);
5008 }
5009 }
5010 src = mputstr(src, "return TRUE;\n"
5011 "}\n\n");
5012
5013 /* clean_up function */
5014 def = mputstr(def, "void clean_up();\n");
5015 src = mputprintf(src,
5016 "void %s_template::clean_up()\n"
5017 "{\n"
5018 "switch (template_selection) {\n"
5019 "case SPECIFIC_VALUE:\n"
5020 "delete single_value;\n"
5021 "break;\n"
5022 "case VALUE_LIST:\n"
5023 "case COMPLEMENTED_LIST:\n"
5024 "delete [] value_list.list_value;\n"
5025 "default:\n"
5026 "break;\n"
5027 "}\n"
5028 "template_selection = UNINITIALIZED_TEMPLATE;\n"
5029 "}\n\n", name);
5030
5031 /* valueof operation */
5032 def = mputprintf(def, "%s valueof() const;\n", name);
5033
5034 src = mputprintf(src, "%s %s_template::valueof() const\n"
5035 "{\n"
5036 "if (template_selection != SPECIFIC_VALUE || is_ifpresent)\n"
5037 "TTCN_error(\"Performing valueof or send operation on a non-specific "
5038 "template of type %s.\");\n"
5039 "%s ret_val;\n", name, name, dispname, name);
5040 for (i = 0; i < sdef->nElements; i++) {
5041 if (sdef->elements[i].isOptional) {
5042 src = mputprintf(src,
5043 "if (single_value->field_%s.is_omit()) "
5044 "ret_val.%s() = OMIT_VALUE;\n"
5045 "else ",
5046 sdef->elements[i].name, sdef->elements[i].name);
5047 }
5048 src = mputprintf(src, "if (single_value->field_%s.is_bound()) {\n"
5049 "ret_val.%s() = single_value->field_%s.valueof();\n"
5050 "}\n",
5051 sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name);
5052 }
5053 src = mputstr(src, "return ret_val;\n"
5054 "}\n\n");
5055
5056 /* void set_type(template_sel, int) function */
5057 def = mputstr(def,
5058 "void set_type(template_sel template_type, "
5059 "unsigned int list_length);\n");
5060
5061 src = mputprintf(src,
5062 "void %s_template::set_type(template_sel template_type, "
5063 "unsigned int list_length)\n"
5064 "{\n"
5065 "if (template_type != VALUE_LIST "
5066 "&& template_type != COMPLEMENTED_LIST)\n"
5067 "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n"
5068 "clean_up();\n"
5069 "set_selection(template_type);\n"
5070 "value_list.n_values = list_length;\n"
5071 "value_list.list_value = new %s_template[list_length];\n"
5072 "}\n\n", name, dispname, name);
5073
5074 /* list_item(int) function */
5075
5076 def = mputprintf(def,
5077 "%s_template& list_item(unsigned int list_index) const;\n", name);
5078
5079 src = mputprintf(src,
5080 "%s_template& %s_template::list_item(unsigned int list_index) const\n"
5081 "{\n"
5082 "if (template_selection != VALUE_LIST "
5083 "&& template_selection != COMPLEMENTED_LIST)\n"
5084 "TTCN_error(\"Accessing a list element of a non-list template of "
5085 "type %s.\");\n"
5086 "if (list_index >= value_list.n_values)\n"
5087 "TTCN_error(\"Index overflow in a value list template of type "
5088 "%s.\");\n"
5089 "return value_list.list_value[list_index];\n"
5090 "}\n\n", name, name, dispname, dispname);
5091
5092 /* template field access functions (non-const & const) */
5093 for (i = 0; i < sdef->nElements; i++) {
5094 def = mputprintf(def, "%s_template& %s();\n",
5095 sdef->elements[i].type, sdef->elements[i].name);
5096 src = mputprintf(src, "%s_template& %s_template::%s()\n"
5097 "{\n"
5098 "set_specific();\n"
5099 "return single_value->field_%s;\n"
5100 "}\n\n",
5101 sdef->elements[i].type, name, sdef->elements[i].name,
5102 sdef->elements[i].name);
5103 def = mputprintf(def, "const %s_template& %s() const;\n",
5104 sdef->elements[i].type, sdef->elements[i].name);
5105 src = mputprintf(src, "const %s_template& %s_template::%s() const\n"
5106 "{\n"
5107 "if (template_selection != SPECIFIC_VALUE)\n"
5108 "TTCN_error(\"Accessing field %s of a non-specific "
5109 "template of type %s.\");\n"
5110 "return single_value->field_%s;\n"
5111 "}\n\n",
5112 sdef->elements[i].type, name, sdef->elements[i].name,
5113 sdef->elements[i].dispname, dispname, sdef->elements[i].name);
5114 }
5115
5116 /* sizeof operation */
5117 def = mputstr(def, "int size_of() const;\n");
5118 src = mputprintf(src,
5119 "int %s_template::size_of() const\n"
5120 "{\n"
5121 " if (is_ifpresent) TTCN_error(\"Performing sizeof() operation on a "
5122 "template of type %s which has an ifpresent attribute.\");\n"
5123 " switch (template_selection)\n"
5124 " {\n"
5125 " case SPECIFIC_VALUE:\n",
5126 name, dispname);
5127 mandatory_fields_count = 0;
5128 for (i = 0; i < sdef->nElements; i++)
5129 if (!sdef->elements[i].isOptional) mandatory_fields_count++;
5130 if(sdef->nElements == mandatory_fields_count){
5131 src = mputprintf(src," return %lu;\n",
5132 (unsigned long) mandatory_fields_count);
5133 }else{
5134 src = mputprintf(src,
5135 " {"
5136 " int ret_val = %lu;\n", (unsigned long) mandatory_fields_count);
5137 for (i = 0; i < sdef->nElements; i++)
5138 if (sdef->elements[i].isOptional)
5139 src = mputprintf(src,
5140 " if (single_value->field_%s.is_present()) ret_val++;\n",
5141 sdef->elements[i].name);
5142 src = mputstr(src,
5143 " return ret_val;\n"
5144 " }\n");
5145 }
5146 src = mputprintf(src,
5147
5148 " case VALUE_LIST:\n"
5149 " {\n"
5150 " if (value_list.n_values<1)\n"
5151 " TTCN_error(\"Internal error: Performing sizeof() operation on a "
5152 "template of type %s containing an empty list.\");\n"
5153 " int item_size = value_list.list_value[0].size_of();\n"
5154 " for (unsigned int l_idx = 1; l_idx < value_list.n_values; l_idx++)\n"
5155 " {\n"
5156 " if (value_list.list_value[l_idx].size_of()!=item_size)\n"
5157 " TTCN_error(\"Performing sizeof() operation on a template "
5158 "of type %s containing a value list with different sizes.\");\n"
5159 " }\n"
5160 " return item_size;\n"
5161 " }\n"
5162 " case OMIT_VALUE:\n"
5163 " TTCN_error(\"Performing sizeof() operation on a template of type %s "
5164 "containing omit value.\");\n"
5165 " case ANY_VALUE:\n"
5166 " case ANY_OR_OMIT:\n"
5167 " TTCN_error(\"Performing sizeof() operation on a template of type %s "
5168 "containing */? value.\");\n"
5169 " case COMPLEMENTED_LIST:\n"
5170 " TTCN_error(\"Performing sizeof() operation on a template of type %s "
5171 "containing complemented list.\");\n"
5172 " default:\n"
5173 " TTCN_error(\"Performing sizeof() operation on an "
5174 "uninitialized/unsupported template of type %s.\");\n"
5175 " }\n"
5176 " return 0;\n"
5177 "}\n\n",
5178 dispname,dispname,dispname,dispname,dispname,dispname);
5179
5180 /* log function */
5181 def = mputstr(def, "void log() const;\n");
5182 src = mputprintf(src,
5183 "void %s_template::log() const\n"
5184 "{\n"
5185 "switch (template_selection) {\n"
5186 "case SPECIFIC_VALUE:\n", name);
5187 for (i = 0; i < sdef->nElements; i++) {
5188 src = mputstr(src, "TTCN_Logger::log_event_str(\"");
5189 if (i == 0) src = mputc(src, '{');
5190 else src = mputc(src, ',');
5191 src = mputprintf(src, " %s := \");\n"
5192 "single_value->field_%s.log();\n",
5193 sdef->elements[i].dispname, sdef->elements[i].name);
5194 }
5195 src = mputstr(src,
5196 "TTCN_Logger::log_event_str(\" }\");\n"
5197 "break;\n"
5198 "case COMPLEMENTED_LIST:\n"
5199 "TTCN_Logger::log_event_str(\"complement \");\n"
5200 "case VALUE_LIST:\n"
5201 "TTCN_Logger::log_char('(');\n"
5202 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
5203 "list_count++) {\n"
5204 "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n"
5205 "value_list.list_value[list_count].log();\n"
5206 "}\n"
5207 "TTCN_Logger::log_char(')');\n"
5208 "break;\n"
5209 "default:\n"
5210 "log_generic();\n"
5211 "}\n"
5212 "log_ifpresent();\n"
5213 "}\n\n");
5214
5215 /* log_match function */
5216 def = mputprintf(def, "void log_match(const %s& match_value) "
5217 "const;\n", name);
5218 src = mputprintf(src,
5219 "void %s_template::log_match(const %s& match_value) const\n"
5220 "{\n"
5221 "if(TTCN_Logger::VERBOSITY_COMPACT"
5222 " == TTCN_Logger::get_matching_verbosity()){\n"
5223 "if(match(match_value)){\n"
5224 "TTCN_Logger::print_logmatch_buffer();\n"
5225 "TTCN_Logger::log_event_str(\" matched\");\n"
5226 "} else{\n"
5227 "if (template_selection == SPECIFIC_VALUE) {\n"
5228 "size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();\n"
5229 , name, name);
5230 for (i = 0; i < sdef->nElements; i++) {
5231 if (sdef->elements[i].isOptional){
5232 src = mputprintf(src,
5233 "if (match_value.%s().ispresent()){\n"
5234 "if(!single_value->field_%s.match(match_value.%s())){\n"
5235 "TTCN_Logger::log_logmatch_info(\".%s\");\n"
5236 "single_value->field_%s.log_match(match_value.%s());\n"
5237 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
5238 "}\n"
5239 "} else {\n"
5240 "if (!single_value->field_%s.match_omit()){\n "
5241 "TTCN_Logger::log_logmatch_info(\".%s := omit with \");\n"
5242 "TTCN_Logger::print_logmatch_buffer();\n"
5243 "single_value->field_%s.log();\n"
5244 "TTCN_Logger::log_event_str(\" unmatched\");\n"
5245 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
5246 "}\n"
5247 "}\n"
5248 , sdef->elements[i].name, sdef->elements[i].name,
5249 sdef->elements[i].name, sdef->elements[i].dispname,
5250 sdef->elements[i].name, sdef->elements[i].name,
5251 sdef->elements[i].name, sdef->elements[i].dispname,
5252 sdef->elements[i].name);
5253 }else{
5254 src = mputprintf(src,
5255 "if(!single_value->field_%s.match(match_value.%s())){\n"
5256 "TTCN_Logger::log_logmatch_info(\".%s\");\n"
5257 "single_value->field_%s.log_match(match_value.%s());\n"
5258 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
5259 "}\n",sdef->elements[i].name, sdef->elements[i].name,
5260 sdef->elements[i].dispname, sdef->elements[i].name,
5261 sdef->elements[i].name);
5262 }
5263 }
5264
5265 src = mputstr(src,"}else {\n"
5266 "TTCN_Logger::print_logmatch_buffer();\n"
5267 "match_value.log();\n"
5268 "TTCN_Logger::log_event_str(\" with \");\n"
5269 "log();\n"
5270 "TTCN_Logger::log_event_str(\" unmatched\");\n"
5271 "}\n"
5272 "}\n"
5273 "return;\n"
5274 "}\n"
5275 "if (template_selection == SPECIFIC_VALUE) {\n");
5276 for (i = 0; i < sdef->nElements; i++) {
5277 src = mputstr(src, "TTCN_Logger::log_event_str(\"");
5278 if (i == 0) src = mputc(src, '{');
5279 else src = mputc(src, ',');
5280 src = mputprintf(src, " %s := \");\n", sdef->elements[i].dispname);
5281 if (sdef->elements[i].isOptional) src = mputprintf(src,
5282 "if (match_value.%s().ispresent()) "
5283 "single_value->field_%s.log_match(match_value.%s());\n"
5284 "else {\n"
5285 "TTCN_Logger::log_event_str(\"omit with \");\n"
5286 "single_value->field_%s.log();\n"
5287 "if (single_value->field_%s.match_omit()) "
5288 "TTCN_Logger::log_event_str(\" matched\");\n"
5289 "else TTCN_Logger::log_event_str(\" unmatched\");\n"
5290 "}\n",
5291 sdef->elements[i].name, sdef->elements[i].name,
5292 sdef->elements[i].name, sdef->elements[i].name,
5293 sdef->elements[i].name);
5294 else src = mputprintf(src,
5295 "single_value->field_%s.log_match(match_value.%s());\n",
5296 sdef->elements[i].name, sdef->elements[i].name);
5297 }
5298 src = mputstr(src,
5299 "TTCN_Logger::log_event_str(\" }\");\n"
5300 "} else {\n"
5301 "match_value.log();\n"
5302 "TTCN_Logger::log_event_str(\" with \");\n"
5303 "log();\n"
5304 "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n"
5305 "else TTCN_Logger::log_event_str(\" unmatched\");\n"
5306 "}\n"
5307 "}\n\n");
5308
5309 /*encode_text function*/
5310 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
5311 src = mputprintf(src,
5312 "void %s_template::encode_text(Text_Buf& text_buf) const\n"
5313 "{\n"
5314 "encode_text_base(text_buf);\n"
5315 "switch (template_selection) {\n"
5316 "case SPECIFIC_VALUE:\n", name);
5317 for (i = 0; i < sdef->nElements; i++) {
5318 src = mputprintf(src, "single_value->field_%s.encode_text(text_buf);\n",
5319 sdef->elements[i].name);
5320 }
5321 src = mputprintf(src,
5322 "case OMIT_VALUE:\n"
5323 "case ANY_VALUE:\n"
5324 "case ANY_OR_OMIT:\n"
5325 "break;\n"
5326 "case VALUE_LIST:\n"
5327 "case COMPLEMENTED_LIST:\n"
5328 "text_buf.push_int(value_list.n_values);\n"
5329 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
5330 "list_count++)\n"
5331 "value_list.list_value[list_count].encode_text(text_buf);\n"
5332 "break;\n"
5333 "default:\n"
5334 "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported "
5335 "template of type %s.\");\n"
5336 "}\n"
5337 "}\n\n", dispname);
5338
5339 /*decode_text function*/
5340 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
5341 src = mputprintf(src,
5342 "void %s_template::decode_text(Text_Buf& text_buf)\n"
5343 "{\n"
5344 "clean_up();\n"
5345 "decode_text_base(text_buf);\n"
5346 "switch (template_selection) {\n"
5347 "case SPECIFIC_VALUE:\n"
5348 "single_value = new single_value_struct;\n", name);
5349 for (i = 0; i < sdef->nElements; i++) {
5350 src = mputprintf(src, "single_value->field_%s.decode_text(text_buf);\n",
5351 sdef->elements[i].name);
5352 }
5353 src = mputprintf(src,
5354 "case OMIT_VALUE:\n"
5355 "case ANY_VALUE:\n"
5356 "case ANY_OR_OMIT:\n"
5357 "break;\n"
5358 "case VALUE_LIST:\n"
5359 "case COMPLEMENTED_LIST:\n"
5360 "value_list.n_values = text_buf.pull_int().get_val();\n"
5361 "value_list.list_value = new %s_template[value_list.n_values];\n"
5362 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
5363 "list_count++)\n"
5364 "value_list.list_value[list_count].decode_text(text_buf);\n"
5365 "break;\n"
5366 "default:\n"
5367 "TTCN_error(\"Text decoder: An unknown/unsupported selection was "
5368 "received in a template of type %s.\");\n"
5369 "}\n"
5370 "}\n\n", name, dispname);
5371
5372 /* set_param() */
5373 def = mputstr(def, "void set_param(Module_Param& param);\n");
5374 src = mputprintf(src,
5375 "void %s_template::set_param(Module_Param& param)\n"
5376 "{\n"
5377 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
5378 " param.get_id()->next_name()) {\n"
5379 // Haven't reached the end of the module parameter name
5380 // => the name refers to one of the fields, not to the whole record
5381 " char* param_field = param.get_id()->get_current_name();\n"
5382 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
5383 " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n"
5384 " \" name for %s template type `%s'\");\n"
5385 " }\n"
5386 " ", name, kind_str, dispname);
5387 for (i = 0; i < sdef->nElements; i++) {
5388 src = mputprintf(src,
5389 "if (strcmp(\"%s\", param_field) == 0) {\n"
5390 " %s().set_param(param);\n"
5391 " return;\n"
5392 " } else ",
5393 sdef->elements[i].dispname, sdef->elements[i].name);
5394 }
5395 src = mputprintf(src,
5396 "param.error(\"Field `%%s' not found in %s template type `%s'\", param_field);\n"
5397 " }\n"
5398 " param.basic_check(Module_Param::BC_TEMPLATE, \"%s template\");\n"
5399 " switch (param.get_type()) {\n"
5400 " case Module_Param::MP_Omit:\n"
5401 " *this = OMIT_VALUE;\n"
5402 " break;\n"
5403 " case Module_Param::MP_Any:\n"
5404 " *this = ANY_VALUE;\n"
5405 " break;\n"
5406 " case Module_Param::MP_AnyOrNone:\n"
5407 " *this = ANY_OR_OMIT;\n"
5408 " break;\n"
5409 " case Module_Param::MP_List_Template:\n"
5410 " case Module_Param::MP_ComplementList_Template:\n"
5411 " set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());\n"
5412 " for (size_t p_i=0; p_i<param.get_size(); p_i++) {\n"
5413 " list_item(p_i).set_param(*param.get_elem(p_i));\n"
5414 " }\n"
5415 " break;\n"
5416 " case Module_Param::MP_Value_List:\n"
5417 " if (%lu<param.get_size()) {\n"
5418 " param.error(\"%s template of type %s has %lu fields but list value has %%d fields\", (int)param.get_size());\n"
5419 " }\n",
5420 kind_str, dispname, kind_str, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements);
5421 for (i = 0; i < sdef->nElements; ++i) {
5422 src = mputprintf(src,
5423 " if (param.get_size()>%lu && param.get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*param.get_elem(%lu));\n",
5424 (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i);
5425 }
5426 src = mputstr(src,
5427 " break;\n"
5428 " case Module_Param::MP_Assignment_List: {\n"
5429 " Vector<bool> value_used(param.get_size());\n"
5430 " value_used.resize(param.get_size(), false);\n");
5431 for (i = 0; i < sdef->nElements; ++i) {
5432 src = mputprintf(src,
5433 " for (size_t val_idx=0; val_idx<param.get_size(); val_idx++) {\n"
5434 " Module_Param* const curr_param = param.get_elem(val_idx);\n"
5435 " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n"
5436 " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n"
5437 " %s().set_param(*curr_param);\n"
5438 " }\n"
5439 " value_used[val_idx]=true;\n"
5440 " }\n"
5441 " }\n"
5442 , sdef->elements[i].dispname, sdef->elements[i].name);
5443 }
5444 src = mputprintf(src,
5445 " for (size_t val_idx=0; val_idx<param.get_size(); val_idx++) if (!value_used[val_idx]) {\n"
5446 " param.get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", param.get_elem(val_idx)->get_id()->get_name());\n"
5447 " break;\n"
5448 " }\n"
5449 " } break;\n"
5450 " default:\n"
5451 " param.type_error(\"%s template\", \"%s\");\n"
5452 " }\n"
5453 " is_ifpresent = param.get_ifpresent();\n"
5454 "}\n\n", dispname, kind_str, dispname);
5455
5456 /* check template restriction */
5457 def = mputstr(def, "void check_restriction(template_res t_res, "
5458 "const char* t_name=NULL) const;\n");
5459 src = mputprintf(src,
5460 "void %s_template::check_restriction("
5461 "template_res t_res, const char* t_name) const\n"
5462 "{\n"
5463 "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
5464 "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
5465 "case TR_OMIT:\n"
5466 "if (template_selection==OMIT_VALUE) return;\n"
5467 "case TR_VALUE:\n"
5468 "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n",
5469 name);
5470 for (i = 0; i < sdef->nElements; i++) {
5471 src = mputprintf(src, "single_value->field_%s.check_restriction("
5472 "t_res, t_name ? t_name : \"%s\");\n",
5473 sdef->elements[i].name, dispname);
5474 }
5475 src = mputprintf(src,
5476 "return;\n"
5477 "case TR_PRESENT:\n"
5478 "if (!match_omit()) return;\n"
5479 "break;\n"
5480 "default:\n"
5481 "return;\n"
5482 "}\n"
5483 "TTCN_error(\"Restriction `%%s' on template of type %%s "
5484 "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n"
5485 "}\n\n", dispname);
5486
5487 defCommonRecordTemplate(name, &def, &src);
5488
5489 def = mputstr(def, "};\n\n");
5490
5491 output->header.class_defs = mputstr(output->header.class_defs, def);
5492 Free(def);
5493
5494 output->source.methods = mputstr(output->source.methods, src);
5495 Free(src);
5496 }
5497
5498 static void defEmptyRecordClass(const struct_def *sdef,
5499 output_struct *output)
5500 {
5501 const char *name = sdef->name, *dispname = sdef->dispname;
5502 char *def = NULL, *src = NULL;
5503 boolean ber_needed = sdef->isASN1 && enable_ber();
5504 boolean raw_needed = sdef->hasRaw && enable_raw();
5505 boolean text_needed = sdef->hasText && enable_text();
5506 boolean xer_needed = sdef->hasXer && enable_xer();
5507 boolean json_needed = sdef->hasJson && enable_json();
5508
5509 def = mputprintf(def,
5510 #ifndef NDEBUG
5511 "// written by %s in " __FILE__ " at line %d\n"
5512 #endif
5513 "class %s : public Base_Type {\n"
5514 "boolean bound_flag;\n"
5515 "public:\n"
5516 #ifndef NDEBUG
5517 , __FUNCTION__, __LINE__
5518 #endif
5519 , name);
5520
5521 /* default ctor */
5522 def = mputprintf(def, "%s();\n", name);
5523 src = mprintf("%s::%s()\n"
5524 "{\n"
5525 "bound_flag = FALSE;\n"
5526 "}\n\n", name, name);
5527
5528 /* ctor from NULL_VALUE (i.e. {}) */
5529 def = mputprintf(def, "%s(null_type other_value);\n", name);
5530 src = mputprintf(src, "%s::%s(null_type)\n"
5531 "{\n"
5532 "bound_flag = TRUE;\n"
5533 "}\n\n", name, name);
5534
5535 /* copy ctor */
5536 def = mputprintf(def, "%s(const %s& other_value);\n", name, name);
5537 src = mputprintf(src, "%s::%s(const %s& other_value)\n"
5538 "{\n"
5539 "other_value.must_bound(\"Copying an unbound value of "
5540 "type %s.\");\n"
5541 "bound_flag = TRUE;\n"
5542 "}\n\n", name, name, name, dispname);
5543
5544 /* assignment op: from NULL_VALUE */
5545 def = mputprintf(def, "%s& operator=(null_type other_value);\n", name);
5546 src = mputprintf(src, "%s& %s::operator=(null_type)\n"
5547 "{\n"
5548 "bound_flag = TRUE;\n"
5549 "return *this;\n"
5550 "}\n\n", name, name);
5551
5552 /* assignment op: from itself */
5553 def = mputprintf(def, "%s& operator=(const %s& other_value);\n", name,
5554 name);
5555 src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n"
5556 "{\n"
5557 "other_value.must_bound(\"Assignment of an unbound value of type "
5558 "%s.\");\n"
5559 "bound_flag = TRUE;\n"
5560 "return *this;\n"
5561 "}\n\n", name, name, name, dispname);
5562
5563 /* comparison op: with NULL_VALUE */
5564 def = mputstr(def, "boolean operator==(null_type other_value) const;\n");
5565 src = mputprintf(src,
5566 "boolean %s::operator==(null_type) const\n"
5567 "{\n"
5568 "must_bound(\"Comparison of an unbound value of type %s.\");\n"
5569 "return TRUE;\n"
5570 "}\n\n", name, dispname);
5571
5572 /* comparison op: with itself */
5573 def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n",
5574 name);
5575 src = mputprintf(src,
5576 "boolean %s::operator==(const %s& other_value) const\n"
5577 "{\n"
5578 "must_bound(\"Comparison of an unbound value of type %s.\");\n"
5579 "other_value.must_bound(\"Comparison of an unbound value of type "
5580 "%s.\");\n"
5581 "return TRUE;\n"
5582 "}\n\n", name, name, dispname, dispname);
5583
5584 /* non-equal operators */
5585 def = mputprintf(def,
5586 "inline boolean operator!=(null_type other_value) const "
5587 "{ return !(*this == other_value); }\n"
5588 "inline boolean operator!=(const %s& other_value) const "
5589 "{ return !(*this == other_value); }\n", name);
5590
5591
5592 /* is_bound function */
5593 def = mputstr(def, "inline boolean is_bound() const "
5594 "{ return bound_flag; }\n");
5595
5596 /* is_present function */
5597 def = mputstr(def,
5598 "inline boolean is_present() const { return is_bound(); }\n");
5599
5600 /* is_value function */
5601 def = mputstr(def, "inline boolean is_value() const "
5602 "{ return bound_flag; }\n");
5603
5604 /* clean_up function */
5605 def = mputstr(def, "inline void clean_up() "
5606 "{ bound_flag = FALSE; }\n");
5607
5608 /* must_bound function */
5609 def = mputstr(def, "inline void must_bound(const char *err_msg) const "
5610 "{ if (!bound_flag) TTCN_error(\"%s\", err_msg); }\n");
5611
5612 /* log function */
5613 def = mputstr(def, "void log() const;\n");
5614 src = mputprintf(src, "void %s::log() const\n"
5615 "{\n"
5616 "if (bound_flag) TTCN_Logger::log_event_str(\"{ }\");\n"
5617 "else TTCN_Logger::log_event_unbound();\n"
5618 "}\n\n", name);
5619
5620 /* set_param function */
5621 def = mputstr(def, "void set_param(const Module_Param& param);\n");
5622 src = mputprintf(src, "void %s::set_param(const Module_Param& param)\n"
5623 "{\n"
5624 " param.basic_check(Module_Param::BC_VALUE, \"empty record/set value (i.e. { })\");\n"
5625 " if (param.get_type()!=Module_Param::MP_Value_List || param.get_size()>0) {\n"
5626 " param.type_error(\"empty record/set value (i.e. { })\", \"%s\");\n"
5627 " }\n"
5628 " bound_flag = TRUE;\n"
5629 "}\n\n", name, dispname);
5630
5631 /* encode_text function */
5632 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
5633 src = mputprintf(src, "void %s::encode_text(Text_Buf& /*text_buf*/) const\n"
5634 "{\n"
5635 "must_bound(\"Text encoder: Encoding an unbound value of type %s.\");\n"
5636 "}\n\n", name, dispname);
5637
5638 /* decode_text function */
5639 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
5640 src = mputprintf(src, "void %s::decode_text(Text_Buf& /*text_buf*/)\n"
5641 "{\n"
5642 "bound_flag = TRUE;\n"
5643 "}\n\n", name);
5644
5645 if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
5646 def_encdec(name, &def, &src, ber_needed, raw_needed,
5647 text_needed, xer_needed, json_needed, FALSE);
5648
5649 /* BER functions */
5650 if(ber_needed) {
5651 /* BER_encode_TLV() */
5652 src=mputprintf
5653 (src,
5654 "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,"
5655 " unsigned p_coding) const\n"
5656 "{\n"
5657 " BER_chk_descr(p_td);\n"
5658 " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
5659 " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
5660 " return new_tlv;\n"
5661 "}\n"
5662 "\n"
5663 , name
5664 );
5665
5666 /* BER_decode_TLV() */
5667 src=mputprintf
5668 (src,
5669 "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,"
5670 " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n"
5671 "{\n"
5672 " BER_chk_descr(p_td);\n"
5673 " ASN_BER_TLV_t stripped_tlv;\n"
5674 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
5675 " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n"
5676 " stripped_tlv.chk_constructed_flag(TRUE);\n"
5677 " bound_flag=TRUE;\n"
5678 " return TRUE;\n"
5679 "}\n"
5680 "\n"
5681 , name, sdef->dispname
5682 );
5683 } /* if ber_needed */
5684 if(text_needed){
5685 src = mputprintf(src,
5686 "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td,"
5687 "TTCN_Buffer& p_buf) const{\n"
5688 " int encoded_length=0;\n"
5689 " if(p_td.text->begin_encode){\n"
5690 " p_buf.put_cs(*p_td.text->begin_encode);\n"
5691 " encoded_length+=p_td.text->begin_encode->lengthof();\n"
5692 " }\n"
5693 " if(!bound_flag) {\n"
5694 " TTCN_EncDec_ErrorContext::error\n"
5695 " (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
5696 " }\n"
5697 " if(p_td.text->end_encode){\n"
5698 " p_buf.put_cs(*p_td.text->end_encode);\n"
5699 " encoded_length+=p_td.text->end_encode->lengthof();\n"
5700 " }\n"
5701 " return encoded_length;\n"
5702 "}\n"
5703 ,name
5704 );
5705 src = mputprintf(src,
5706 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
5707 " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n"
5708 " bound_flag = TRUE;\n"
5709 " int decoded_length=0;\n"
5710 " if(p_td.text->begin_decode){\n"
5711 " int tl;\n"
5712 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
5713 " if(no_err)return -1;\n"
5714 " TTCN_EncDec_ErrorContext::error\n"
5715 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
5716 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
5717 ", p_td.name);\n"
5718 " return 0;\n"
5719 " }\n"
5720 " decoded_length+=tl;\n"
5721 " p_buf.increase_pos(tl);\n"
5722 " }\n"
5723 " if(p_td.text->end_decode){\n"
5724 " int tl;\n"
5725 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
5726 " if(no_err)return -1;\n"
5727 " TTCN_EncDec_ErrorContext::error\n"
5728 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
5729 " not found for '%%s': \",(const char*)*(p_td.text->end_decode)"
5730 ", p_td.name);\n"
5731 " return 0;\n"
5732 " }\n"
5733 " decoded_length+=tl;\n"
5734 " p_buf.increase_pos(tl);\n"
5735 " }\n"
5736 " return decoded_length;\n"
5737 "}\n"
5738 ,name
5739 );
5740
5741 }
5742 /* RAW functions */
5743 if (raw_needed) {
5744 src = mputprintf(src,
5745 "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td, "
5746 "RAW_enc_tree& /*myleaf*/) const\n"
5747 "{\n"
5748 "if (!bound_flag) TTCN_EncDec_ErrorContext::error"
5749 "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value of "
5750 "type %%s.\", p_td.name);\n"
5751 "return 0;\n"
5752 "}\n\n", name);
5753
5754 src = mputprintf(src,
5755 "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, "
5756 "TTCN_Buffer& p_buf, int, raw_order_t, boolean, int, boolean)\n"
5757 "{\n"
5758 "bound_flag = TRUE;\n"
5759 "return p_buf.increase_pos_padd(p_td.raw->prepadding) + "
5760 "p_buf.increase_pos_padd(p_td.raw->padding);\n"
5761 "}\n\n", name);
5762 }
5763
5764 if (xer_needed) { /* XERSTUFF codegen for empty record/SEQUENCE */
5765 src=mputprintf(src,
5766 "boolean %s::can_start(const char *p_name, const char *p_uri, "
5767 "const XERdescriptor_t& p_td, unsigned int p_flavor) {\n"
5768 " boolean e_xer = is_exer(p_flavor);\n"
5769 " if (e_xer && (p_td.xer_bits & UNTAGGED)) return false;\n"
5770 " else return check_name(p_name, p_td, e_xer) && (!e_xer || check_namespace(p_uri, p_td));\n"
5771 "}\n\n"
5772 , name
5773
5774 );
5775 src = mputprintf(src,
5776 "int %s::XER_encode(const XERdescriptor_t& p_td,"
5777 " TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent) const{\n"
5778 " int encoded_length=(int)p_buf.get_len();\n"
5779 " int is_indented = !is_canonical(p_flavor);\n"
5780 " int e_xer = is_exer(p_flavor);\n"
5781 " if (is_indented) do_indent(p_buf, p_indent);\n"
5782 " p_buf.put_c('<');\n"
5783 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
5784 " p_buf.put_s((size_t)p_td.namelens[e_xer]-2, (cbyte*)p_td.names[e_xer]);\n"
5785 " p_buf.put_s(2 + is_indented, (cbyte*)\"/>\\n\");\n"
5786 " return (int)p_buf.get_len() - encoded_length;\n"
5787 "}\n\n"
5788 , name);
5789 src = mputprintf(src,
5790 #ifndef NDEBUG
5791 "// written by %s in " __FILE__ " at %d\n"
5792 #endif
5793 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, "
5794 "unsigned int p_flavor)\n"
5795 "{\n"
5796 " int e_xer = is_exer(p_flavor);\n"
5797 " bound_flag = true;\n"
5798 " int rd_ok, depth=-1;\n"
5799 " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n"
5800 " int type = p_reader.NodeType();\n"
5801 " if (type==XML_READER_TYPE_ELEMENT) {\n"
5802 " verify_name(p_reader, p_td, e_xer);\n"
5803 " depth=p_reader.Depth();\n"
5804 " if (p_reader.IsEmptyElement()) {\n"
5805 " rd_ok = p_reader.Read(); break;\n"
5806 " }\n"
5807 " else if ((p_flavor & XER_MASK) == XER_CANONICAL) {\n"
5808 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
5809 "\"Expected an empty element tag\");\n"
5810 " }\n"
5811 " }\n"
5812 " else if (type == XML_READER_TYPE_END_ELEMENT && depth != -1) {\n"
5813 " verify_end(p_reader, p_td, depth, e_xer);\n"
5814 " rd_ok = p_reader.Read(); break;\n"
5815 " }\n"
5816 " }\n"
5817 " return 1;\n"
5818 "}\n\n"
5819 #ifndef NDEBUG
5820 , __FUNCTION__, __LINE__
5821 #endif
5822 , name);
5823 }
5824 if (json_needed) {
5825 // JSON encode, RT1
5826 src = mputprintf(src,
5827 "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
5828 "{\n"
5829 " if (!is_bound()) {\n"
5830 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
5831 " \"Encoding an unbound value of type %s.\");\n"
5832 " return -1;\n"
5833 " }\n\n"
5834 " return p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL) + \n"
5835 " p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
5836 "}\n\n"
5837 , name, dispname);
5838
5839 // JSON decode, RT1
5840 src = mputprintf(src,
5841 "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
5842 "{\n"
5843 " json_token_t token = JSON_TOKEN_NONE;\n"
5844 " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
5845 " if (JSON_TOKEN_ERROR == token) {\n"
5846 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
5847 " return JSON_ERROR_FATAL;\n"
5848 " }\n"
5849 " else if (JSON_TOKEN_OBJECT_START != token) {\n"
5850 " return JSON_ERROR_INVALID_TOKEN;\n"
5851 " }\n\n"
5852 " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n"
5853 " if (JSON_TOKEN_OBJECT_END != token) {\n"
5854 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n"
5855 " return JSON_ERROR_FATAL;\n"
5856 " }\n\n"
5857 " bound_flag = true;\n\n"
5858 " return dec_len;\n"
5859 "}\n\n"
5860 , name);
5861 }
5862
5863 /* closing class definition */
5864 def = mputstr(def, "};\n\n");
5865
5866 output->header.class_defs = mputstr(output->header.class_defs, def);
5867 Free(def);
5868
5869 output->source.methods = mputstr(output->source.methods, src);
5870 Free(src);
5871
5872 output->header.function_prototypes =
5873 mputprintf(output->header.function_prototypes,
5874 "extern boolean operator==(null_type null_value, const %s& "
5875 "other_value);\n", name);
5876 output->source.function_bodies =
5877 mputprintf(output->source.function_bodies,
5878 "boolean operator==(null_type, const %s& other_value)\n"
5879 "{\n"
5880 "other_value.must_bound(\"Comparison of an unbound value of type "
5881 "%s.\");\n"
5882 "return TRUE;\n"
5883 "}\n\n", name, dispname);
5884
5885 output->header.function_prototypes =
5886 mputprintf(output->header.function_prototypes,
5887 "inline boolean operator!=(null_type null_value, const %s& "
5888 "other_value) "
5889 "{ return !(null_value == other_value); }\n", name);
5890 }
5891
5892 static void defEmptyRecordTemplate(const char *name, const char *dispname,
5893 output_struct *output)
5894 {
5895 char *def = NULL, *src = NULL;
5896
5897 /* class definition */
5898 def = mprintf("class %s_template : public Base_Template {\n"
5899 "struct {\n"
5900 "unsigned int n_values;\n"
5901 "%s_template *list_value;\n"
5902 "} value_list;\n", name, name);
5903
5904 /* copy_template function */
5905 def = mputprintf(def, "void copy_template(const %s_template& "
5906 "other_value);\n\n", name);
5907 src = mputprintf(src,
5908 "void %s_template::copy_template(const %s_template& other_value)\n"
5909 "{\n"
5910 "set_selection(other_value);\n"
5911 "switch (template_selection) {\n"
5912 "case OMIT_VALUE:\n"
5913 "case ANY_VALUE:\n"
5914 "case ANY_OR_OMIT:\n"
5915 "case SPECIFIC_VALUE:\n"
5916 "break;\n"
5917 "case VALUE_LIST:\n"
5918 "case COMPLEMENTED_LIST:\n"
5919 "value_list.n_values = other_value.value_list.n_values;\n"
5920 "value_list.list_value = new %s_template[value_list.n_values];\n"
5921 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
5922 "list_count++)\n"
5923 "value_list.list_value[list_count].copy_template("
5924 "other_value.value_list.list_value[list_count]);\n"
5925 "break;\n"
5926 "default:\n"
5927 "TTCN_error(\"Copying an uninitialized/unsupported template of type "
5928 "%s.\");\n"
5929 "break;\n"
5930 "}\n"
5931 "}\n\n", name, name, name, dispname);
5932
5933 /* default ctor */
5934 def = mputprintf(def, "public:\n"
5935 "%s_template();\n", name);
5936 src = mputprintf(src, "%s_template::%s_template()\n"
5937 "{\n"
5938 "}\n\n", name, name);
5939
5940 /* ctor for generic wildcards */
5941 def = mputprintf(def, "%s_template(template_sel other_value);\n", name);
5942 src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n"
5943 " : Base_Template(other_value)\n"
5944 "{\n"
5945 "check_single_selection(other_value);\n"
5946 "}\n\n", name, name);
5947
5948 /* ctor for value {} */
5949 def = mputprintf(def, "%s_template(null_type other_value);\n", name);
5950 src = mputprintf(src, "%s_template::%s_template(null_type)\n"
5951 " : Base_Template(SPECIFIC_VALUE)\n"
5952 "{\n"
5953 "}\n\n", name, name);
5954
5955 /* ctor for specific value */
5956 def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name);
5957 src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n"
5958 " : Base_Template(SPECIFIC_VALUE)\n"
5959 "{\n"
5960 "other_value.must_bound(\"Creating a template from an unbound value of "
5961 "type %s.\");\n"
5962 "}\n\n", name, name, name, dispname);
5963
5964 /* ctor for optional value */
5965 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n",
5966 name, name);
5967 src = mputprintf(src, "%s_template::%s_template(const OPTIONAL<%s>& "
5968 "other_value)\n"
5969 "{\n"
5970 "switch (other_value.get_selection()) {\n"
5971 "case OPTIONAL_PRESENT:\n"
5972 "set_selection(SPECIFIC_VALUE);\n"
5973 "break;\n"
5974 "case OPTIONAL_OMIT:\n"
5975 "set_selection(OMIT_VALUE);\n"
5976 "break;\n"
5977 "default:\n"
5978 "TTCN_error(\"Creating a template of type %s from an unbound optional "
5979 "field.\");\n"
5980 "}\n"
5981 "}\n\n", name, name, name, dispname);
5982
5983 /* copy ctor */
5984 def = mputprintf(def, "%s_template(const %s_template& other_value);\n",
5985 name, name);
5986 src = mputprintf(src, "%s_template::%s_template(const %s_template& "
5987 "other_value)\n"
5988 ": Base_Template()" /* yes, the base class _default_ constructor */
5989 "{\n"
5990 "copy_template(other_value);\n"
5991 "}\n\n", name, name, name);
5992
5993 /* dtor */
5994 def = mputprintf(def, "~%s_template();\n", name);
5995 src = mputprintf(src, "%s_template::~%s_template()\n"
5996 "{\n"
5997 "clean_up();\n"
5998 "}\n\n", name, name);
5999
6000 /* clean_up function */
6001 def = mputstr(def, "void clean_up();\n");
6002 src = mputprintf(src, "void %s_template::clean_up()\n"
6003 "{\n"
6004 "if (template_selection == VALUE_LIST || "
6005 "template_selection == COMPLEMENTED_LIST)\n"
6006 "delete [] value_list.list_value;\n"
6007 "template_selection = UNINITIALIZED_TEMPLATE;\n"
6008 "}\n\n", name);
6009
6010 /* assignment op for generic wildcards */
6011 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
6012 name);
6013 src = mputprintf(src, "%s_template& %s_template::operator=(template_sel "
6014 "other_value)\n"
6015 "{\n"
6016 "check_single_selection(other_value);\n"
6017 "clean_up();\n"
6018 "set_selection(other_value);\n"
6019 "return *this;\n"
6020 "}\n\n", name, name);
6021
6022 /* assignment op for value {} */
6023 def = mputprintf(def, "%s_template& operator=(null_type other_value);\n",
6024 name);
6025 src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n"
6026 "{\n"
6027 "clean_up();\n"
6028 "set_selection(SPECIFIC_VALUE);\n"
6029 "return *this;\n"
6030 "}\n\n", name, name);
6031
6032 /* assignment op for specific value */
6033 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
6034 name, name);
6035 src = mputprintf(src, "%s_template& %s_template::operator=(const %s& "
6036 "other_value)\n"
6037 "{\n"
6038 "other_value.must_bound(\"Assignment of an unbound value of type %s "
6039 "to a template.\");\n"
6040 "clean_up();\n"
6041 "set_selection(SPECIFIC_VALUE);\n"
6042 "return *this;\n"
6043 "}\n\n", name, name, name, dispname);
6044
6045 /* assignment op for optional value */
6046 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
6047 "other_value);\n", name, name);
6048 src = mputprintf(src, "%s_template& %s_template::operator="
6049 "(const OPTIONAL<%s>& other_value)\n"
6050 "{\n"
6051 "clean_up();\n"
6052 "switch (other_value.get_selection()) {\n"
6053 "case OPTIONAL_PRESENT:\n"
6054 "set_selection(SPECIFIC_VALUE);\n"
6055 "break;\n"
6056 "case OPTIONAL_OMIT:\n"
6057 "set_selection(OMIT_VALUE);\n"
6058 "break;\n"
6059 "default:\n"
6060 "TTCN_error(\"Assignment of an unbound optional field to a template "
6061 "of type %s.\");\n"
6062 "}\n"
6063 "return *this;\n"
6064 "}\n\n", name, name, name, dispname);
6065
6066 /* assignment op for itself */
6067 def = mputprintf(def, "%s_template& operator=(const %s_template& "
6068 "other_value);\n", name, name);
6069 src = mputprintf(src, "%s_template& %s_template::operator="
6070 "(const %s_template& other_value)\n"
6071 "{\n"
6072 "if (&other_value != this) {\n"
6073 "clean_up();\n"
6074 "set_selection(other_value);\n"
6075 "}\n"
6076 "return *this;\n"
6077 "}\n\n", name, name, name);
6078
6079 /* match operation with {} */
6080 def = mputstr(def, "boolean match(null_type other_value) const;\n");
6081 src = mputprintf(src, "boolean %s_template::match(null_type other_value) "
6082 "const\n"
6083 "{\n"
6084 "switch (template_selection) {\n"
6085 "case ANY_VALUE:\n"
6086 "case ANY_OR_OMIT:\n"
6087 "case SPECIFIC_VALUE:\n"
6088 "return TRUE;\n"
6089 "case OMIT_VALUE:\n"
6090 "return FALSE;\n"
6091 "case VALUE_LIST:\n"
6092 "case COMPLEMENTED_LIST:\n"
6093 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
6094 "list_count++)\n"
6095 "if (value_list.list_value[list_count].match(other_value)) "
6096 "return template_selection == VALUE_LIST;\n"
6097 "return template_selection == COMPLEMENTED_LIST;\n"
6098 "default:\n"
6099 "TTCN_error(\"Matching an uninitialized/unsupported template of "
6100 "type %s.\");\n"
6101 "}\n"
6102 "return FALSE;\n"
6103 "}\n\n", name, dispname);
6104
6105 /* match operation with specific value */
6106 def = mputprintf(def, "boolean match(const %s& other_value) const;\n",
6107 name);
6108 src = mputprintf(src, "boolean %s_template::match(const %s& other_value) "
6109 "const\n"
6110 "{\n"
6111 "if (!other_value.is_bound()) return FALSE;"
6112 "return match(NULL_VALUE);\n"
6113 "}\n\n", name, name);
6114
6115 /* valueof operation */
6116 def = mputprintf(def, "%s valueof() const;\n", name);
6117 src = mputprintf(src, "%s %s_template::valueof() const\n"
6118 "{\n"
6119 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) "
6120 "TTCN_error(\"Performing a valueof or send operation on a "
6121 "non-specific template of type %s.\");\n"
6122 "return NULL_VALUE;\n"
6123 "}\n\n", name, name, dispname);
6124
6125 /* void set_type(template_sel, int) function */
6126 def = mputstr(def,
6127 "void set_type(template_sel template_type, "
6128 "unsigned int list_length);\n");
6129
6130 src = mputprintf(src,
6131 "void %s_template::set_type(template_sel template_type, "
6132 "unsigned int list_length)\n"
6133 "{\n"
6134 "if (template_type != VALUE_LIST "
6135 "&& template_type != COMPLEMENTED_LIST)\n"
6136 "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n"
6137 "clean_up();\n"
6138 "set_selection(template_type);\n"
6139 "value_list.n_values = list_length;\n"
6140 "value_list.list_value = new %s_template[list_length];\n"
6141 "}\n\n", name, dispname, name);
6142
6143 /* list_item(int) function */
6144
6145 def = mputprintf(def,
6146 "%s_template& list_item(unsigned int list_index) const;\n", name);
6147
6148 src = mputprintf(src,
6149 "%s_template& %s_template::list_item(unsigned int list_index) const\n"
6150 "{\n"
6151 "if (template_selection != VALUE_LIST "
6152 "&& template_selection != COMPLEMENTED_LIST)\n"
6153 "TTCN_error(\"Accessing a list element of a non-list template of "
6154 "type %s.\");\n"
6155 "if (list_index >= value_list.n_values)\n"
6156 "TTCN_error(\"Index overflow in a value list template of type "
6157 "%s.\");\n"
6158 "return value_list.list_value[list_index];\n"
6159 "}\n\n", name, name, dispname, dispname);
6160
6161 /* log function */
6162 def = mputstr(def, "void log() const;\n");
6163 src = mputprintf(src, "void %s_template::log() const\n"
6164 "{\n"
6165 "switch (template_selection) {\n"
6166 "case SPECIFIC_VALUE:\n"
6167 "TTCN_Logger::log_event_str(\"{ }\");\n"
6168 "break;\n"
6169 "case COMPLEMENTED_LIST:\n"
6170 "TTCN_Logger::log_event_str(\"complement \");\n"
6171 "case VALUE_LIST:\n"
6172 "TTCN_Logger::log_char('(');\n"
6173 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
6174 "list_count++) {\n"
6175 "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n"
6176 "value_list.list_value[list_count].log();\n"
6177 "}\n"
6178 "TTCN_Logger::log_char(')');\n"
6179 "break;\n"
6180 "default:\n"
6181 "log_generic();\n"
6182 "}\n"
6183 "log_ifpresent();\n"
6184 "}\n\n", name);
6185
6186 /* log_match function */
6187 def = mputprintf(def, "void log_match(const %s& match_value) const;\n",
6188 name);
6189 src = mputprintf(src, "void %s_template::log_match(const %s& match_value) "
6190 "const\n"
6191 "{\n"
6192 "match_value.log();\n"
6193 "TTCN_Logger::log_event_str(\" with \");\n"
6194 "log();\n"
6195 "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n"
6196 "else TTCN_Logger::log_event_str(\" unmatched\");\n"
6197 "}\n\n", name, name);
6198
6199 /* encode_text function */
6200 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
6201 src = mputprintf(src, "void %s_template::encode_text(Text_Buf& text_buf) "
6202 "const\n"
6203 "{\n"
6204 "encode_text_base(text_buf);\n"
6205 "switch (template_selection) {\n"
6206 "case OMIT_VALUE:\n"
6207 "case ANY_VALUE:\n"
6208 "case ANY_OR_OMIT:\n"
6209 "case SPECIFIC_VALUE:\n"
6210 "break;\n"
6211 "case VALUE_LIST:\n"
6212 "case COMPLEMENTED_LIST:\n"
6213 "text_buf.push_int(value_list.n_values);\n"
6214 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
6215 "list_count++)\n"
6216 "value_list.list_value[list_count].encode_text(text_buf);\n"
6217 "break;\n"
6218 "default:\n"
6219 "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported "
6220 "template of type %s.\");\n"
6221 "}\n"
6222 "}\n\n", name, dispname);
6223
6224 /* decode_text function */
6225 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
6226 src = mputprintf(src, "void %s_template::decode_text(Text_Buf& text_buf)\n"
6227 "{\n"
6228 "clean_up();\n"
6229 "decode_text_base(text_buf);\n"
6230 "switch (template_selection) {\n"
6231 "case OMIT_VALUE:\n"
6232 "case ANY_VALUE:\n"
6233 "case ANY_OR_OMIT:\n"
6234 "case SPECIFIC_VALUE:\n"
6235 "break;\n"
6236 "case VALUE_LIST:\n"
6237 "case COMPLEMENTED_LIST:\n"
6238 "value_list.n_values = text_buf.pull_int().get_val();\n"
6239 "value_list.list_value = new %s_template[value_list.n_values];\n"
6240 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
6241 "list_count++)\n"
6242 "value_list.list_value[list_count].decode_text(text_buf);\n"
6243 "break;\n"
6244 "default:\n"
6245 "TTCN_error(\"Text decoder: An unknown/unsupported selection was "
6246 "received in a template of type %s.\");\n"
6247 "}\n"
6248 "}\n\n", name, name, dispname);
6249
6250 /* set_param() */
6251 def = mputstr(def, "void set_param(const Module_Param& param);\n");
6252 src = mputprintf(src,
6253 "void %s_template::set_param(const Module_Param& param)\n"
6254 "{\n"
6255 " param.basic_check(Module_Param::BC_TEMPLATE, \"empty record/set template\");\n"
6256 " switch (param.get_type()) {\n"
6257 " case Module_Param::MP_Omit:\n"
6258 " *this = OMIT_VALUE;\n"
6259 " break;\n"
6260 " case Module_Param::MP_Any:\n"
6261 " *this = ANY_VALUE;\n"
6262 " break;\n"
6263 " case Module_Param::MP_AnyOrNone:\n"
6264 " *this = ANY_OR_OMIT;\n"
6265 " break;\n"
6266 " case Module_Param::MP_List_Template:\n"
6267 " case Module_Param::MP_ComplementList_Template:\n"
6268 " set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());\n"
6269 " for (size_t p_i=0; p_i<param.get_size(); p_i++) {\n"
6270 " list_item(p_i).set_param(*param.get_elem(p_i));\n"
6271 " }\n"
6272 " break;\n"
6273 " case Module_Param::MP_Value_List:\n"
6274 " if (param.get_size()>0) param.type_error(\"empty record/set template\", \"%s\");\n"
6275 " *this = NULL_VALUE;\n"
6276 " break;\n"
6277 " default:\n"
6278 " param.type_error(\"empty record/set template\", \"%s\");\n"
6279 " }\n"
6280 " is_ifpresent = param.get_ifpresent();\n"
6281 "}\n\n", name, dispname, dispname);
6282
6283 /* check template restriction */
6284 def = mputstr(def, "void check_restriction(template_res t_res, "
6285 "const char* t_name=NULL) const;\n");
6286 src = mputprintf(src,
6287 "void %s_template::check_restriction("
6288 "template_res t_res, const char* t_name) const\n"
6289 "{\n"
6290 "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
6291 "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
6292 "case TR_OMIT:\n"
6293 "if (template_selection==OMIT_VALUE) return;\n"
6294 "case TR_VALUE:\n"
6295 "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n"
6296 "return;\n"
6297 "case TR_PRESENT:\n"
6298 "if (!match_omit()) return;\n"
6299 "break;\n"
6300 "default:\n"
6301 "return;\n"
6302 "}\n"
6303 "TTCN_error(\"Restriction `%%s' on template of type %%s "
6304 "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n"
6305 "}\n\n", name, dispname);
6306
6307 defCommonRecordTemplate(name, &def, &src);
6308
6309 def = mputstr(def, "};\n\n");
6310
6311 output->header.class_defs = mputstr(output->header.class_defs, def);
6312 Free(def);
6313
6314 output->source.methods = mputstr(output->source.methods, src);
6315 Free(src);
6316 }
6317
6318 static void defCommonRecordTemplate(const char *name,
6319 char **def, char **src)
6320 {
6321 /* TTCN-3 ispresent() function */
6322 *def = mputstr(*def, "boolean is_present() const;\n");
6323 *src = mputprintf(*src,
6324 "boolean %s_template::is_present() const\n"
6325 "{\n"
6326 "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n"
6327 "return !match_omit();\n"
6328 "}\n\n", name);
6329
6330 /* match_omit() */
6331 *def = mputstr(*def, "boolean match_omit() const;\n");
6332 *src = mputprintf(*src,
6333 "boolean %s_template::match_omit() const\n"
6334 "{\n"
6335 "if (is_ifpresent) return TRUE;\n"
6336 "switch (template_selection) {\n"
6337 "case OMIT_VALUE:\n"
6338 "case ANY_OR_OMIT:\n"
6339 "return TRUE;\n"
6340 "case VALUE_LIST:\n"
6341 "case COMPLEMENTED_LIST:\n"
6342 "for (unsigned int l_idx=0; l_idx<value_list.n_values; l_idx++)\n"
6343 "if (value_list.list_value[l_idx].match_omit())\n"
6344 "return template_selection==VALUE_LIST;\n"
6345 "return template_selection==COMPLEMENTED_LIST;\n"
6346 "default:\n"
6347 "return FALSE;\n"
6348 "}\n"
6349 "return FALSE;\n"
6350 "}\n\n", name);
6351 }
6352
6353 /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
6354
6355 void defRecordClass2(const struct_def *sdef, output_struct *output)
6356 {
6357 size_t i;
6358 size_t optional_num = 0;
6359 const char *name = sdef->name;
6360 char *def = NULL, *src = NULL;
6361
6362 boolean xer_needed = sdef->hasXer && enable_xer();
6363 boolean raw_needed = sdef->hasRaw && enable_raw();
6364 boolean has_optional = FALSE;
6365 boolean has_default = FALSE;
6366
6367 const char* base_class = (sdef->nElements==0) ? "Empty_Record_Type" : "Record_Type";
6368
6369 /* class declaration code */
6370 output->header.class_decls = mputprintf(output->header.class_decls,
6371 "class %s;\n", name);
6372
6373 /* class definition and source code */
6374 def=mputprintf(def, "class %s : public %s {\n", name, base_class);
6375
6376 /* data members */
6377 for (i = 0; i < sdef->nElements; i++) {
6378 if(sdef->elements[i].isOptional) {
6379 optional_num++;
6380 def = mputprintf(def, " OPTIONAL<%s> field_%s;\n",
6381 sdef->elements[i].type,
6382 sdef->elements[i].name);
6383 } else {
6384 def = mputprintf(def, " %s field_%s;\n",
6385 sdef->elements[i].type, sdef->elements[i].name);
6386 }
6387 }
6388 if (sdef->nElements) {
6389 def = mputprintf(def, " Base_Type* fld_vec[%lu];\n", (unsigned long)sdef->nElements);
6390 }
6391
6392 /* default constructor */
6393 if (sdef->nElements==0) {
6394 def = mputprintf(def, "public:\n"
6395 " %s();\n", name);
6396 src = mputprintf(src,
6397 "%s::%s() : Empty_Record_Type() {}\n\n",
6398 name, name);
6399 } else {
6400 def = mputstr(def, " void init_vec();\n");
6401 src = mputprintf(src, "void %s::init_vec() { ", name);
6402 for (i = 0; i < sdef->nElements; i++) {
6403 src = mputprintf(src, "fld_vec[%lu]=&field_%s; ",
6404 (unsigned long)i, sdef->elements[i].name);
6405 }
6406 src = mputstr(src, " }\n\n");
6407
6408 def = mputprintf(def, "public:\n"
6409 " %s();\n", name);
6410 src = mputprintf(src,
6411 "%s::%s() : Record_Type() { init_vec(); }\n\n", name, name);
6412 }
6413
6414 /* copy constructor */
6415 if (sdef->nElements) {
6416 def = mputprintf(def, " %s(const %s& other_value);\n", name, name);
6417 src = mputprintf(src, "%s::%s(const %s& other_value) : Record_Type(other_value)\n", name, name, name);
6418 src = mputstr(src, "{\n"
6419 " if(!other_value.is_bound()) "
6420 "TTCN_error(\"Copying an unbound record/set value.\");\n"
6421 "bound_flag = TRUE;\n");
6422 for (i = 0; i < sdef->nElements; i++) {
6423 src = mputprintf(src,
6424 "if (other_value.field_%s.is_bound() )\n"
6425 " field_%s = other_value.field_%s;\n",
6426 sdef->elements[i].name, sdef->elements[i].name,
6427 sdef->elements[i].name);
6428 }
6429
6430 src = mputstr(src, "init_vec();\n"
6431 "}\n\n");
6432 } else {
6433 def = mputprintf(def, " %s(const %s& other_value): %s(other_value) {}\n", name, name, base_class);
6434 }
6435
6436 if (sdef->nElements>0) { /* constructor by fields */
6437 def = mputprintf(def, " %s(", name);
6438 src = mputprintf(src, "%s::%s(", name, name);
6439 for (i = 0; i < sdef->nElements; i++) {
6440 char *tmp = NULL;
6441 if (i > 0) tmp = mputstr(tmp, ",\n ");
6442 if (sdef->elements[i].isOptional)
6443 tmp = mputprintf
6444 (tmp,
6445 "const OPTIONAL<%s>& par_%s",
6446 sdef->elements[i].type, sdef->elements[i].name);
6447 else
6448 tmp = mputprintf
6449 (tmp,
6450 "const %s& par_%s",
6451 sdef->elements[i].type, sdef->elements[i].name);
6452 def = mputstr(def, tmp);
6453 src = mputstr(src, tmp);
6454 Free(tmp);
6455 }
6456 def = mputstr(def, ");\n");
6457 src = mputprintf(src, ") : ");
6458 for (i = 0; i < sdef->nElements; i++) {
6459 if (i > 0) src = mputstr(src, ",\n ");
6460 src = mputprintf(src, "field_%s(par_%s)", sdef->elements[i].name,
6461 sdef->elements[i].name);
6462 }
6463 src = mputstr(src, "\n"
6464 "{\n"
6465 "init_vec();\n"
6466 "bound_flag = TRUE;\n"
6467 "}\n\n");
6468 } else { /* constructor from null */
6469 def = mputprintf(def, " %s(null_type) {bound_flag = TRUE;}\n", name);
6470 }
6471
6472 /* assignment operators */
6473 def = mputprintf(def, "inline %s& operator=(const %s& other_value) "
6474 "{ set_value(&other_value); return *this; }\n\n", name, name);
6475 if (sdef->nElements == 0) {
6476 def = mputprintf(def, "inline %s& operator=(null_type) "
6477 "{ bound_flag = TRUE; return *this; }\n", name);
6478 }
6479
6480 /* == operator */
6481 def = mputprintf(def, "inline boolean operator==(const %s& other_value) "
6482 "const { return is_equal(&other_value); }\n", name);
6483 /* != operator */
6484 def = mputprintf(def,
6485 " inline boolean operator!=(const %s& other_value) const\n"
6486 " { return !is_equal(&other_value); }\n\n", name);
6487
6488 for (i = 0; i < sdef->nElements; i++) {
6489 if(sdef->elements[i].isOptional)
6490 def = mputprintf
6491 (def,
6492 " inline OPTIONAL<%s>& %s()\n"
6493 " {return field_%s;}\n"
6494 " inline const OPTIONAL<%s>& %s() const\n"
6495 " {return field_%s;}\n",
6496 sdef->elements[i].type, sdef->elements[i].name,
6497 sdef->elements[i].name,
6498 sdef->elements[i].type, sdef->elements[i].name,
6499 sdef->elements[i].name);
6500 else def = mputprintf
6501 (def,
6502 " inline %s& %s()\n"
6503 " {return field_%s;}\n"
6504 " inline const %s& %s() const\n"
6505 " {return field_%s;}\n",
6506 sdef->elements[i].type, sdef->elements[i].name,
6507 sdef->elements[i].name, sdef->elements[i].type,
6508 sdef->elements[i].name, sdef->elements[i].name);
6509
6510 }
6511
6512 /* override virtual functions where needed */
6513 def = mputprintf(def,
6514 "Base_Type* clone() const { return new %s(*this); }\n"
6515 "const TTCN_Typedescriptor_t* get_descriptor() const;\n"
6516 "boolean is_set() const { return %s; }\n",
6517 name,
6518 (sdef->kind==SET) ? "TRUE" : "FALSE");
6519 src = mputprintf(src,
6520 "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n",
6521 name, name);
6522
6523 if (sdef->nElements > 0) {
6524
6525 /* field access functions */
6526 def = mputprintf(def,
6527 "Base_Type* get_at(int index_value) { return fld_vec[index_value]; }\n"
6528 "const Base_Type* get_at(int index_value) const { return fld_vec[index_value]; }\n\n"
6529 "int get_count() const { return %lu; }\n", (unsigned long)sdef->nElements);
6530
6531 /* override if there are optional fields */
6532 if (optional_num) {
6533 def = mputprintf(def,
6534 "int optional_count() const { return %lu; }\n", (unsigned long)optional_num);
6535 }
6536
6537 if (sdef->opentype_outermost)
6538 def = mputstr(def, "boolean is_opentype_outermost() const { return TRUE; }\n");
6539
6540 /* FIXME: use static member in Record_Type and initialize somewhere */
6541 if (default_as_optional)
6542 def = mputstr(def, "boolean default_as_optional() const { return TRUE; }\n");
6543
6544 for (i = 0; i < sdef->nElements; i++) {
6545 if (sdef->elements[i].isOptional) {
6546 has_optional = TRUE;
6547 break;
6548 }
6549 }
6550
6551 for (i = 0; i < sdef->nElements; i++) {
6552 if (sdef->elements[i].isDefault) {
6553 has_default = TRUE;
6554 break;
6555 }
6556 }
6557 def = mputstr(def,
6558 "static const TTCN_Typedescriptor_t* fld_descriptors[];\n"
6559 "const TTCN_Typedescriptor_t* fld_descr(int p_index) const;\n\n"
6560 "static const char* fld_names[];\n"
6561 "const char* fld_name(int p_index) const;\n\n");
6562
6563 src = mputprintf(src, "const TTCN_Typedescriptor_t* %s::fld_descriptors[] = ", name);
6564 for (i = 0; i < sdef->nElements; i++) {
6565 src = mputprintf(src, "%c &%s_descr_",
6566 (i ? ',' : '{'), sdef->elements[i].typedescrname);
6567 }
6568 src = mputstr(src, " };\n");
6569 src = mputprintf(src,
6570 "const TTCN_Typedescriptor_t* %s::fld_descr(int p_index) const "
6571 "{ return fld_descriptors[p_index]; }\n\n", name);
6572
6573 src = mputprintf(src, "const char* %s::fld_names[] = ", name);
6574 for (i = 0; i < sdef->nElements; i++) {
6575 src = mputprintf(src, "%c \"%s\"",
6576 (i ? ',' : '{'), sdef->elements[i].dispname);
6577 }
6578 src = mputstr(src, " };\n");
6579
6580 src = mputprintf(src,
6581 "const char* %s::fld_name(int p_index) const "
6582 "{ return fld_names[p_index]; }\n\n", name);
6583
6584 if (has_optional) {
6585 def = mputstr(def,
6586 "static const int optional_indexes[];\n"
6587 "const int* get_optional_indexes() const;\n\n");
6588 src = mputprintf(src, "const int %s::optional_indexes[] = { ", name);
6589 for (i = 0; i < sdef->nElements; i++) {
6590 if (sdef->elements[i].isOptional) {
6591 src = mputprintf(src, "%lu, ", (unsigned long)i);
6592 }
6593 }
6594 src = mputstr(src, "-1 };\n");
6595 src = mputprintf(src,
6596 "const int* %s::get_optional_indexes() const "
6597 "{ return optional_indexes; }\n\n", name);
6598 }
6599
6600 if (has_default) {
6601 def = mputstr(def,
6602 "static const default_struct default_indexes[];\n"
6603 "const default_struct* get_default_indexes() const;\n");
6604 src = mputprintf(src, "const Record_Type::default_struct %s::default_indexes[] = { ", name);
6605 for (i = 0; i < sdef->nElements; i++) {
6606 if (sdef->elements[i].isDefault) {
6607 src = mputprintf(src, "{%lu,&%s}, ",
6608 (unsigned long)i, sdef->elements[i].defvalname);
6609 }
6610 }
6611 src = mputstr(src, "{-1,NULL} };\n");
6612 src = mputprintf(src,
6613 "const Record_Type::default_struct* %s::get_default_indexes() const "
6614 "{ return default_indexes; }\n", name);
6615 }
6616
6617 if (raw_needed) {
6618 struct raw_option_struct *raw_options;
6619 boolean haslengthto, haspointer, hascrosstag, has_ext_bit;
6620 boolean generate_raw_function = FALSE;
6621
6622 raw_options = (struct raw_option_struct*)
6623 Malloc(sdef->nElements * sizeof(*raw_options));
6624
6625 set_raw_options(sdef, raw_options, &haslengthto,
6626 &haspointer, &hascrosstag, &has_ext_bit);
6627
6628 /* set the value of generate_raw_function: if the coding/decoding is too
6629 complex for this type then generate the functions, otherwise generate
6630 helper functions only which are called by the default RAW enc/dec
6631 functions */
6632 if (haslengthto || haspointer || hascrosstag) {
6633 generate_raw_function = TRUE;
6634 goto check_generate_end;
6635 }
6636 for (i = 0; i < sdef->nElements; i++) {
6637 if (raw_options[i].lengthto || raw_options[i].lengthof ||
6638 raw_options[i].lengthoffield || raw_options[i].pointerto ||
6639 raw_options[i].pointerof || raw_options[i].ptrbase ||
6640 raw_options[i].extbitgroup || raw_options[i].tag_type ||
6641 raw_options[i].delayed_decode || raw_options[i].nof_dependent_fields
6642 || raw_options[i].dependent_fields) {
6643 generate_raw_function = TRUE;
6644 goto check_generate_end;
6645 }
6646 }
6647 for (i = 0; i < sdef->nElements; i++) {
6648 if (raw_options[i].lengthof || raw_options[i].lengthoffield ||
6649 raw_options[i].nof_dependent_fields ||
6650 raw_options[i].dependent_fields) {
6651 generate_raw_function = TRUE;
6652 goto check_generate_end;
6653 }
6654 }
6655 if (sdef->raw.ext_bit_goup_num || sdef->raw.ext_bit_groups ||
6656 sdef->raw.lengthto || sdef->raw.lengthindex ||
6657 sdef->raw.taglist.nElements || sdef->raw.crosstaglist.nElements ||
6658 sdef->raw.presence.fieldnum || sdef->raw.presence.fields ||
6659 sdef->raw.member_name) {
6660 generate_raw_function = TRUE;
6661 goto check_generate_end;
6662 }
6663 for (i = 0; i < sdef->nElements; i++) {
6664 if (sdef->elements[i].hasRaw) {
6665 generate_raw_function = TRUE;
6666 goto check_generate_end;
6667 }
6668 }
6669 check_generate_end:
6670
6671 if (generate_raw_function) {
6672 def = mputprintf(def,
6673 "int RAW_encode(const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n"
6674 "virtual int RAW_encode_negtest(const Erroneous_descriptor_t *, const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n"
6675 "int RAW_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, "
6676 "int, raw_order_t, boolean no_err = FALSE, "
6677 "int sel_field = -1, boolean first_call = TRUE);\n");
6678 src = generate_raw_coding(src, sdef, raw_options, haspointer,
6679 hascrosstag, has_ext_bit);
6680 } else { /* generate helper functions for the default RAW enc/dec */
6681 if (has_ext_bit)
6682 def = mputstr(def,"boolean raw_has_ext_bit() const { return TRUE; }\n");
6683 }
6684 for (i = 0; i < sdef->nElements; i++) {
6685 Free(raw_options[i].lengthoffield);
6686 Free(raw_options[i].dependent_fields);
6687 }
6688 Free(raw_options);
6689 } /* if (raw_needed) */
6690
6691 if (xer_needed) { /* XERSTUFF codegen for record/SEQUENCE in RT2 */
6692 size_t num_attributes = 0;
6693
6694 /* XER descriptors needed because of the xer antipattern */
6695 def = mputstr(def,
6696 "static const XERdescriptor_t* xer_descriptors[];\n"
6697 "const XERdescriptor_t* xer_descr(int p_index) const;\n"
6698 "virtual boolean can_start_v(const char *name, const char *prefix, "
6699 "XERdescriptor_t const& xd, unsigned int flavor);\n"
6700 "static boolean can_start (const char *name, const char *prefix, "
6701 "XERdescriptor_t const& xd, unsigned int flavor);\n");
6702 src = mputprintf(src, "const XERdescriptor_t* %s::xer_descriptors[] = ", name);
6703 for (i = 0; i < sdef->nElements; i++) {
6704 src = mputprintf(src, "%c &%s_xer_",
6705 (i ? ',' : '{'), sdef->elements[i].typegen);
6706 }
6707 src = mputstr(src, " };\n");
6708 src = mputprintf(src,
6709 "const XERdescriptor_t* %s::xer_descr(int p_index) const "
6710 "{ return xer_descriptors[p_index]; }\n"
6711 /* The virtual can_start_v hands off to the static can_start.
6712 * We must make a virtual call in Record_Type::XER_decode because
6713 * we don't know the actual type (derived from Record_Type) */
6714 "boolean %s::can_start_v(const char *p_name, const char *p_uri, "
6715 "XERdescriptor_t const& p_td, unsigned int p_flavor)\n"
6716 "{ return can_start(p_name, p_uri, p_td, p_flavor); }\n"
6717 "boolean %s::can_start(const char *p_name, const char *p_uri, "
6718 "XERdescriptor_t const& p_td, unsigned int p_flavor) {\n"
6719 " boolean e_xer = is_exer(p_flavor);\n"
6720 " if (!e_xer || (!(p_td.xer_bits & UNTAGGED) && !(p_flavor & USE_NIL))) return check_name(p_name, p_td, e_xer) && (!e_xer || check_namespace(p_uri, p_td));\n"
6721 , name , name, name);
6722 for (i = 0; i < sdef->nElements; i++) {
6723 src = mputprintf(src,
6724 " else if (%s::can_start(p_name, p_uri, %s_xer_, p_flavor)) return true;\n"
6725 , sdef->elements[i].type, sdef->elements[i].typegen);
6726 }
6727 src = mputstr(src,
6728 " return false;\n"
6729 "}\n\n");
6730 /* end of antipattern */
6731
6732 /* calculate num_attributes in compile time */
6733 for ( i=0; i < sdef->nElements; ++i ) {
6734 if (sdef->elements[i].xerAttribute
6735 ||(sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) ++num_attributes;
6736 else if (num_attributes) break;
6737 }
6738
6739 /* generate helper virtual functions for XER encdec */
6740 if (num_attributes) {
6741 def = mputprintf(def,
6742 "int get_xer_num_attr() const { return %lu; }\n",
6743 (unsigned long)num_attributes);
6744 }
6745 }
6746 else { /* XER not needed */
6747 def = mputstr(def,
6748 "boolean can_start_v(const char *, const char *, XERdescriptor_t const&, unsigned int)\n"
6749 "{ return FALSE; }\n"
6750 );
6751 } /* if (xer_needed) */
6752 } /* if (sdef->nElements > 0) */
6753
6754 /* end of class definition */
6755 def = mputstr(def, "};\n\n");
6756
6757 output->header.class_defs = mputstr(output->header.class_defs, def);
6758 Free(def);
6759
6760 output->source.methods = mputstr(output->source.methods, src);
6761 Free(src);
6762 }
6763
6764 void defRecordTemplate2(const struct_def *sdef, output_struct *output)
6765 {
6766 int i;
6767 const char *name = sdef->name;
6768 char *def = NULL, *src = NULL;
6769
6770 const char* base_class = (sdef->nElements==0) ? "Empty_Record_Template" : "Record_Template";
6771
6772 /* class declaration */
6773 output->header.class_decls = mputprintf(output->header.class_decls,
6774 "class %s_template;\n", name);
6775
6776 /* template class definition */
6777 def = mputprintf(def, "class %s_template : public %s {\n", name, base_class);
6778
6779 if (sdef->nElements>0) {
6780 /* set_specific function (used in field access members) */
6781 def = mputstr(def, "void set_specific();\n");
6782 src = mputprintf(src, "void %s_template::set_specific()\n"
6783 "{\n"
6784 "if (template_selection != SPECIFIC_VALUE) {\n"
6785 "%s"
6786 "clean_up();\n"
6787 "single_value.n_elements = %lu;\n"
6788 "single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);\n"
6789 "set_selection(SPECIFIC_VALUE);\n",
6790 name, sdef->nElements ? "boolean was_any = (template_selection == ANY_VALUE || template_selection == ANY_OR_OMIT);\n" : "",
6791 (unsigned long)sdef->nElements);
6792 for (i = 0; i < sdef->nElements; i++) {
6793 src = mputprintf(src,
6794 "single_value.value_elements[%d] = was_any ? new %s_template(%s) : new %s_template;\n",
6795 i, sdef->elements[i].type,
6796 sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE",
6797 sdef->elements[i].type);
6798 }
6799 src = mputstr(src,
6800 "}\n"
6801 "}\n\n");
6802 }
6803
6804 /* default constructor */
6805 def = mputprintf(def, "public:\n"
6806 "%s_template(): %s() {}\n", name, base_class);
6807
6808 if (sdef->nElements==0) {
6809 /* ctor for value {} */
6810 def = mputprintf(def, "%s_template(null_type) : "
6811 "Empty_Record_Template() { set_selection(SPECIFIC_VALUE); }\n",
6812 name);
6813 }
6814
6815 /* constructor t1_template(template_sel other_value) */
6816 def = mputprintf(def, "%s_template(template_sel other_value): "
6817 "%s(other_value) {}\n", name, base_class);
6818
6819 /* constructor t1_template(const t1& other_value) */
6820 def = mputprintf(def, "%s_template(const %s& other_value): "
6821 "%s() { copy_value(&other_value); }\n",
6822 name, name, base_class);
6823
6824 /* constructor t1_template(const OPTIONAL<t1>& other_value) */
6825 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value): "
6826 "%s() { copy_optional(&other_value); }\n",
6827 name, name, base_class);
6828
6829 /* copy constructor */
6830 def = mputprintf(def, "%s_template(const %s_template& other_value): %s() "
6831 "{ copy_template(other_value); }\n", name, name, base_class);
6832
6833 /* assignment operator <- template_sel */
6834 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
6835 name);
6836 src = mputprintf(src,
6837 "%s_template& %s_template::operator=(template_sel other_value)\n"
6838 "{\n"
6839 "check_single_selection(other_value);\n"
6840 "clean_up();\n"
6841 "set_selection(other_value);\n"
6842 "return *this;\n"
6843 "}\n\n", name, name);
6844
6845 /* assignment operator <- value */
6846 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
6847 name, name);
6848 src = mputprintf(src,
6849 "%s_template& %s_template::operator=(const %s& other_value)\n"
6850 "{\n"
6851 "clean_up();\n"
6852 "copy_value(&other_value);\n"
6853 "return *this;\n"
6854 "}\n\n", name, name, name);
6855
6856 /* assignment operator <- optional value */
6857 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
6858 "other_value);\n", name, name);
6859 src = mputprintf(src,
6860 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
6861 "{\n"
6862 "clean_up();\n"
6863 "copy_optional(&other_value);\n"
6864 "return *this;\n"
6865 "}\n\n", name, name, name);
6866
6867 /* assignment operator <- template*/
6868 def = mputprintf(def,
6869 "%s_template& operator=(const %s_template& other_value);\n",
6870 name, name);
6871 src = mputprintf(src,
6872 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
6873 "{\n"
6874 "if (&other_value != this) {\n"
6875 "clean_up();\n"
6876 "copy_template(other_value);\n"
6877 "}\n"
6878 "return *this;\n"
6879 "}\n\n", name, name, name);
6880
6881 if (sdef->nElements==0) {
6882 /* assignment op for value {} */
6883 def = mputprintf(def, "%s_template& operator=(null_type other_value);\n",
6884 name);
6885 src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n"
6886 "{\n"
6887 "clean_up();\n"
6888 "set_selection(SPECIFIC_VALUE);\n"
6889 "return *this;\n"
6890 "}\n\n", name, name);
6891 }
6892
6893 /* match operation (template matching) */
6894 def = mputprintf(def, "inline boolean match(const %s& other_value) const "
6895 "{ return matchv(&other_value); }\n", name);
6896
6897 /* log_match */
6898 def = mputprintf(def, "inline void log_match(const %s& match_value) const "
6899 "{ log_matchv(&match_value); }\n", name);
6900
6901 /* valueof operation */
6902 def = mputprintf(def, "%s valueof() const;\n", name);
6903
6904 src = mputprintf(src, "%s %s_template::valueof() const\n"
6905 "{\n"
6906 "%s ret_val;\n"
6907 "valueofv(&ret_val);\n"
6908 "return ret_val;\n"
6909 "}\n\n", name, name, name);
6910
6911 /* list_item(int) function */
6912
6913 def = mputprintf(def,
6914 "inline %s_template& list_item(unsigned int list_index) const "
6915 "{ return *(static_cast<%s_template*>(get_list_item(list_index))); }\n", name, name);
6916
6917 if (sdef->nElements>0) {
6918 /* template field access functions (non-const & const) */
6919 for (i = 0; i < sdef->nElements; i++) {
6920 def = mputprintf(def,
6921 "%s_template& %s();\n"
6922 "const %s_template& %s() const;\n",
6923 sdef->elements[i].type, sdef->elements[i].name,
6924 sdef->elements[i].type, sdef->elements[i].name);
6925 src = mputprintf(src,
6926 "%s_template& %s_template::%s() { return *(static_cast<%s_template*>(get_at(%d))); }\n"
6927 "const %s_template& %s_template::%s() const { return *(static_cast<const %s_template*>(get_at(%d))); }\n",
6928 sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i,
6929 sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i);
6930 }
6931 }
6932
6933 /* virtual functions */
6934 def = mputprintf(def,
6935 "%s* create() const { return new %s_template; }\n"
6936 "const TTCN_Typedescriptor_t* get_descriptor() const;\n",
6937 base_class, name);
6938 src = mputprintf(src,
6939 "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const { return &%s_descr_; }\n",
6940 name, name);
6941
6942 if (sdef->nElements>0) {
6943 def = mputprintf(def, "const char* fld_name(int p_index) const;\n");
6944 src = mputprintf(src,
6945 "const char* %s_template::fld_name(int p_index) const { return %s::fld_names[p_index]; }\n",
6946 name, name);
6947 }
6948
6949 def = mputstr(def, "};\n\n");
6950
6951 output->header.class_defs = mputstr(output->header.class_defs, def);
6952 Free(def);
6953
6954 output->source.methods = mputstr(output->source.methods, src);
6955 Free(src);
6956 }
6957
This page took 0.394828 seconds and 4 git commands to generate.