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