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