Sync with 5.4.2
[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
3f84031e 1918 if (want_namespaces && (start_at < sdef->nElements)) { /* there _are_ non-special members */
970ed795
EL
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");
3f84031e 2012
2013 /* First, the EMBED-VALUES member as an ordinary member if not doing EXER */
970ed795
EL
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
3f84031e 2068 , sdef->elements[i].xerAttribute || (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT) ? "if (!e_xer) " : ""
970ed795
EL
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) */
3f84031e 2099 " if (%s%s%s field_%s%s.size_of() > 0) {\n"
2100 " sub_len += field_%s%s[0].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
af710487 2101 " }\n"
970ed795 2102 " }\n"
3f84031e 2103 , sdef->elements[0].dispname
2104 , sdef->elements[0].isOptional ? "field_" : ""
2105 , sdef->elements[0].isOptional ? sdef->elements[0].name : ""
2106 , sdef->elements[0].isOptional ? ".ispresent() &&" : ""
2107 , sdef->elements[0].name
2108 , sdef->elements[0].isOptional ? "()" : "", sdef->elements[0].name
2109 , sdef->elements[0].isOptional ? "()" : "");
970ed795
EL
2110 if (want_namespaces) { /* here's another chance */
2111 src = mputprintf(src,
2112 " else if ( !(p_td.xer_bits & EMBED_VALUES)) {\n"
af710487 2113 " %sfield_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n"
970ed795
EL
2114 " }\n"
2115 , ((sdef->elements[0].xerAnyKind & ANY_ATTRIB_BIT) ? "" : "sub_len += " )
2116 , sdef->elements[0].name, sdef->elements[0].typegen
2117 );
2118 }
2119 }
2120
2121 /* Then, all the non-attributes. Structuring the code like this depends on
2122 * all attributes appearing before all non-attributes (excluding
2123 * special members for EMBED-VALUES, USE-ORDER, etc.) */
af710487 2124 if (sdef->xerEmbedValuesPossible) {
2125 src = mputprintf(src,
2126 " embed_values_enc_struct_t* emb_val = 0;\n"
3f84031e 2127 " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && "
2128 " %s%s%s field_%s%s.size_of() > 1) {\n"
af710487 2129 " emb_val = new embed_values_enc_struct_t;\n"
a38c6d4c 2130 /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated
2131 * record of universal charstring, so it needs a cast to avoid a compilation error */
3f84031e 2132 " emb_val->embval_array%s = (const PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s%s;\n"
a38c6d4c 2133 " emb_val->embval_array%s = NULL;\n"
af710487 2134 " emb_val->embval_index = 1;\n"
a38c6d4c 2135 " }\n"
3f84031e 2136 , sdef->elements[0].isOptional ? "field_" : ""
2137 , sdef->elements[0].isOptional ? sdef->elements[0].name : ""
2138 , sdef->elements[0].isOptional ? ".ispresent() &&" : ""
a38c6d4c 2139 , sdef->elements[0].name
3f84031e 2140 , sdef->elements[0].isOptional ? "()" : ""
a38c6d4c 2141 , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg"
2142 , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : ""
2143 , sdef->elements[0].name
3f84031e 2144 , sdef->elements[0].isOptional ? "()" : ""
a38c6d4c 2145 , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt");
af710487 2146 }
2147
970ed795
EL
2148 if (sdef->xerUseOrderPossible) {
2149 int max_ordered = sdef->nElements - start_at - num_attributes;
2150 int min_ordered = max_ordered - n_opt_elements;
2151 size_t offset = 0;
2152 size_t base = i;
2153 size_t limit = sdef->nElements;
2154 /* base and limit are indexes into sdef->elements[] */
2155 src = mputprintf(src,
2156 " int dis_order = e_xer && (p_td.xer_bits & USE_ORDER);\n"
2157 " int to_send = field_%s.lengthof();\n"
2158 " int uo_limit = dis_order ? to_send : %lu;\n"
2159 , sdef->elements[start_at-1].name
2160 , (unsigned long)(limit - base)
2161 );
2162 if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */
2163 base = sdef->nElements;
2164 limit = sdef->totalElements;
2165 min_ordered = max_ordered = limit - base;
2166 src = mputprintf(src,
2167 " if (!nil_attribute) {\n"
2168 "%s"
af710487 2169 " if (!e_xer) sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, 0);\n"
970ed795
EL
2170 " else" /* no newline */
2171 , (sdef->xerUseNilPossible ? " if (!(p_td.xer_bits & USE_ORDER)) p_flavor |= (p_td.xer_bits & USE_NIL);\n" : "")
2172 /* If USE-ORDER is on, the tag-removing effect of USE-NIL has been
2173 * performed by calling the sub-fields directly. */
2174 , sdef->elements[sdef->nElements-1].name
2175 , sdef->elements[sdef->nElements-1].typegen
2176 );
2177 }
2178
2179 /* check incorrect data */
2180 src = mputprintf(src,
2181 " {\n"
2182 " if (to_send < %d || to_send > %d) {\n"
2183 " ec_1.set_msg(\"%s': \");\n"
2184 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, "
2185 "\"Wrong number of USE-ORDER, %%d instead of %d..%d\", to_send);\n"
2186 " uo_limit = -1;\n" /* squash the loop */
2187 " }\n"
2188 " else {\n" /* check duplicates */
2189 " int *seen = new int [to_send];\n"
2190 " int num_seen = 0;\n"
2191 " for (int ei = 0; ei < to_send; ++ei) {\n"
2192 " int val = field_%s[ei];\n"
2193 " for (int x = 0; x < num_seen; ++x) {\n"
2194 " if (val == seen[x]) { // complain\n"
2195 " ec_1.set_msg(\"%s': \");\n"
2196 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n"
2197 " \"Duplicate value for USE-ORDER\");\n"
2198 " uo_limit = -1; // don't bother sending anything\n"
2199 " goto trouble;\n"
2200 " }\n"
2201 " }\n"
2202 " seen[num_seen++] = val;\n"
2203 " }\n"
2204 "trouble:\n"
2205 " delete [] seen;"
2206 " }\n"
2207 " "
2208 , min_ordered, max_ordered
2209 , sdef->elements[start_at-1].dispname
2210 , min_ordered, max_ordered
2211 , sdef->elements[start_at-1].name
2212 , sdef->elements[start_at-1].dispname
2213 );
2214
2215 src = mputprintf(src,
2216 " for (int i = 0; i < uo_limit; ++i) {\n"
2217 " switch (dis_order ? (int)field_%s[i] : i) {\n"
2218 , sdef->elements[start_at-1].name
2219 );
2220 for ( i = base; i < limit; ++i ) {
2221 src = mputprintf(src,
2222 " case %lu:\n"
2223 " ec_1.set_msg(\"%s': \");\n"
af710487 2224 " sub_len += field_%s%s%s%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, %s);\n"
970ed795
EL
2225
2226 , (unsigned long)offset++
2227 , sdef->elements[i].dispname
2228 , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name : sdef->elements[i].name)
2229 , (sdef->xerUseNilPossible ? "()." : "")
2230 , (sdef->xerUseNilPossible ? sdef->elements[i].name : "")
2231 , (sdef->xerUseNilPossible ? "()" : "")
2232 , sdef->elements[i].typegen
af710487 2233 , sdef->xerEmbedValuesPossible ? "emb_val" : "0"
970ed795
EL
2234 );
2235
2236 src = mputstr(src, " break;\n");
2237 } /* next element */
2238 src = mputstr(src,
2239 " default:\n"
2240 " TTCN_error(\"Runaway value while encoding USE-ORDER\");\n"
2241 " break;\n" /* cannot happen, complain */
2242 " }\n");
2243
2244 if (sdef->xerEmbedValuesPossible) {
2245 src = mputprintf(src,
af710487 2246 " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n"
3f84031e 2247 " %s%s%s emb_val->embval_index < field_%s%s.size_of()) { // embed-val\n"
2248 " field_%s%s[emb_val->embval_index].XER_encode(\n"
af710487 2249 " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
2250 " ++emb_val->embval_index;\n"
970ed795 2251 " }\n"
3f84031e 2252 , sdef->elements[0].isOptional ? "field_" : ""
2253 , sdef->elements[0].isOptional ? sdef->elements[0].name : ""
2254 , sdef->elements[0].isOptional ? ".ispresent() &&" : ""
2255 , sdef->elements[0].name
2256 , sdef->elements[0].isOptional ? "()" : "", sdef->elements[0].name
2257 , sdef->elements[0].isOptional ? "()" : "");
970ed795
EL
2258 }
2259
2260
2261 src = mputstr(src,
2262 " }\n" /* end of loop */
2263 " } // exer\n");
2264 if (sdef->xerUseNilPossible) {
2265 src = mputstr(src, " } // nil_attr\n");
2266 }
2267 }
2268 else /* not USE-ORDER */
2269 for ( /* continue with i */; i < sdef->nElements; ++i ) {
2270 src = mputprintf(src,
2271 " ec_1.set_msg(\"%s': \");\n"
2272 , sdef->elements[i].dispname
2273 );
2274 src = mputprintf(src,
af710487 2275 " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor%s, p_indent+!omit_tag, %s);\n"
970ed795
EL
2276 , sdef->elements[i].name, sdef->elements[i].typegen
2277 , sdef->xerUseNilPossible ? "| (p_td.xer_bits & USE_NIL)" : ""
af710487 2278 , sdef->xerEmbedValuesPossible ? "emb_val" : "0"
970ed795
EL
2279 );
2280
2281 if (sdef->xerEmbedValuesPossible) {
970ed795 2282 src = mputprintf(src,
af710487 2283 " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n"
3f84031e 2284 " %s%s%s emb_val->embval_index < field_%s%s.size_of()) {\n"
2285 " field_%s%s[emb_val->embval_index].XER_encode(\n"
af710487 2286 " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n"
2287 " ++emb_val->embval_index;\n"
970ed795 2288 " }\n"
3f84031e 2289 , sdef->elements[0].isOptional ? "field_" : ""
2290 , sdef->elements[0].isOptional ? sdef->elements[0].name : ""
2291 , sdef->elements[0].isOptional ? ".ispresent() &&" : ""
2292 , sdef->elements[0].name
2293 , sdef->elements[0].isOptional ? "()" : "", sdef->elements[0].name
2294 , sdef->elements[0].isOptional ? "()" : "");
970ed795
EL
2295 }
2296 } /* next field when not USE-ORDER */
2297
af710487 2298 if (sdef->xerEmbedValuesPossible) {
2299 src = mputprintf(src,
2300 " if (0 != emb_val) {\n"
3f84031e 2301 " if (%s%s%s emb_val->embval_index < field_%s%s.size_of()) {\n"
af710487 2302 " ec_1.set_msg(\"%s': \");\n"
2303 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n"
2304 " \"Too many EMBED-VALUEs specified: %%d (expected %%d or less)\",\n"
3f84031e 2305 " field_%s%s.size_of(), emb_val->embval_index);\n"
af710487 2306 " }\n"
2307 " delete emb_val;\n"
2308 " }\n"
3f84031e 2309 , sdef->elements[0].isOptional ? "field_" : ""
2310 , sdef->elements[0].isOptional ? sdef->elements[0].name : ""
2311 , sdef->elements[0].isOptional ? ".ispresent() &&" : ""
2312 , sdef->elements[0].name, sdef->elements[0].isOptional ? "()" : ""
2313 , sdef->elements[0].name, sdef->elements[0].name
2314 , sdef->elements[0].isOptional ? "()" : "");
af710487 2315 }
2316
970ed795
EL
2317 src = mputstr(src, " } // QN?\n");
2318
2319 {
2320 src = mputprintf(src,
2321 " if (!omit_tag) {\n"
2322 " if (sub_len) {\n" /* something was written, now an end tag */
2323 " if (is_indented && !(e_xer && (p_td.xer_bits & (HAS_1UNTAGGED | USE_QNAME)))) {\n"
2324 " switch ((int)(e_xer && (p_td.xer_bits & USE_NIL))) {\n"
2325 " case 1: {\n"
2326 " const unsigned char *buf_end = p_buf.get_data() + (p_buf.get_len()-1);\n"
2327 " if (buf_end[-1] != '>' || *buf_end != '\\n') break;\n"
2328 /* else fall through */
2329 " }\n"
2330 " case 0:\n"
2331 " do_indent(p_buf, p_indent);\n"
2332 " break;\n"
2333 " }\n"
2334 " }\n"
2335 " p_buf.put_c('<');\n"
2336 " p_buf.put_c('/');\n"
2337 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
2338 " p_buf.put_s((size_t)p_td.namelens[e_xer]-!is_indented, (cbyte*)p_td.names[e_xer]);\n"
2339 " } else {\n" /* need to generate an empty element tag */
2340 " p_buf.increase_length(%s-1);\n" /* decrease length */
2341 " p_buf.put_s((size_t)2+is_indented, (cbyte*)\"/>\\n\");\n"
2342 " }}\n"
2343 , (sdef->xerUntaggedOne /*|| sdef->xerUseNil*/) ? "" : "-is_indented"
2344 );
2345 }
2346 src = mputstr(src,
2347 " return (int)p_buf.get_len() - encoded_length;\n"
2348 "}\n\n");
2349
2350#ifndef NDEBUG
2351 src = mputprintf(src, "// %s has%s%s%s%s%s%s%s%s%s\n"
2352 "// written by %s in " __FILE__ " at %d\n"
2353 , name
2354 , (sdef->xerUntagged ? " UNTAGGED" : "")
2355 , (sdef->xerUntaggedOne ? "1" : "")
2356 , (sdef->xerUseNilPossible ? " USE_NIL?" : "")
2357 , (sdef->xerUseOrderPossible ? " USE_ORDER?" : "")
2358 , (sdef->xerUseQName ? " USE_QNAME" : "")
2359 , (sdef->xerUseTypeAttr ? " USE_TYPE_ATTR" : "")
2360 , (sdef->xerUseUnion ? " USE-UNION" : "")
2361 , (sdef->xerHasNamespaces ? " namespace" : "")
2362 , (sdef->xerEmbedValuesPossible ? " EMBED?" : "")
2363 , __FUNCTION__, __LINE__
2364 );
2365#endif
2366
2367 src = mputprintf(src, /* XERSTUFF decodegen for record/SEQUENCE*/
2368 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader,"
af710487 2369 " unsigned int p_flavor, embed_values_dec_struct_t*)\n"
970ed795
EL
2370 "{\n"
2371 " bound_flag = TRUE;\n"
2372 /* Remove XER_LIST, XER_RECOF from p_flavor. This is not required
2373 * for is_exer (which tests another bit), but for subsequent code. */
2374 " int e_xer = is_exer(p_flavor);\n"
2375 " int xerbits = p_td.xer_bits;\n"
2376 " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n"
2377 " const boolean omit_tag = e_xer && ((xerbits & (UNTAGGED|XER_ATTRIBUTE)) "
2378 "|| (p_flavor & (USE_NIL|USE_TYPE_ATTR)));\n"
2379 "%s"
2380 " const boolean parent_tag = e_xer && (p_flavor & (USE_TYPE_ATTR));\n"
2381 " (void)parent_tag;\n"
2382 " p_flavor &= XER_MASK;\n" /* also removes "toplevel" bit */
2383 " int rd_ok, xml_depth=-1, type;\n"
2384 " {\n" /* scope for the error contexts */
2385 , name
2386 , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0)
2387 ? " boolean tag_closed = (p_flavor & PARENT_CLOSED) != 0;\n" : "")
2388 /* tag_closed needed for non-attribute normal members only,
2389 * or if EMBED-VALUES is possible, but isn't. */
2390 );
2391
2392 if (sdef->xerUseNilPossible) src = mputstr(src,
2393 " boolean nil_attribute = FALSE;\n");
2394
2395 src = mputprintf(src,
2396 " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n"
2397 " TTCN_EncDec_ErrorContext ec_1;\n"
2398 " if (!omit_tag) for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n"
2399 " type = p_reader.NodeType();\n"
2400 " if (type==XML_READER_TYPE_ELEMENT) {\n"
2401 " verify_name(p_reader, p_td, e_xer);\n"
2402 " xml_depth = p_reader.Depth();\n"
2403 "%s"
2404 " break;\n"
2405 " }\n"
2406 " }\n"
2407 , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0)
2408 ? " tag_closed = p_reader.IsEmptyElement();\n": "")
2409 );
2410
2411
2412 if (sdef->xerUseQName) {
2413 src = mputprintf(src,
2414 " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n"
2415 " if (p_td.xer_bits & XER_ATTRIBUTE) rd_ok = 1;\n"
2416 " else for (rd_ok = p_reader.Read(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
2417 " type = p_reader.NodeType();\n"
2418 " if (type == XML_READER_TYPE_TEXT) break;\n"
2419 " }\n"
2420 " if (rd_ok==1) {\n"
2421 " xmlChar *new_val = p_reader.NewValue();\n"
2422 " xmlChar *v_npfx = (xmlChar*)strchr((char*)new_val, ':');\n"
2423 " xmlChar *v_pfx;\n"
2424 " if (v_npfx != NULL) {\n"
2425 " *v_npfx++ = '\\0';\n"
2426 " v_pfx = new_val;\n"
2427 " }\n"
2428 " else {\n"
2429 " v_npfx = new_val;\n"
2430 " v_pfx = NULL;\n"
2431 " }\n"
2432 " xmlChar *q_ns = p_reader.LookupNamespace(v_pfx);\n"
2433 " if (q_ns) field_%s = (const char*)q_ns;\n"
2434 " else field_%s = OMIT_VALUE;\n"
2435 " field_%s = (const char*)v_npfx;\n"
2436 " xmlFree(q_ns);\n"
2437 " xmlFree(new_val);\n"
2438 " }\n"
2439 " } else {\n"
2440 , sdef->elements[0].name
2441 , sdef->elements[0].name
2442 , sdef->elements[1].name
2443 );
2444 } /* QName */
2445
2446 if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) {
2447 src = mputstr(src, "if (e_xer) {\n");
2448 }
2449
2450 /* ********************************************************************
2451 * ATTRIBUTES
2452 ***************************/
2453 if (num_attributes || sdef->xerUseNilPossible /* maybe QNAME too ? */) {
2454 size_t aaa;
2455 src = mputstr(src, " if (!omit_tag || parent_tag) {\n");
2456
2457 /* Prepare for attributes not present in the XML.
2458 * Set all attributes with defaultForEmpty to the D-F-E value.
2459 * Set all optional components with ATTRIBUTE to omit.
2460 *
2461 * If EMBED-VALUES is possible, the first component can't be optional.
2462 * The same is true for the USE-ORDER component. Hence start_at. */
2463 for (aaa = start_at; aaa < start_at + num_attributes; ++aaa) {
2464 if (sdef->elements[aaa].xerAttribute) { /* "proper" ATTRIBUTE */
2465 src = mputprintf(src,
2466 " if (%s_xer_.dfeValue) field_%s = "
2467 "*static_cast<const %s*>(%s_xer_.dfeValue);\n"
2468 , sdef->elements[aaa].typegen, sdef->elements[aaa].name
2469 , sdef->elements[aaa].type , sdef->elements[aaa].typegen);
2470 if (sdef->elements[aaa].isOptional) src = mputprintf(src,
2471 " else field_%s = OMIT_VALUE;\n", sdef->elements[aaa].name);
2472 }
2473 else { /* must be the ANY-ATTRIBUTES */
2474 src = mputprintf(src,
af710487 2475 " field_%s%s;\n"
2476 , sdef->elements[aaa].name
2477 , sdef->elements[aaa].isOptional ? " = OMIT_VALUE" : ".set_size(0)");
970ed795
EL
2478 }
2479 }
2480
2481 if (num_attributes==0 /* therefore sdef->xerUseNilPossible is true */ ) {
2482 /* Only the "nil" attribute may be present. If there is no USE-NIL,
2483 * then there can be no attributes at all. */
2484 src = mputstr(src,
2485 " if (e_xer && (p_td.xer_bits & (USE_NIL|USE_TYPE_ATTR))) {\n");
2486 }
2487
2488 if (aa_index > -1) src = mputstr(src, " size_t num_aa = 0;\n");
2489 if (sdef->xerUseNilPossible) {
2490 src = mputstr(src,
2491 " static const namespace_t *control_ns = p_td.my_module->get_controlns();\n");
2492 }
2493
2494 src = mputstr(src,
2495 " for (rd_ok = p_reader.MoveToFirstAttribute(); rd_ok==1 && "
2496 "p_reader.NodeType()==XML_READER_TYPE_ATTRIBUTE; "
2497 "rd_ok = p_reader.AdvanceAttribute()) {\n"
2498 " if (p_reader.IsNamespaceDecl()) continue;\n");
2499 /* if the only attribute is ANY-ATTRIBUTE, it doesn't need attr_name */
2500 if (num_attributes==1 && aa_index!=-1 /*&& !sdef->xerUseNilPossible*/) {}
2501 else {
2502 src = mputstr(src,
2503 " const char *attr_name = (const char*)p_reader.LocalName();\n"
2504 " const char *ns_uri = (const char*)p_reader.NamespaceUri();\n");
2505 }
2506
2507 if (sdef->xerUseNilPossible) {
2508 src = mputprintf(src,
2509 " const char *prefix = (const char*)p_reader.Prefix();\n"
2510 /* prefix may be NULL, control_ns->px is never NULL or empty */
2511 " if (prefix && !strcmp(prefix, control_ns->px)\n"
2512 " && !strcmp((const char*)p_reader.LocalName(), \"nil\")){\n"
2513 " const char *value = (const char*)p_reader.Value();\n"
2514 " if (!strcmp(value, \"1\") || !strcmp(value, \"true\")) {\n"
2515 " field_%s = OMIT_VALUE;\n"
2516 " nil_attribute = TRUE;\n"
2517 /* found the "nil" attribute */
2518 " }\n"
2519 " } else"
2520 , sdef->elements[sdef->nElements-1].name);
2521 }
2522
2523 for (i = start_at; i < start_at + num_attributes; ++i) {
2524 if (i == aa_index) continue; /* ANY_ATTR. is handled below */
2525 src = mputprintf(src,
2526 " if (check_name(attr_name, %s_xer_, 1) && check_namespace(ns_uri, %s_xer_)) {\n"
2527 " ec_1.set_msg(\"%s': \");\n"
af710487 2528 " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), 0);\n"
970ed795
EL
2529 " } else"
2530 , sdef->elements[i].typegen, sdef->elements[i].typegen
2531 , sdef->elements[i].dispname /* set_msg */
2532 , sdef->elements[i].name, sdef->elements[i].typegen
2533 );
2534 }
2535
2536 if (sdef->control_ns_prefix && !(num_attributes==1 && aa_index!=-1)) {
2537 src = mputprintf(src,
2538 " if (parent_tag && !strcmp(attr_name, \"type\") "
2539 "&& !strcmp((const char*)p_reader.Prefix(), \"%s\")) {} else\n"
2540 , sdef->control_ns_prefix);
2541 /* xsi:type; already processed by parent with USE-UNION or USE-TYPE */
2542 }
2543
2544
2545 if (aa_index >= 0) {
2546 /* we are at a dangling else */
2547 src = mputprintf(src,
2548 " {\n"
af710487 2549 " TTCN_EncDec_ErrorContext ec_0(\"Attribute %%d: \", (int)num_aa);\n"
2550 " UNIVERSAL_CHARSTRING& new_elem = field_%s%s[num_aa++];\n"
970ed795
EL
2551 /* Construct the AnyAttributeFormat (X.693amd1, 18.2.6) */
2552 " TTCN_Buffer aabuf;\n"
2553 " const xmlChar *x_name = p_reader.LocalName();\n"
2554 " const xmlChar *x_val = p_reader.Value();\n"
2555 " const xmlChar *x_uri = p_reader.NamespaceUri();\n"
2556 " if (%s_xer_.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n"
2557 " check_namespace_restrictions(%s_xer_, (const char*)x_uri);\n"
2558 " }\n"
2559 /* We don't care about p_reader.Prefix() */
2560 /* Using strlen to count bytes */
2561 " aabuf.put_s(x_uri ? strlen((const char*)x_uri) : 0, x_uri);\n"
2562 " if (x_uri && *x_uri) aabuf.put_c(' ');\n"
2563 " aabuf.put_s(x_name ? strlen((const char*)x_name) : 0, x_name);\n"
2564 " aabuf.put_c('=');\n"
2565 " aabuf.put_c('\"');\n"
2566 " aabuf.put_s(x_val ? strlen((const char*)x_val) : 0, x_val);\n"
2567 " aabuf.put_c('\"');\n"
2568 " new_elem.decode_utf8(aabuf.get_len(), aabuf.get_data());\n"
2569 " } \n"
2570 , sdef->elements[aa_index].name
af710487 2571 , sdef->elements[aa_index].isOptional ? "()" : ""
970ed795
EL
2572 , sdef->elements[aa_index].typegen, sdef->elements[aa_index].typegen
2573 );
2574 }
2575 else {
2576 /* we are at a dangling else */
2577 src = mputstr(src, " {\n");
2578 if (sdef->control_ns_prefix) {
2579 src = mputprintf(src,
2580 // Lastly check for the xsi:schemaLocation attribute, this does not
2581 // affect TTCN-3, but it shouldn't cause a DTE
2582 " if (!p_reader.LocalName() || strcmp((const char*)p_reader.LocalName(), \"schemaLocation\") ||\n"
2583 " !p_reader.Prefix() || strcmp((const char*)p_reader.Prefix(), \"%s\"))\n"
2584 , sdef->control_ns_prefix);
2585 }
2586 src = mputstr(src,
2587 " {\n"
2588 " ec_0.set_msg(\" \"); ec_1.set_msg(\" \");\n" /* we have no component */
2589 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
2590 "\"Unexpected attribute '%s', ns '%s'\", attr_name, ns_uri ? ns_uri : \"\");\n"
2591 " }\n"
2592 " }\n");
2593 }
2594 src = mputstr(src, " }\n"); /* for */
2595
2596 for (i = start_at; i < start_at + num_attributes; ++i) {
2597 if (sdef->elements[i].isOptional) continue; /* allowed to be missing */
2598 src = mputprintf(src, " if (!field_%s.is_bound()) "
2599 "TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
2600 "\"Missing attribute '%s'\");\n"
2601 , sdef->elements[i].name, sdef->elements[i].dispname);
2602 }
2603
2604 if (num_attributes==0) src = mputstr(src, " }\n"); /* if USE_NIL or USE_TYPE_ATTR */
2605 src = mputstr(src, " }\n"); /* process (attributes) in (own or parent) tag */
2606 } /* * * * * * * * * end if(attributes...) * * * * * * * * * * * * */
2607
2608 src = mputstr(src,
2609 " if ((!omit_tag || parent_tag) && !p_reader.IsEmptyElement()) "
2610 "rd_ok = p_reader.Read();\n");
2611
2612 if (sdef->xerEmbedValuesPossible && num_attributes==0) {
2613 /* EMBED-VALUES possible, but isn't: the first component is a non-special
2614 * record of strings. This means there are no attributes, unless
2615 * the first component is an ATTRIBUTE or ANY-ATTRIBUTES. */
2616 src = mputprintf(src,
2617 " if (!(p_td.xer_bits & EMBED_VALUES)) {\n"
2618 " ec_1.set_msg(\"%s': \");\n"
2619 " field_%s.XER_decode(%s_xer_, p_reader, "
3f84031e 2620 "p_flavor | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : XER_NONE), 0);\n"
970ed795
EL
2621 " }\n"
2622 , sdef->elements[0].dispname
2623 , sdef->elements[0].name, sdef->elements[0].typegen
2624 );
2625 }
2626
2627 if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) {
2628 src = mputstr(src,
2629 "} else {\n" /* now the non-EXER processing of (would-be) attributes */
2630 " if (!p_reader.IsEmptyElement()) p_reader.Read();\n"
2631 );
2632 }
2633
2634 if (sdef->xerUseOrderPossible) {
2635 src = mputstr(src,
2636 " if (e_xer && p_td.xer_bits & USE_ORDER) ; else {");
2637 }
2638
2639 if (start_at + num_attributes > 0)
2640 {
2641 /* No attributes nor USE-NIL:
2642 * Just decode the specials and would-be attributes. */
2643
2644 // FIXME: WTF is this?
2645 //if (sdef->xerEmbedValuesPossible) {
2646 // /* Only decode the first member if it really is EMBED-VALUES */
2647 // src = mputprintf(src, "if (p_td.xer_bits & EMBED_VALUES) ");
2648 //}
2649 for (i = 0; i < start_at + num_attributes; ++i) {
2650 /* Decode the field */
2651 src = mputprintf(src,
2652 " {\n"
2653 " ec_1.set_msg(\"%s': \");\n"
af710487 2654 " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), 0);\n"
970ed795
EL
2655 " }\n"
2656 , sdef->elements[i].dispname
2657 , sdef->elements[i].name, sdef->elements[i].typegen
2658 );
2659 } /* next field */
2660
2661 if (sdef->xerUseOrderPossible) {
2662 src = mputstr(src, " }\n");
2663 }
2664 }
2665
2666 if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) {
2667 src = mputstr(src, "}\n");
2668 }
af710487 2669
2670 if (sdef->xerEmbedValuesPossible) {
2671 src = mputprintf(src,
2672 " embed_values_dec_struct_t* emb_val = 0;\n"
2673 " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n"
2674 " emb_val = new embed_values_dec_struct_t;\n"
a38c6d4c 2675 /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated
2676 * record of universal charstring, so it needs a cast to avoid a compilation error */
3f84031e 2677 " emb_val->embval_array%s = (PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s%s;\n"
a38c6d4c 2678 " emb_val->embval_array%s = NULL;\n"
af710487 2679 " emb_val->embval_index = 0;\n"
3f84031e 2680 " field_%s%s.set_size(0);\n"
a38c6d4c 2681 " }\n"
2682 , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg"
2683 , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : ""
2684 , sdef->elements[0].name
3f84031e 2685 , sdef->elements[0].isOptional ? "()" : ""
a38c6d4c 2686 , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt"
3f84031e 2687 , sdef->elements[0].name
2688 , sdef->elements[0].isOptional ? "()" : "");
af710487 2689 }
970ed795
EL
2690
2691 if (sdef->xerUseOrderPossible) {
2692 size_t begin = start_at + num_attributes; /* first non-attribute */
2693 size_t end = sdef->nElements;
2694 size_t n_optionals = 0, n_embed;
2695 int max_ordered = sdef->nElements - start_at - num_attributes;
2696 int min_ordered = max_ordered - n_opt_elements;
2697 if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */
2698 begin = sdef->nElements;
2699 end = sdef->totalElements;
2700 }
2701 n_embed = end - begin;
2702
2703 src = mputstr(src,
2704 " if (e_xer && (p_td.xer_bits & USE_ORDER)) {\n"
2705 );
2706 for (i = begin; i < end; ++i) {
2707 if (sdef->elements[i].isOptional) {
2708 src = mputprintf(src, " field_%s = OMIT_VALUE;\n",
2709 sdef->elements[i].name);
2710 ++n_optionals;
2711 }
2712 }
2713
970ed795
EL
2714 if (sdef->xerUseNilPossible) { /* USE-NIL and USE-ORDER */
2715 src = mputprintf(src,
2716 " if (nil_attribute) field_%s.set_size(0);\n else"
2717 , sdef->elements[uo].name);
2718 }
2719
2720 src = mputprintf(src,
2721 " {\n"
2722 " field_%s.set_size(0);\n"
3abe9331 2723 " if (!tag_closed) {\n" /* Nothing to order if there are no child elements */
970ed795 2724 " int e_val, num_seen = 0, *seen_f = new int[%lu];\n"
970ed795
EL
2725 , sdef->elements[uo].name
2726 , (unsigned long)(n_embed)
af710487 2727 );
2728 if (sdef->xerEmbedValuesPossible) {
2729 // The index of the latest embedded value can change outside of this function
2730 // (if the field is a untagged record of), in this case the next value should
2731 // be ignored, as it's already been handled by the record of
2732 src = mputstr(src, " int last_embval_index = 0;\n");
2733 }
2734 src = mputprintf(src,
3abe9331 2735 " bool early_exit = false;\n"
af710487 2736 " for (int i=0; i < %lu; ++i) {\n"
2737 " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n"
970ed795
EL
2738 , (unsigned long)(n_embed));
2739
2740 if (sdef->xerEmbedValuesPossible) {
2741 /* read and store embedValues text if present */
2742 src = mputprintf(src,
af710487 2743 " if (0 != emb_val && p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n"
970ed795 2744 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
3f84031e 2745 " field_%s%s[emb_val->embval_index] = emb_ustr;\n"
970ed795 2746 " }\n"
3f84031e 2747 , sdef->elements[0].name
2748 , sdef->elements[0].isOptional ? "()" : "");
970ed795
EL
2749 }
2750
2751 src = mputstr(src,
2752 " type = p_reader.NodeType();\n"
2753 " if (type==XML_READER_TYPE_ELEMENT) break;\n"
3abe9331 2754 " if (type == XML_READER_TYPE_END_ELEMENT) {\n"
2755 " early_exit = true;\n"
2756 " break;\n"
2757 " }\n"
970ed795 2758 " }\n"
3abe9331 2759 " if (rd_ok != 1 || early_exit) break;\n"
970ed795 2760 " const char * x_name = (const char*)p_reader.LocalName();\n" /* Name or LocalName ? */);
af710487 2761
2762 if (sdef->xerEmbedValuesPossible) {
2763 src = mputstr(src,
2764 " if (0 != emb_val) {\n"
2765 " if (last_embval_index == emb_val->embval_index) {\n"
2766 " ++emb_val->embval_index;\n"
2767 " }\n"
2768 " last_embval_index = emb_val->embval_index;\n"
2769 " }\n");
2770 }
970ed795
EL
2771
2772 /* * * * * code for USE-ORDER * * * * */
2773
2774 for (i = begin; i < end; ++i) {
2775 // Check non-anyElement fields first
2776 if (!(sdef->elements[i].xerAnyKind & ANY_ELEM_BIT)) {
2777 src = mputprintf(src,
2778 " if (check_name(x_name, %s_xer_, 1)) {\n"
2779 " ec_1.set_msg(\"%s': \");\n"
af710487 2780 " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, %s);\n"
970ed795
EL
2781 , sdef->elements[i].typegen
2782 , sdef->elements[i].dispname
970ed795
EL
2783 , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name)
2784 , (sdef->xerUseNilPossible ? "()." : "")
2785 , (sdef->xerUseNilPossible ? sdef->elements[i].name : "")
2786 , (sdef->xerUseNilPossible ? "()" : "")
2787 , sdef->elements[i].typegen
af710487 2788 , sdef->xerEmbedValuesPossible ? "emb_val" : "0"
970ed795
EL
2789 );
2790 src = mputprintf(src,
af710487 2791 " field_%s[i] = e_val = %s::of_type::%s;\n"
2792 , sdef->elements[uo].name
2793 , sdef->elements[uo].typegen, sdef->elements[i].name);
970ed795
EL
2794 src = mputstr(src, " }\n else");
2795 }
2796 }
2797 src = mputstr(src,
2798 " {\n"
2799 " boolean any_found = false;\n"
2800 " if (!any_found)");
2801 for (i = begin; i < end; ++i) {
2802 // Check anyElement fields after all other fields
2803 if (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT) {
2804 src = mputstr(src, " {\n");
2805 src = mputprintf(src,
2806 " e_val = %s::of_type::%s;\n"
2807 , sdef->elements[uo].typegen, sdef->elements[i].name);
2808 src = mputprintf(src,
2809 " boolean next_any = false;\n"
2810 " for (int d_f = 0; d_f < num_seen; ++d_f) {\n"
2811 " if (e_val == seen_f[d_f]) {\n"
2812 " next_any = true;\n"
2813 " }\n"
2814 " }\n"
2815 " if (!next_any) {\n"
2816 " ec_1.set_msg(\"%s': \");\n"
af710487 2817 " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, 0);\n"
970ed795
EL
2818 " field_%s[i] = e_val;\n"
2819 " any_found = true;\n"
2820 " }\n"
2821 " }\n"
2822 " if (!any_found)"
2823 , sdef->elements[i].dispname
2824 , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name)
2825 , (sdef->xerUseNilPossible ? "()." : "")
2826 , (sdef->xerUseNilPossible ? sdef->elements[i].name : "")
2827 , (sdef->xerUseNilPossible ? "()" : "")
2828 , sdef->elements[i].typegen, sdef->elements[uo].name
2829 );
2830 }
2831 }
2832
2833 src = mputstr(src,
3abe9331 2834 " {\n" /* take care of the dangling else */
2835 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n"
2836 " \"Bad XML tag '%s' instead of a valid field\", x_name);\n"
2837 " break;\n"
2838 " }\n"
970ed795
EL
2839 " }\n"
2840 " for (int d_f = 0; d_f < num_seen; ++d_f)\n"
2841 " if (e_val == seen_f[d_f])\n"
2842 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Duplicate field\");\n"
2843 " seen_f[num_seen++] = e_val;\n"
2844 " } // next i\n");
2845
2846 if (sdef->xerEmbedValuesPossible) {
2847 /* read and store embedValues text if present */
2848 src = mputprintf(src,
af710487 2849 " if (0 != emb_val) {\n"
2850 " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n"
2851 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
3f84031e 2852 " field_%s%s[emb_val->embval_index] = emb_ustr;\n"
af710487 2853 " }\n"
2854 " if (last_embval_index == emb_val->embval_index) {\n"
2855 " ++emb_val->embval_index;\n"
2856 " }\n"
970ed795 2857 " }\n"
3f84031e 2858 , sdef->elements[0].name
2859 , sdef->elements[0].isOptional ? "()" : "");
970ed795
EL
2860 }
2861
2862 src = mputprintf(src,
2863 " delete [] seen_f;\n"
2864 " }\n"
2865 " int n_collected = field_%s.size_of();\n"
2866 " if (p_td.xer_bits & USE_NIL) {\n"
2867 " ;\n"
2868 " } else {\n"
2869 " if (n_collected < %d || n_collected > %d) {\n"
2870 " ec_0.set_msg(\" \");\n"
2871 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Wrong number of elements\");\n"
2872 " }\n"
2873 " }\n"
3abe9331 2874 " } // !tag_closed\n"
970ed795
EL
2875 " } else { // !uo\n"
2876 , sdef->elements[uo].dispname
2877 , min_ordered, max_ordered
2878 );
2879 } /* end if(UseOrder possible) */
2880
2881 /* * * * * non-UseOrder code always written, executed when * * * *
2882 * * * * * UseOrder not possible or in the "else" clause * * * * */
2883
2884 if (sdef->xerUseNilPossible) {
2885 /* value absent, nothing more to do */
2886 src = mputstr(src,
2887 " if (nil_attribute) {\n"
2888 " p_reader.MoveToElement();\n"
2889 " } else {\n");
2890 }
af710487 2891 if (sdef->xerEmbedValuesPossible) {
2892 // The index of the latest embedded value can change outside of this function
2893 // (if the field is a untagged record of), in this case the next value should
2894 // be ignored, as it's already been handled by the record of
2895 // Omitted fields can also reset this value
2896 src = mputstr(src, " int last_embval_index = 0;\n");
2897 }
970ed795
EL
2898 /* for all the non-attribute fields... */
2899 for (i = start_at + num_attributes; i < sdef->nElements; ++i) {
2900 if (sdef->xerEmbedValuesPossible) {
2901 /* read and store embedValues text if present */
2902 src = mputprintf(src,
af710487 2903 " if (0 != emb_val) {\n"
2904 " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n"
2905 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
3f84031e 2906 " field_%s%s[emb_val->embval_index] = emb_ustr;\n"
af710487 2907 " }\n"
2908 " if (last_embval_index == emb_val->embval_index) {\n"
2909 " ++emb_val->embval_index;\n"
2910 " }\n"
2911 " last_embval_index = emb_val->embval_index;\n"
970ed795 2912 " }\n"
3f84031e 2913 , sdef->elements[0].name
2914 , sdef->elements[0].isOptional ? "()" : "");
970ed795
EL
2915 }
2916 /* The DEFAULT-FOR-EMPTY member can not be involved with EMBED-VALUES,
2917 * so we can use the same pattern: optional "if(...) else" before {}
2918 * XXX check with single-element record where nElements-1 == 0 !! */
2919 if (sdef->kind == RECORD && i == sdef->nElements-1) {
2920 src = mputprintf(src,
2921 " if (e_xer && p_td.dfeValue && p_reader.IsEmptyElement()) {\n"
2922 " field_%s = *static_cast<const %s*>(p_td.dfeValue);\n"
2923 " }\n"
2924 " else"
2925 , sdef->elements[i].name, sdef->elements[i].type);
2926 }
2927 /* Decode the field */
2928 src = mputprintf(src,
2929 " {\n"
2930 " ec_1.set_msg(\"%s': \");\n"
2931 , sdef->elements[i].dispname);
2932
2933 if ( (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT)
2934 && !strcmp(sdef->elements[i].type,"UNIVERSAL_CHARSTRING") ) {
2935 // In case the field is an optional anyElement -> check if it should be omitted
2936 if (sdef->elements[i].isOptional) {
2937 src = mputprintf(src,
2938 " if (field_%s.XER_check_any_elem(p_reader, \"%s\", tag_closed))\n "
2939 , sdef->elements[i].name
2940 , (i == sdef->nElements - 1) ? "NULL" : sdef->elements[i + 1].name);
2941 } else {
2942 // If the record is emptyElement, there's no way it will have an anyElement field
2943 src = mputstr(src, " if (tag_closed) p_reader.Read(); \n");
2944 }
2945 }
2946
2947 src = mputprintf(src,
2948 " field_%s.XER_decode(%s_xer_, p_reader, p_flavor"
3f84031e 2949 " | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : XER_NONE), %s);\n"
970ed795 2950 " }\n"
af710487 2951 , sdef->elements[i].name, sdef->elements[i].typegen
2952 , sdef->xerEmbedValuesPossible ? "emb_val" : "0");
2953 if (sdef->xerEmbedValuesPossible) {
2954 src = mputprintf(src,
2955 " if (!field_%s.is_present()) {\n"
2956 // there was no new element, the last embedded value is for the next field
2957 // (or the end of the record if this is the last field)
2958 " last_embval_index = -1;\n"
2959 " }\n"
2960 , sdef->elements[i].name);
2961 }
970ed795
EL
2962 } /* next field */
2963
970ed795
EL
2964 if (sdef->xerEmbedValuesPossible) {
2965 /* read and store embedValues text if present */
2966 src = mputprintf(src,
af710487 2967 " if (0 != emb_val) {\n"
2968 " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n"
2969 " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n"
3f84031e 2970 " field_%s%s[emb_val->embval_index] = emb_ustr;\n"
af710487 2971 " }\n"
2972 " if (last_embval_index == emb_val->embval_index) {\n"
2973 " ++emb_val->embval_index;\n"
2974 " }\n"
970ed795 2975 " }\n"
3f84031e 2976 , sdef->elements[0].name
2977 , sdef->elements[0].isOptional ? "()" : "");
af710487 2978 }
2979
2980 if (sdef->xerUseNilPossible) {
2981 src = mputstr(src, " } // use_nil\n");
970ed795
EL
2982 }
2983
af710487 2984 if (sdef->xerUseOrderPossible) {
2985 src = mputstr(src, " } // uo\n");
2986 }
2987
970ed795 2988 if (sdef->xerEmbedValuesPossible) {
970ed795 2989 src = mputprintf(src,
3f84031e 2990 "%s"
af710487 2991 " if (0 != emb_val) {\n"
970ed795 2992 " %s::of_type empty_string(\"\");\n"
af710487 2993 " for (int j_j = 0; j_j < emb_val->embval_index; ++j_j) {\n"
3f84031e 2994 " if (!field_%s%s[j_j].is_bound()) {\n"
2995 " field_%s%s[j_j] = empty_string;\n"
2996 " }%s%s%s%s"
970ed795 2997 " }\n"
af710487 2998 " delete emb_val;\n"
2999 " }\n"
3f84031e 3000 , sdef->elements[0].isOptional ? " bool all_unbound = true;\n" : ""
970ed795
EL
3001 , sdef->elements[0].type
3002 , sdef->elements[0].name
3f84031e 3003 , sdef->elements[0].isOptional ? "()" : ""
970ed795 3004 , sdef->elements[0].name
3f84031e 3005 , sdef->elements[0].isOptional ? "()" : ""
3006 , sdef->elements[0].isOptional ? " else if(field_" : "\n"
3007 , sdef->elements[0].isOptional ? sdef->elements[0].name : ""
3008 , sdef->elements[0].isOptional ? "()" : ""
3009 , sdef->elements[0].isOptional ? "[j_j] != empty_string) {\n all_unbound = false;\n }\n" : ""
970ed795 3010 );
3f84031e 3011
3012 if(sdef->elements[0].isOptional) {
3013 src = mputprintf(src,
3014 " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && all_unbound) {\n"
3015 " field_%s = OMIT_VALUE;\n"
3016 " }\n"
3017 , sdef->elements[0].name
3018 );
3019 }
970ed795
EL
3020 }
3021
970ed795
EL
3022 if (sdef->xerUseQName) {
3023 src = mputstr(src, " } // qn\n");
3024 }
3025
3026 src = mputstr(src,
3abe9331 3027 " } // errorcontext\n"); /* End scope for error context objects */
3028
3029 /* Check if every non-optional field has been set */
3030 for (i = 0; i < sdef->nElements; ++i) {
3031 if (!sdef->elements[i].isOptional) {
3032 src = mputprintf(src,
3033 " if (!field_%s.is_bound()) {\n"
3034 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,\n"
3035 " \"No data found for non-optional field '%s'\");\n"
3036 " }\n"
3037 , sdef->elements[i].name, sdef->elements[i].dispname);
3038 }
3039 }
3040 src = mputstr(src,
970ed795
EL
3041 " if (!omit_tag) {\n"
3042 " int current_depth;\n"
3043 " for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
3044 " type = p_reader.NodeType();\n"
3045 " if ((current_depth = p_reader.Depth()) > xml_depth) {\n"
3046 " if (XML_READER_TYPE_ELEMENT == type) {\n"
3047 /* An element deeper than our start tag has not been processed */
3048 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG,\n"
3049 " \"Unprocessed XML tag `%s'\", (const char *)p_reader.Name());\n"
3050 " }\n"
3051 " continue;\n"
3052 " }\n"
3053 " else if (current_depth == xml_depth) {\n"
3054 " if (XML_READER_TYPE_ELEMENT == type) {\n"
3055 " verify_name(p_reader, p_td, e_xer);\n"
3056 " if (p_reader.IsEmptyElement()) {\n"
3057 " p_reader.Read();\n" /* advance one more time */
3058 " break;\n"
3059 " }\n"
3060 " }\n"
3061 " else if (XML_READER_TYPE_END_ELEMENT == type) {\n"
3062 " verify_end(p_reader, p_td, xml_depth, e_xer);\n"
3063 " rd_ok = p_reader.Read();\n"
3064 " break;\n"
3065 " }\n"
3066 " }\n"
3067 " else break;" /* depth is less, we are in trouble... */
3068 " }\n"
3069 " }\n"
3070 " return 1;\n}\n\n");
3071
3072 *pdef = def;
3073 *psrc = src;
3074}
3075
3076void defRecordClass1(const struct_def *sdef, output_struct *output)
3077{
3078 size_t i;
3079 size_t mandatory_fields_count;
3080 const char *name = sdef->name, *dispname = sdef->dispname;
3081 const char* kind_str = sdef->kind == SET ? "set" : "record";
3082 char *def = NULL, *src = NULL;
3083 boolean ber_needed = sdef->isASN1 && enable_ber();
3084 boolean raw_needed = sdef->hasRaw && enable_raw();
3085 boolean text_needed = sdef->hasText && enable_text();
3086 boolean xer_needed = sdef->hasXer && enable_xer();
3087 boolean json_needed = sdef->hasJson && enable_json();
3088
3089 /* class declaration code */
3090 output->header.class_decls = mputprintf(output->header.class_decls,
3091 "class %s;\n", name);
3092
3093 if (sdef->nElements <= 0) {
3094 defEmptyRecordClass(sdef, output);
3095 return;
3096 }
3097
3098 /* class definition and source code */
3099 if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) {
3100 def=mputprintf
3101 (def,
3102#ifndef NDEBUG
3103 "// written by %s in " __FILE__ " at line %d\n"
3104#endif
3105 "class %s : public Base_Type {\n"
3106#ifndef NDEBUG
3107 , __FUNCTION__, __LINE__
3108#endif
3109 , name);
3110 } else {
3111 def=mputprintf(def, "class %s {\n", name);
3112 }
3113
3114 /* fields */
3115 for (i = 0; i < sdef->nElements; i++) {
3116 if(sdef->elements[i].isOptional)
3117 def = mputprintf(def, " OPTIONAL<%s> field_%s;\n",
3118 sdef->elements[i].type,
3119 sdef->elements[i].name);
3120 else
3121 def = mputprintf(def, " %s field_%s;\n",
3122 sdef->elements[i].type, sdef->elements[i].name);
3123 }
3124
3125 /* bound flag */
3126 def = mputstr(def, " boolean bound_flag;\n");
3127
3128 /* default constructor */
3129 def = mputprintf(def, "public:\n"
3130 " %s();\n", name);
3131 src = mputprintf(src, "%s::%s()\n"
3132 "{\n"
3133 " bound_flag = FALSE;\n"
3134 "}\n\n", name, name);
3135
3136 /* constructor by fields */
3137 def = mputprintf(def, " %s(", name);
3138 src = mputprintf(src, "%s::%s(", name, name);
3139
3140 for (i = 0; i < sdef->nElements; i++) {
3141 char *tmp = NULL;
3142 if (i > 0) tmp = mputstr(tmp, ",\n ");
3143 if (sdef->elements[i].isOptional)
3144 tmp = mputprintf
3145 (tmp,
3146 "const OPTIONAL<%s>& par_%s",
3147 sdef->elements[i].type, sdef->elements[i].name);
3148 else
3149 tmp = mputprintf
3150 (tmp,
3151 "const %s& par_%s",
3152 sdef->elements[i].type, sdef->elements[i].name);
3153 def = mputstr(def, tmp);
3154 src = mputstr(src, tmp);
3155 Free(tmp);
3156 }
3157 def = mputstr(def, ");\n");
3158 src = mputstr(src, ")\n"
3159 " : ");
3160 for (i = 0; i < sdef->nElements; i++) {
3161 if (i > 0) src = mputstr(src, ",\n");
3162 src = mputprintf(src, " field_%s(par_%s)", sdef->elements[i].name,
3163 sdef->elements[i].name);
3164 }
3165 src = mputstr(src, "\n"
3166 "{\n"
3167 " bound_flag = TRUE;\n"
3168 "}\n\n");
3169
3170 /* copy constructor */
3171 def = mputprintf(def, " %s(const %s& other_value);\n", name, name);
3172 src = mputprintf(src, "%s::%s(const %s& other_value)\n"
3173 "{\n"
3174 "if(!other_value.is_bound()) "
3175 "TTCN_error(\"Copying an unbound value of type %s.\");\n"
3176 "bound_flag = TRUE;\n",
3177 name, name, name, dispname);
3178 for (i = 0; i < sdef->nElements; i++) {
3179 src = mputprintf(src,
3180 "if (other_value.%s().is_bound()) field_%s = other_value.%s();\n"
3181 "else field_%s.clean_up();\n",
3182 sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name,
3183 sdef->elements[i].name);
3184 }
3185 src = mputstr(src, "}\n\n");
3186
3187 /* not a component */
3188 def = mputstr(def, " inline boolean is_component() { return FALSE; }\n");
3189
3190 /* clean_up */
3191 def = mputstr(def, " void clean_up();\n");
3192 src = mputprintf(src, "void %s::clean_up()\n"
3193 "{\n", name);
3194 for (i = 0; i < sdef->nElements; i++) {
3195 src = mputprintf(src,
3196 "field_%s.clean_up();\n", sdef->elements[i].name);
3197 }
3198 src = mputstr(src,
3199 "bound_flag = FALSE;\n"
3200 "}\n\n");
3201
3202 /* = operator */
3203 def = mputprintf(def, " %s& operator=(const %s& other_value);\n", name, name);
3204 src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n"
3205 "{\n"
3206 "if (this != &other_value) {\n"
3207 " if(!other_value.is_bound()) "
3208 "TTCN_error(\"Assignment of an unbound value of type %s.\");\n"
3209 " bound_flag = TRUE;\n",
3210 name, name, name, dispname);
3211 for (i = 0; i < sdef->nElements; i++) {
3212 src = mputprintf(src,
3213 " if (other_value.%s().is_bound()) field_%s = other_value.%s();\n"
3214 " else field_%s.clean_up();\n",
3215 sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name,
3216 sdef->elements[i].name);
3217 }
3218 src = mputstr(src,
3219 "}\n"
3220 "return *this;\n"
3221 "}\n\n");
3222
3223 /* == operator */
3224 def = mputprintf(def, " boolean operator==(const %s& other_value) "
3225 "const;\n", name);
3226 src = mputprintf(src,
3227 "boolean %s::operator==(const %s& other_value) const\n"
3228 "{\n"
3229 "if (!is_bound() && !other_value.is_bound()) return TRUE;\n"
3230 "return ", name, name);
3231 for (i = 0; i < sdef->nElements; i++) {
3232 if (i > 0) src = mputstr(src, "\n && ");
3233 src = mputprintf(src, "field_%s==other_value.field_%s",
3234 sdef->elements[i].name, sdef->elements[i].name);
3235 }
3236 src = mputstr(src, ";\n}\n\n");
3237
3238 /* != and () operator */
3239 def = mputprintf(def,
3240 " inline boolean operator!=(const %s& other_value) const\n"
3241 " { return !(*this == other_value); }\n\n", name);
3242
3243 /* is_bound */
3244 def = mputprintf(def,
3245 " boolean is_bound() const;\n\n");
3246 src = mputprintf(src,
3247 "boolean %s::is_bound() const\n"
3248 "{\n"
3249 "if (bound_flag) return TRUE;\n", name);
3250 for(i=0; i < sdef->nElements; i++) {
3251 if(sdef->elements[i].isOptional) {
3252 src = mputprintf(src,
3253 "if(OPTIONAL_OMIT == field_%s.get_selection() || field_%s.is_bound()) return TRUE;\n",
3254 sdef->elements[i].name, sdef->elements[i].name);
3255 } else {
3256 src = mputprintf(src,
3257 "if(field_%s.is_bound()) return TRUE;\n",
3258 sdef->elements[i].name);
3259 }
3260 }
3261 src = mputprintf(src,
3262 "return FALSE;\n"
3263 "}\n");
3264
3265 /* is_present */
3266 def = mputstr(def,
3267 "inline boolean is_present() const { return is_bound(); }\n");
3268
3269 /* is_value */
3270 def = mputprintf(def,
3271 " boolean is_value() const;\n\n");
3272 src = mputprintf(src,
3273 "boolean %s::is_value() const\n"
3274 "{\n"
3275 "if (!is_bound()) return FALSE;\n", name);
3276 for(i=0; i < sdef->nElements; i++) {
3277 if(sdef->elements[i].isOptional) {
3278 src = mputprintf(src,
3279 "if(OPTIONAL_OMIT != field_%s.get_selection() && !field_%s.is_value()) return FALSE;\n",
3280 sdef->elements[i].name, sdef->elements[i].name);
3281 } else {
3282 src = mputprintf(src,
3283 "if(!field_%s.is_value()) return FALSE;\n",
3284 sdef->elements[i].name);
3285 }
3286 }
3287 src = mputprintf(src,
3288 "return TRUE;\n}\n");
3289
3290 /* field accessor methods */
3291 for (i = 0; i < sdef->nElements; i++) {
3292 if(sdef->elements[i].isOptional)
3293 def = mputprintf
3294 (def,
3295 " inline OPTIONAL<%s>& %s()\n"
3296 " {return field_%s;}\n"
3297 " inline const OPTIONAL<%s>& %s() const\n"
3298 " {return field_%s;}\n",
3299 sdef->elements[i].type, sdef->elements[i].name,
3300 sdef->elements[i].name,
3301 sdef->elements[i].type, sdef->elements[i].name,
3302 sdef->elements[i].name);
3303 else def = mputprintf
3304 (def,
3305 " inline %s& %s()\n"
3306 " {return field_%s;}\n"
3307 " inline const %s& %s() const\n"
3308 " {return field_%s;}\n",
3309 sdef->elements[i].type, sdef->elements[i].name,
3310 sdef->elements[i].name, sdef->elements[i].type,
3311 sdef->elements[i].name, sdef->elements[i].name);
3312
3313 }
3314
3315 /* sizeof operation */
3316 mandatory_fields_count = 0;
3317 for (i = 0; i < sdef->nElements; i++)
3318 if (!sdef->elements[i].isOptional) mandatory_fields_count++;
3319
3320 def = mputstr(def, " int size_of() const;\n");
3321 src = mputprintf(src,
3322 "int %s::size_of() const\n"
3323 "{\n"
3324 " if (!is_bound()) "
3325 "TTCN_error(\"Calculating the size of an unbound record/set value of type %s\");\n"
3326 , name, dispname);
3327 if (sdef->nElements == mandatory_fields_count) {
3328 src = mputprintf(src, " return %lu;\n", (unsigned long) mandatory_fields_count);
3329 }
3330 else {
3331 src = mputprintf(src, " int ret_val = %lu;\n",
3332 (unsigned long) mandatory_fields_count);
3333 for (i = 0; i < sdef->nElements; i++)
3334 if (sdef->elements[i].isOptional)
3335 src = mputprintf(src,
3336 " if (field_%s.ispresent()) ret_val++;\n",
3337 sdef->elements[i].name);
3338 src = mputstr(src, " return ret_val;\n");
3339 }
3340 src = mputstr(src, "}\n\n");
3341
3342 /* log function */
3343 def = mputstr(def, " void log() const;\n");
3344 src = mputprintf(src,
3345 "void %s::log() const\n{\n"
3346 "if (!is_bound()) {\n"
3347 "TTCN_Logger::log_event_unbound();\n"
3348 "return;\n"
3349 "}\n", name);
3350 for (i = 0; i < sdef->nElements; i++) {
3351 src = mputstr(src, "TTCN_Logger::log_event_str(\"");
3352 if (i == 0) src = mputc(src, '{');
3353 else src = mputc(src, ',');
3354 src = mputprintf(src, " %s := \");\n"
3355 "field_%s.log();\n",
3356 sdef->elements[i].dispname, sdef->elements[i].name);
3357 }
3358 src = mputstr(src, "TTCN_Logger::log_event_str(\" }\");\n}\n\n");
3359
3360 /* set param function */
3361 def = mputstr(def, " void set_param(Module_Param& param);\n");
3362 src = mputprintf
3363 (src,
3364 "void %s::set_param(Module_Param& param)\n{\n"
3365 " bound_flag = TRUE;\n"
3366 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
3367 " param.get_id()->next_name()) {\n"
3368 // Haven't reached the end of the module parameter name
3369 // => the name refers to one of the fields, not to the whole record
3370 " char* param_field = param.get_id()->get_current_name();\n"
3371 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
3372 " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n"
3373 " \" name for %s type `%s'\");\n"
3374 " }\n"
3375 " ", name, kind_str, dispname);
3376 for (i = 0; i < sdef->nElements; i++) {
3377 src = mputprintf(src,
3378 "if (strcmp(\"%s\", param_field) == 0) {\n"
3379 " %s().set_param(param);\n"
3380 " return;\n"
3381 " } else ",
3382 sdef->elements[i].dispname, sdef->elements[i].name);
3383 }
3384 src = mputprintf(src,
3385 "param.error(\"Field `%%s' not found in %s type `%s'\", param_field);\n"
3386 " }\n"
3387 " param.basic_check(Module_Param::BC_VALUE, \"%s value\");\n"
3f84031e 3388 " Module_Param_Ptr m_p = &param;\n"
3abe9331 3389 " if (param.get_type() == Module_Param::MP_Reference) {\n"
3f84031e 3390 " m_p = param.get_referenced_param();\n"
3abe9331 3391 " }\n"
3f84031e 3392 " switch (m_p->get_type()) {\n"
970ed795 3393 " case Module_Param::MP_Value_List:\n"
3f84031e 3394 " if (%lu<m_p->get_size()) {\n"
3395 " param.error(\"%s value of type %s has %lu fields but list value has %%d fields\", (int)m_p->get_size());\n"
970ed795
EL
3396 " }\n",
3397 kind_str, dispname, kind_str, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements);
3398
3399 for (i = 0; i < sdef->nElements; ++i) {
3400 src = mputprintf(src,
3f84031e 3401 " if (m_p->get_size()>%lu && m_p->get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*m_p->get_elem(%lu));\n",
970ed795
EL
3402 (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i);
3403 }
3404 src = mputstr(src,
3405 " break;\n"
3406 " case Module_Param::MP_Assignment_List: {\n"
3f84031e 3407 " Vector<bool> value_used(m_p->get_size());\n"
3408 " value_used.resize(m_p->get_size(), false);\n");
970ed795
EL
3409 for (i = 0; i < sdef->nElements; ++i) {
3410 src = mputprintf(src,
3f84031e 3411 " for (size_t val_idx=0; val_idx<m_p->get_size(); val_idx++) {\n"
3412 " Module_Param* const curr_param = m_p->get_elem(val_idx);\n"
970ed795
EL
3413 " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n"
3414 " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n"
3415 " %s().set_param(*curr_param);\n"
3416 " }\n"
3417 " value_used[val_idx]=true;\n"
3418 " }\n"
3419 " }\n"
3420 , sdef->elements[i].dispname, sdef->elements[i].name);
3421 }
3422 src = mputprintf(src,
3f84031e 3423 " for (size_t val_idx=0; val_idx<m_p->get_size(); val_idx++) if (!value_used[val_idx]) {\n"
3424 " m_p->get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", m_p->get_elem(val_idx)->get_id()->get_name());\n"
970ed795
EL
3425 " break;\n"
3426 " }\n"
3427 " } break;\n"
3428 " default:\n"
3429 " param.type_error(\"%s value\", \"%s\");\n"
3430 " }\n"
3431 "}\n\n", dispname, kind_str, dispname);
3abe9331 3432
3433 /* get param function */
3434 def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
3435 src = mputprintf(src,
3436 "Module_Param* %s::get_param(Module_Param_Name& param_name) const\n"
3437 "{\n"
3438 " if (!is_bound()) {\n"
3439 " return new Module_Param_Unbound();\n"
3440 " }\n"
3441 " if (param_name.next_name()) {\n"
3442 // Haven't reached the end of the module parameter name
3443 // => the name refers to one of the fields, not to the whole record
3444 " char* param_field = param_name.get_current_name();\n"
3445 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
3446 " TTCN_error(\"Unexpected array index in module parameter reference, \"\n"
3447 " \"expected a valid field name for %s type `%s'\");\n"
3448 " }\n"
3449 " ", name, kind_str, dispname);
3450 for (i = 0; i < sdef->nElements; i++) {
3451 src = mputprintf(src,
3452 "if (strcmp(\"%s\", param_field) == 0) {\n"
3453 " return %s().get_param(param_name);\n"
3454 " } else ",
3455 sdef->elements[i].dispname, sdef->elements[i].name);
3456 }
3457 src = mputprintf(src,
3458 "TTCN_error(\"Field `%%s' not found in %s type `%s'\", param_field);\n"
3459 " }\n"
3f84031e 3460 " Module_Param_Assignment_List* m_p = new Module_Param_Assignment_List();\n"
3abe9331 3461 , kind_str, dispname);
3462 for (i = 0; i < sdef->nElements; i++) {
3463 src = mputprintf(src,
3464 " Module_Param* mp_field_%s = field_%s.get_param(param_name);\n"
3465 " mp_field_%s->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n"
3f84031e 3466 " m_p->add_elem(mp_field_%s);\n"
3abe9331 3467 , sdef->elements[i].name, sdef->elements[i].name
3468 , sdef->elements[i].name, sdef->elements[i].dispname
3469 , sdef->elements[i].name);
3470 }
3471 src = mputstr(src,
3f84031e 3472 " return m_p;\n"
3abe9331 3473 " }\n\n");
970ed795
EL
3474
3475 /* set implicit omit function, recursive */
3476 def = mputstr(def, " void set_implicit_omit();\n");
3477 src = mputprintf(src, "void %s::set_implicit_omit()\n{\n", name);
3478 for (i = 0; i < sdef->nElements; i++) {
3479 if (sdef->elements[i].isOptional) {
3480 src = mputprintf(src,
3481 "if (!%s().is_bound()) %s() = OMIT_VALUE;\n"
3482 "else %s().set_implicit_omit();\n",
3483 sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name);
3484 } else {
3485 src = mputprintf(src,
3486 "if (%s().is_bound()) %s().set_implicit_omit();\n",
3487 sdef->elements[i].name, sdef->elements[i].name);
3488 }
3489 }
3490 src = mputstr(src, "}\n\n");
3491
3492 /* text encoder function */
3493 def = mputstr(def, " void encode_text(Text_Buf& text_buf) const;\n");
3494 src = mputprintf(src,
3495 "void %s::encode_text(Text_Buf& text_buf) const\n{\n"
3496 "if (!is_bound()) "
3497 "TTCN_error(\"Text encoder: Encoding an unbound record/set value of type %s.\");\n"
3498 , name, dispname);
3499 for (i = 0; i < sdef->nElements; i++) {
3500 src = mputprintf(src, "field_%s.encode_text(text_buf);\n",
3501 sdef->elements[i].name);
3502 }
3503 src = mputstr(src, "}\n\n");
3504
3505 /* text decoder function */
3506 def = mputstr(def, " void decode_text(Text_Buf& text_buf);\n");
3507 src = mputprintf(src,
3508 "void %s::decode_text(Text_Buf& text_buf)\n{\n"
3509 "bound_flag = TRUE;\n", name);
3510 for (i = 0; i < sdef->nElements; i++) {
3511 src = mputprintf(src, "field_%s.decode_text(text_buf);\n",
3512 sdef->elements[i].name);
3513 }
3514 src = mputstr(src, "}\n\n");
3515
3516 /* The common "classname::encode()" and "classname::decode()" functions */
3517 if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
3518 def_encdec(name, &def, &src, ber_needed, raw_needed,
3519 text_needed, xer_needed, json_needed, FALSE);
3520
3521 /* BER functions */
3522 if(ber_needed) {
3523 /* BER_encode_TLV() */
3524 src=mputprintf
3525 (src,
3526 "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,"
3527 " unsigned p_coding) const\n"
3528 "{\n"
3529 " if (!is_bound()) TTCN_EncDec_ErrorContext::error"
3530 "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
3531 " BER_chk_descr(p_td);\n"
3532 " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
3533 " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n"
3534 " TTCN_EncDec_ErrorContext ec_1;\n"
3535 , name
3536 );
3537 for(i=0; i<sdef->nElements; i++) {
3538 if(!default_as_optional && sdef->elements[i].isDefault) { /* is DEFAULT */
3539 src=mputprintf
3540 (src,
3541 " if(field_%s!=%s) {\n"
3542 " ec_1.set_msg(\"%s': \");\n"
3543 " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_,"
3544 " p_coding));\n"
3545 " }\n"
3546 , sdef->elements[i].name, sdef->elements[i].defvalname
3547 , sdef->elements[i].dispname
3548 , sdef->elements[i].name, sdef->elements[i].typedescrname
3549 );
3550 }
3551 else { /* is not DEFAULT */
3552 src=mputprintf
3553 (src,
3554 " ec_1.set_msg(\"%s': \");\n"
3555 " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_,"
3556 " p_coding));\n"
3557 , sdef->elements[i].dispname
3558 , sdef->elements[i].name, sdef->elements[i].typedescrname
3559 );
3560 } /* !isDefault */
3561 } /* for i */
3562 if(sdef->kind==SET) {
3563 src=mputstr
3564 (src,
3565 " if(p_coding==BER_ENCODE_DER)\n"
3566 " new_tlv->sort_tlvs_tag();\n"
3567 );
3568 }
3569 src=mputstr
3570 (src,
3571 " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
3572 " return new_tlv;\n"
3573 "}\n"
3574 "\n"
3575 );
3576
3577 /* BER_decode_TLV() */
3578 src=mputprintf
3579 (src,
3580 "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,"
3581 " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n"
3582 "{\n"
3583 " bound_flag = TRUE;\n"
3584 " BER_chk_descr(p_td);\n"
3585 " ASN_BER_TLV_t stripped_tlv;\n"
3586 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
3587 " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n"
3588 " stripped_tlv.chk_constructed_flag(TRUE);\n"
3589 " size_t V_pos=0;\n"
3590 " ASN_BER_TLV_t tmp_tlv;\n"
3591 , name, sdef->dispname
3592 );
3593
3594 if(sdef->kind==RECORD)
3595 { /* SEQUENCE decoding */
3596 src=mputstr
3597 (src,
3598 " boolean tlv_present=FALSE;\n"
3599 " {\n"
3600 " TTCN_EncDec_ErrorContext ec_1(\"Component '\");\n"
3601 " TTCN_EncDec_ErrorContext ec_2;\n"
3602 );
3603 for(i=0; i<sdef->nElements; i++) {
3604 src=mputprintf
3605 (src,
3606 " ec_2.set_msg(\"%s': \");\n"
3607 " if(!tlv_present) tlv_present=BER_decode_constdTLV_next"
3608 "(stripped_tlv, V_pos, L_form, tmp_tlv);\n"
3609 , sdef->elements[i].dispname
3610 );
3611 if(sdef->elements[i].isDefault) { /* is DEFAULT */
3612 src=mputprintf
3613 (src,
3614 " if(!tlv_present || !field_%s.BER_decode_isMyMsg(%s_descr_,"
3615 " tmp_tlv))\n"
3616 " field_%s=%s;\n"
3617 " else {\n"
3618 " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv,"
3619 " L_form);\n"
3620 " tlv_present=FALSE;\n"
3621 " }\n"
3622 , sdef->elements[i].name, sdef->elements[i].typedescrname
3623 , sdef->elements[i].name, sdef->elements[i].defvalname
3624 , sdef->elements[i].name, sdef->elements[i].typedescrname
3625 );
3626 }
3627 else if(sdef->elements[i].isOptional) { /* is OPTIONAL */
3628 src=mputprintf
3629 (src,
3630 " if(!tlv_present) field_%s=OMIT_VALUE;\n"
3631 " else {\n"
3632 " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n"
3633 " if(field_%s.ispresent()) tlv_present=FALSE;\n"
3634 " }\n"
3635 , sdef->elements[i].name
3636 , sdef->elements[i].name, sdef->elements[i].typedescrname
3637 , sdef->elements[i].name
3638 );
3639 }
3640 else { /* is not DEFAULT OPTIONAL */
3641 src=mputprintf
3642 (src,
3643 " if(!tlv_present){\n"
3644 " ec_2.error(TTCN_EncDec::ET_INCOMPL_MSG,\"Invalid or incomplete message was received.\");\n"
3645 " return FALSE;\n"
3646 " }\n"
3647 " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n"
3648 " tlv_present=FALSE;\n"
3649 , sdef->elements[i].name, sdef->elements[i].typedescrname
3650 );
3651 } /* !isDefault */
3652 } /* for i */
3653 src=mputstr
3654 (src,
3655 " }\n"
3656 " BER_decode_constdTLV_end(stripped_tlv, V_pos, L_form, tmp_tlv,"
3657 " tlv_present);\n"
3658 );
3659 } /* SEQUENCE decoding */
3660 else { /* SET decoding */
3661 src=mputprintf
3662 (src,
3663 " const char *fld_name[%lu]={"
3664 , (unsigned long) sdef->nElements
3665 );
3666 for(i=0; i<sdef->nElements; i++)
3667 src=mputprintf
3668 (src,
3669 "%s\"%s\""
3670 , i?", ":""
3671 , sdef->elements[i].dispname
3672 );
3673 /* field indicator:
3674 * 0x01: value arrived
3675 * 0x02: is optional / not used :)
3676 * 0x04: has default / not used :)
3677 */
3678 src=mputprintf
3679 (src,
3680 "};\n"
3681 " unsigned char fld_indctr[%lu]={"
3682 , (unsigned long) sdef->nElements
3683 );
3684 for(i=0; i<sdef->nElements; i++)
3685 src=mputprintf
3686 (src,
3687 "%s0"
3688 , i?", ":""
3689 );
3690 src=mputstr
3691 (src,
3692 "};\n"
3693 " size_t fld_curr;\n"
3694 " while(BER_decode_constdTLV_next(stripped_tlv, V_pos,"
3695 " L_form, tmp_tlv)) {\n"
3696 );
3697 for(i=0; i<sdef->nElements; i++)
3698 src=mputprintf
3699 (src,
3700 " %sif(field_%s.BER_decode_isMyMsg(%s_descr_, tmp_tlv)) {\n"
3701 " fld_curr=%lu;\n"
3702 " TTCN_EncDec_ErrorContext ec_1(\"Component '%%s': \","
3703 " fld_name[%lu]);\n"
3704 " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n"
3705 " }\n"
3706 , i?"else ":""
3707 , sdef->elements[i].name, sdef->elements[i].typedescrname
3708 , (unsigned long) i, (unsigned long) i
3709 , sdef->elements[i].name, sdef->elements[i].typedescrname
3710 );
3711 src=mputprintf
3712 (src,
3713 " else {\n"
3714 " /* ellipsis or error... */\n"
3715 " fld_curr=static_cast<size_t>(-1);\n"
3716 " }\n"
3717 " if(fld_curr!=static_cast<size_t>(-1)) {\n"
3718 " if(fld_indctr[fld_curr])\n"
3719 " ec_0.error(TTCN_EncDec::ET_DEC_DUPFLD, \"Duplicated"
3720 " value for component '%%s'.\", fld_name[fld_curr]);\n"
3721 " fld_indctr[fld_curr]=1;\n"
3722 " }\n" /* if != -1 */
3723 " }\n" /* while */
3724 " for(fld_curr=0; fld_curr<%lu; fld_curr++) {\n"
3725 " if(fld_indctr[fld_curr]) continue;\n"
3726 " switch(fld_curr) {\n"
3727 , (unsigned long) sdef->nElements
3728 );
3729 for(i=0; i<sdef->nElements; i++) {
3730 if(sdef->elements[i].isDefault)
3731 src=mputprintf
3732 (src,
3733 " case %lu:\n"
3734 " field_%s=%s;\n"
3735 " break;\n"
3736 , (unsigned long) i
3737 , sdef->elements[i].name, sdef->elements[i].defvalname
3738 );
3739 else if(sdef->elements[i].isOptional)
3740 src=mputprintf
3741 (src,
3742 " case %lu:\n"
3743 " field_%s=OMIT_VALUE;\n"
3744 " break;\n"
3745 , (unsigned long) i
3746 , sdef->elements[i].name
3747 );
3748 } /* for i */
3749 src=mputstr
3750 (src,
3751 " default:\n"
3752 " ec_0.error(TTCN_EncDec::ET_DEC_MISSFLD, \"Missing"
3753 " value for component '%s'.\", fld_name[fld_curr]);\n"
3754 " }\n" /* switch */
3755 " }\n" /* for fld_curr */
3756 );
3757 } /* SET decoding */
3758
3759 if(sdef->opentype_outermost) {
3760 src=mputstr
3761 (src,
3762 " TTCN_EncDec_ErrorContext ec_1(\"While decoding opentypes: \");\n"
3763 " TTCN_Type_list p_typelist;\n"
3764 " BER_decode_opentypes(p_typelist, L_form);\n"
3765 );
3766 } /* if sdef->opentype_outermost */
3767 src=mputstr
3768 (src,
3769 " return TRUE;\n"
3770 "}\n"
3771 "\n"
3772 );
3773
3774 if(sdef->has_opentypes) {
3775 /* BER_decode_opentypes() */
3776 def=mputstr
3777 (def,
3778 "void BER_decode_opentypes(TTCN_Type_list& p_typelist,"
3779 " unsigned L_form);\n");
3780 src=mputprintf
3781 (src,
3782 "void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist,"
3783 " unsigned L_form)\n"
3784 "{\n"
3785 " bound_flag = TRUE;\n"
3786 " p_typelist.push(this);\n"
3787 " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n"
3788 " TTCN_EncDec_ErrorContext ec_1;\n"
3789 , name
3790 );
3791 for(i=0; i<sdef->nElements; i++) {
3792 src=mputprintf
3793 (src,
3794 " ec_1.set_msg(\"%s': \");\n"
3795 " field_%s.BER_decode_opentypes(p_typelist, L_form);\n"
3796 , sdef->elements[i].dispname
3797 , sdef->elements[i].name
3798 );
3799 } /* for i */
3800 src=mputstr
3801 (src,
3802 " p_typelist.pop();\n"
3803 "}\n"
3804 "\n"
3805 );
3806 } /* if sdef->has_opentypes */
3807
3808 } /* if ber_needed */
3809
3810 if(text_needed){
3811 int man_num=0;
3812 int opt_number=0;
3813 int seof=0;
3814 size_t last_man_index=0;
3815 for(i=0;i<sdef->nElements;i++){
3816 if(sdef->elements[i].isOptional) opt_number++;
3817 else {man_num++;last_man_index=i+1;}
3818 if(sdef->elements[i].of_type) seof++;
3819 }
3820
3821 src=mputprintf(src,
3822 "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td,"
3823 " TTCN_Buffer& p_buf) const{\n"
3824 " if (!is_bound()) TTCN_EncDec_ErrorContext::error"
3825 "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
3826 " bool need_separator=false;\n"
3827 " int encoded_length=0;\n"
3828 " if(p_td.text->begin_encode){\n"
3829 " p_buf.put_cs(*p_td.text->begin_encode);\n"
3830 " encoded_length+=p_td.text->begin_encode->lengthof();\n"
3831 " }\n"
3832 ,name
3833 );
3834
3835 for(i=0;i<sdef->nElements;i++){
3836 if(sdef->elements[i].isOptional){
3837 src=mputprintf(src,
3838 " if(field_%s.ispresent()){\n"
3839 ,sdef->elements[i].name
3840 );
3841 }
3842 src=mputprintf(src,
3843 " if(need_separator && p_td.text->separator_encode){\n"
3844 " p_buf.put_cs(*p_td.text->separator_encode);\n"
3845 " encoded_length+=p_td.text->separator_encode->lengthof();\n"
3846 " }\n"
3847 " encoded_length+=field_%s%s.TEXT_encode(%s_descr_,p_buf);\n"
3848 " need_separator=true;\n"
3849 ,sdef->elements[i].name
3850 ,sdef->elements[i].isOptional?"()":"",sdef->elements[i].typedescrname
3851 );
3852 if(sdef->elements[i].isOptional){
3853 src=mputstr(src,
3854 " }\n"
3855 );
3856 }
3857 }
3858
3859 src=mputstr(src,
3860 " if(p_td.text->end_encode){\n"
3861 " p_buf.put_cs(*p_td.text->end_encode);\n"
3862 " encoded_length+=p_td.text->end_encode->lengthof();\n"
3863 " }\n"
3864 " return encoded_length;\n"
3865 "}\n"
3866 );
3867
3868 if(sdef->kind==SET){ /* set decoder start*/
3869 src = mputprintf(src,
3870 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
3871 " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n"
3872 " bound_flag = TRUE;\n"
3873 " int decoded_length=0;\n"
3874 " int decoded_field_length=0;\n"
3875 " size_t pos=p_buf.get_pos();\n"
3876 " boolean sep_found=FALSE;\n"
3877 " int ml=0;\n"
3878 " int sep_length=0;\n"
3879 " int mand_field_num=%d;\n"
3880 " int opt_field_num=%d;\n"
3881 " int loop_detector=1;\n"
3882 " int last_field_num=-1;\n"
3883 " int field_map[%lu];\n"
3884 " memset(field_map, 0, sizeof(field_map));\n"
3885 " if(p_td.text->begin_decode){\n"
3886 " int tl;\n"
3887 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
3888 " if(no_err)return -1;\n"
3889 " TTCN_EncDec_ErrorContext::error\n"
3890 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
3891 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
3892 ", p_td.name);\n"
3893 " return 0;\n"
3894 " }\n"
3895 " decoded_length+=tl;\n"
3896 " p_buf.increase_pos(tl);\n"
3897 " }\n"
3898 " if(p_td.text->end_decode){\n"
3899 " limit.add_token(p_td.text->end_decode);\n"
3900 " ml++;\n"
3901 " }\n"
3902 " if(p_td.text->separator_decode){\n"
3903 " limit.add_token(p_td.text->separator_decode);\n"
3904 " ml++;\n"
3905 " }\n"
3906 ,name,man_num,opt_number,(unsigned long) sdef->nElements
3907 );
3908
3909 if(seof){
3910 int first=0;
3911 src=mputstr(src,
3912 " int has_repeatable=0;\n"
3913 " if("
3914 );
3915 for(i=0;i<sdef->nElements;i++){
3916 if(sdef->elements[i].of_type){
3917 src=mputprintf(src,
3918 "%s%s_descr_.text->val.parameters->decoding_params.repeatable"
3919 ,first?" && ":""
3920 ,sdef->elements[i].typedescrname
3921 );
3922 first=1;
3923 }
3924 }
3925 src=mputstr(src,
3926 ") has_repeatable=1;\n"
3927 );
3928
3929 }
3930 for(i=0;i<sdef->nElements;i++){
3931 if(sdef->elements[i].isOptional){
3932 src=mputprintf(src,
3933 " field_%s=OMIT_VALUE;\n"
3934 ,sdef->elements[i].name
3935 );
3936 }
3937 }
3938 src = mputprintf(src,
3939 " while(mand_field_num+opt_field_num%s){\n"
3940 " loop_detector=1;\n"
3941 " while(TRUE){\n"
3942 ,seof?"+has_repeatable":""
3943 );
3944
3945 for(i=0;i<sdef->nElements;i++){
3946 if(sdef->elements[i].of_type){
3947 src=mputprintf(src,
3948 " if( (%s_descr_.text->val.parameters->decoding_params.repeatable"
3949 " && field_map[%lu]<3) || !field_map[%lu]){\n"
3950 " pos=p_buf.get_pos();\n"
3951 " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf,"
3952 "limit,true,!field_map[%lu]);\n"
3953 " if(decoded_field_length<0){\n"
3954 " p_buf.set_pos(pos);\n"
3955 ,sdef->elements[i].typedescrname,(unsigned long) i,(unsigned long) i
3956 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
3957 ,sdef->elements[i].typedescrname
3958 ,(unsigned long) i
3959 );
3960
3961 if(sdef->elements[i].isOptional){
3962 src=mputprintf(src,
3963 " if(!field_map[%lu]) field_%s=OMIT_VALUE;\n"
3964 ,(unsigned long) i
3965 ,sdef->elements[i].name
3966 );
3967 }
3968 src=mputprintf(src,
3969 " }else{\n"
3970 " loop_detector=0;\n"
3971 " if(!field_map[%lu]) {%s--;field_map[%lu]=1;}\n"
3972 " else field_map[%lu]=2;\n"
3973 " last_field_num=%lu;\n"
3974 " break;\n"
3975 " }\n"
3976 " }\n"
3977 ,(unsigned long) i
3978 ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num"
3979 ,(unsigned long) i,(unsigned long) i,(unsigned long) i
3980 );
3981 } else {
3982 src=mputprintf(src,
3983 " if(!field_map[%lu]){\n"
3984 " pos=p_buf.get_pos();\n"
3985 " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf,"
3986 "limit,true);\n"
3987 " if(decoded_field_length<0){\n"
3988 " p_buf.set_pos(pos);\n"
3989 "%s%s%s"
3990 " }else{\n"
3991 " loop_detector=0;\n"
3992 " field_map[%lu]=1;\n"
3993 " %s--;\n"
3994 " last_field_num=%lu;\n"
3995 " break;\n"
3996 " }\n"
3997 " }\n"
3998 ,(unsigned long) i
3999 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4000 ,sdef->elements[i].typedescrname
4001 ,sdef->elements[i].isOptional?" field_":""
4002 ,sdef->elements[i].isOptional?sdef->elements[i].name:""
4003 ,sdef->elements[i].isOptional?"=OMIT_VALUE;\n":"",(unsigned long) i
4004 ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num"
4005 ,(unsigned long) i
4006 );
4007 }
4008 }
4009
4010 src = mputstr(src,
4011 " break;\n"
4012 " }\n"
4013 " if(loop_detector) break;\n"
4014 " if(p_td.text->separator_decode){\n"
4015 " int tl;\n"
4016 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
4017 " if(p_td.text->end_decode){\n"
4018 " int tl;\n"
4019 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
4020 " sep_found=FALSE;\n"
4021 " break;\n"
4022 " }\n"
4023 " } else if(limit.has_token(ml)){\n"
4024 " int tl;\n"
4025 " if((tl=limit.match(p_buf,ml))==0){\n"
4026 " sep_found=FALSE;\n"
4027 " break;\n"
4028 " }\n"
4029 " } else break;\n"
4030 " p_buf.set_pos(pos);\n"
4031 " decoded_length-=decoded_field_length;\n"
4032 " field_map[last_field_num]+=2;\n"
4033 );
4034
4035 if(opt_number){
4036 src=mputstr(src,
4037 "switch(last_field_num){\n"
4038 );
4039 for(i=0;i<sdef->nElements;i++){
4040 if(sdef->elements[i].of_type){
4041 if(sdef->elements[i].isOptional){
4042 src=mputprintf(src,
4043 " case %lu:\n"
4044 " if(field_map[%lu]==3){\n"
4045 " field_%s=OMIT_VALUE;\n"
4046 " opt_field_num++;\n"
4047 " }\n"
4048 " break;\n"
4049 ,(unsigned long) i,(unsigned long) i,sdef->elements[i].name
4050 );
4051 } else {
4052 src=mputprintf(src,
4053 " case %lu:\n"
4054 " if(field_map[%lu]==3){\n"
4055 " mand_field_num++;\n"
4056 " }\n"
4057 " break;\n"
4058 ,(unsigned long) i,(unsigned long) i
4059 );
4060 }
4061 } else if(sdef->elements[i].isOptional){
4062 src=mputprintf(src,
4063 " case %lu:\n"
4064 " field_%s=OMIT_VALUE;\n"
4065 " opt_field_num++;\n"
4066 " break;\n"
4067 ,(unsigned long) i,sdef->elements[i].name
4068 );
4069 }
4070 }
4071 src=mputstr(src,
4072 " default:\n"
4073 " mand_field_num++;\n"
4074 " break;\n"
4075 "}\n"
4076 );
4077 }
4078
4079 src = mputprintf(src,
4080 " } else {\n"
4081 " sep_length=tl;\n"
4082 " decoded_length+=tl;\n"
4083 " p_buf.increase_pos(tl);\n"
4084 " for(int a=0;a<%lu;a++) if(field_map[a]>2) field_map[a]-=3;\n"
4085 " sep_found=TRUE;}\n"
4086 " } else if(p_td.text->end_decode){\n"
4087 " int tl;\n"
4088 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
4089 " decoded_length+=tl;\n"
4090 " p_buf.increase_pos(tl);\n"
4091 " limit.remove_tokens(ml);\n"
4092 " if(mand_field_num) return -1;\n"
4093 " return decoded_length;\n"
4094 " }\n"
4095 " } else if(limit.has_token(ml)){\n"
4096 " int tl;\n"
4097 " if((tl=limit.match(p_buf,ml))==0){\n"
4098 " sep_found=FALSE;\n"
4099 " break;\n"
4100 " }\n"
4101 " }\n"
4102 " }\n"
4103 " limit.remove_tokens(ml);\n"
4104 " if(sep_found){\n"
4105 " if(mand_field_num){\n"
4106 " if(no_err)return -1;\n"
4107 " TTCN_EncDec_ErrorContext::error"
4108 "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding '%%s': \","
4109 "p_td.name);\n"
4110 " return decoded_length;\n"
4111 " } else {\n"
4112 " decoded_length-=sep_length;\n"
4113 " p_buf.set_pos(p_buf.get_pos()-sep_length);\n"
4114 " }\n"
4115 " }\n"
4116 " if(p_td.text->end_decode){\n"
4117 " int tl;\n"
4118 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
4119 " if(no_err)return -1;\n"
4120 " TTCN_EncDec_ErrorContext::error"
4121 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
4122 " not found for '%%s': \",(const char*)*(p_td.text->end_decode)"
4123 ",p_td.name);\n"
4124 " return decoded_length;\n"
4125 " }\n"
4126 " decoded_length+=tl;\n"
4127 " p_buf.increase_pos(tl);\n"
4128 " }\n"
4129 " if(mand_field_num) return -1;\n"
4130 " return decoded_length;\n"
4131 "}\n"
4132 ,(unsigned long) sdef->nElements
4133 );
4134 } else { /* record decoder start */
4135 src = mputprintf(src,
4136 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
4137 " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n"
509718e0 4138 " bound_flag = TRUE;\n"
970ed795
EL
4139 " int decoded_length=0;\n"
4140 " int decoded_field_length=0;\n"
4141 "%s"
4142 " boolean sep_found=FALSE;\n"
4143 " int sep_length=0;\n"
4144 " int ml=0;\n"
4145 " if(p_td.text->begin_decode){\n"
4146 " int tl;\n"
4147 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
4148 " if(no_err)return -1;\n"
4149 " TTCN_EncDec_ErrorContext::error\n"
4150 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
4151 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
4152 ", p_td.name);\n"
4153 " return 0;\n"
4154 " }\n"
4155 " decoded_length+=tl;\n"
4156 " p_buf.increase_pos(tl);\n"
4157 " }\n"
4158 " if(p_td.text->end_decode){\n"
4159 " limit.add_token(p_td.text->end_decode);\n"
4160 " ml++;\n"
4161 " }\n"
4162 " if(p_td.text->separator_decode){\n"
4163 " limit.add_token(p_td.text->separator_decode);\n"
4164 " ml++;\n"
4165 " }\n"
4166 ,name,opt_number?" size_t pos=p_buf.get_pos();\n":""
4167 );
4168 for(i=0;i<sdef->nElements;i++){
4169 if(sdef->elements[i].isOptional){
4170 src=mputprintf(src,
4171 " field_%s=OMIT_VALUE;\n"
4172 ,sdef->elements[i].name
4173 );
4174 } }
4175 src=mputstr(src,
4176 " while(TRUE){\n"
4177 );
4178 for(i=0;i<sdef->nElements;i++){
4179 if(sdef->elements[i].isOptional){
4180 src=mputstr(src,
4181 " pos=p_buf.get_pos();\n"
4182 );
4183 }
4184 src=mputprintf(src,
4185 " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf"
4186 ",limit,TRUE);\n"
4187 " if(decoded_field_length<0){\n"
4188 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4189 ,sdef->elements[i].typedescrname
4190 );
4191 if(sdef->elements[i].isOptional){
4192 src=mputprintf(src,
4193 " field_%s=OMIT_VALUE;\n"
4194 " p_buf.set_pos(pos);\n"
4195 " } else {\n"
4196 ,sdef->elements[i].name
4197 );
4198 } else {
4199 src=mputprintf(src,
4200 " limit.remove_tokens(ml);\n"
4201 " if(no_err)return -1;\n"
4202 " TTCN_EncDec_ErrorContext::error"
4203 "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding "
4204 "field '%s' for '%%s': \", p_td.name);\n"
4205 " return decoded_length;\n"
4206 " } else {\n"
4207 ,sdef->elements[i].name
4208 );
4209 }
4210 src=mputstr(src,
4211 " decoded_length+=decoded_field_length;\n"
4212 );
4213 if(last_man_index>(i+1)){
4214 src=mputstr(src,
4215 " if(p_td.text->separator_decode){\n"
4216 " int tl;\n"
4217 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
4218 );
4219
4220 if(sdef->elements[i].isOptional){
4221 src=mputprintf(src,
4222 " field_%s=OMIT_VALUE;\n"
4223 " p_buf.set_pos(pos);\n"
4224 " decoded_length-=decoded_field_length;\n"
4225 ,sdef->elements[i].name
4226 );
4227 } else {
4228 src=mputstr(src,
4229 " limit.remove_tokens(ml);\n"
4230 " if(no_err)return -1;\n"
4231 " TTCN_EncDec_ErrorContext::error"
4232 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'"
4233 " not found for '%s': \",(const char*)*(p_td.text->"
4234 "separator_decode),p_td.name);\n"
4235 " return decoded_length;\n"
4236 );
4237 }
4238
4239 src=mputstr(src,
4240 " } else {\n"
4241 " decoded_length+=tl;\n"
4242 " p_buf.increase_pos(tl);\n"
4243 " sep_length=tl;\n"
4244 " sep_found=TRUE;}\n"
4245 " } else sep_found=FALSE;\n"
4246 );
4247 } else if(i==(sdef->nElements-1)){
4248 src=mputstr(src,
4249 " sep_found=FALSE;\n"
4250 );
4251 } else {
4252 src=mputstr(src,
4253 " if(p_td.text->separator_decode){\n"
4254 " int tl;\n"
4255 " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n"
4256 );
4257 if(sdef->elements[i].isOptional){
4258 src=mputprintf(src,
4259 " if(p_td.text->end_decode){\n"
4260 " int tl;\n"
4261 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
4262 " decoded_length+=tl;\n"
4263 " p_buf.increase_pos(tl);\n"
4264 " limit.remove_tokens(ml);\n"
4265 " return decoded_length;\n"
4266 " }\n"
4267 " } else if(limit.has_token(ml)){\n"
4268 " if((tl=limit.match(p_buf,ml))==0){\n"
4269 " sep_found=FALSE;\n"
4270 " break;\n"
4271 " }\n"
4272 " } else break;\n"
4273 " field_%s=OMIT_VALUE;\n"
4274 " p_buf.set_pos(pos);\n"
4275 " decoded_length-=decoded_field_length;\n"
4276 ,sdef->elements[i].name
4277 );
4278 } else {
4279 src=mputstr(src,
4280 " sep_found=FALSE;\n"
4281 " break;\n"
4282 );
4283 }
4284 src=mputstr(src,
4285 " } else {\n"
4286 " decoded_length+=tl;\n"
4287 " p_buf.increase_pos(tl);\n"
4288 " sep_length=tl;\n"
4289 " sep_found=TRUE;}\n"
4290 " } else {\n"
4291 " sep_found=FALSE;\n"
4292 " if(p_td.text->end_decode){\n"
4293 " int tl;\n"
4294 " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n"
4295 " decoded_length+=tl;\n"
4296 " p_buf.increase_pos(tl);\n"
4297 " limit.remove_tokens(ml);\n"
4298 " return decoded_length;\n"
4299 " }\n"
4300 " } else if(limit.has_token(ml)){\n"
4301 " int tl;\n"
4302 " if((tl=limit.match(p_buf,ml))==0){\n"
4303 " sep_found=FALSE;\n"
4304 " break;\n"
4305 " }\n"
4306 " }\n"
4307 " }\n"
4308 );
4309 }
4310 src=mputstr(src,
4311 " }\n"
4312 );
4313 }
4314
4315 src = mputstr(src,
4316 " break;\n"
4317 " }\n"
4318 " limit.remove_tokens(ml);\n"
4319 " if(sep_found){\n"
4320 " p_buf.set_pos(p_buf.get_pos()-sep_length);\n"
4321 " decoded_length-=sep_length;\n"
4322 " }\n"
4323 " if(p_td.text->end_decode){\n"
4324 " int tl;\n"
4325 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
4326 " if(no_err)return -1;\n"
4327 " TTCN_EncDec_ErrorContext::error"
4328 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'"
4329 " not found for '%s': \",(const char*)*(p_td.text->end_decode)"
4330 ",p_td.name);\n"
4331 " return decoded_length;\n"
4332 " }\n"
4333 " decoded_length+=tl;\n"
4334 " p_buf.increase_pos(tl);\n"
4335 " }\n"
4336 " return decoded_length;\n"
4337 "}\n"
4338 );
4339 }
4340 } /* text_needed */
4341
4342 /* RAW functions */
4343 if(raw_needed){
4344 struct raw_option_struct *raw_options;
4345 boolean haslengthto, haspointer, hascrosstag, has_ext_bit;
4346 raw_options = (struct raw_option_struct*)
4347 Malloc(sdef->nElements * sizeof(*raw_options));
4348
4349 set_raw_options(sdef, raw_options, &haslengthto,
4350 &haspointer, &hascrosstag, &has_ext_bit);
4351
4352 src = generate_raw_coding(src, sdef, raw_options, haspointer, hascrosstag,
4353 has_ext_bit);
4354
4355 for (i = 0; i < sdef->nElements; i++) {
4356 Free(raw_options[i].lengthoffield);
4357 Free(raw_options[i].dependent_fields);
4358 }
4359 Free(raw_options);
4360 } /* if raw_needed */
4361
4362 if (xer_needed) gen_xer(sdef, &def, &src);
4363
4364 if (json_needed) {
4365 // JSON encode, RT1
4366 src = mputprintf(src,
4367 "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
4368 "{\n"
4369 " if (!is_bound()) {\n"
4370 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
4371 " \"Encoding an unbound value of type %s.\");\n"
4372 " return -1;\n"
4373 " }\n\n"
4374 " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n"
4375 , name, dispname);
4376 for (i = 0; i < sdef->nElements; ++i) {
3abe9331 4377 if (sdef->elements[i].isOptional && !sdef->elements[i].jsonOmitAsNull &&
4378 !sdef->elements[i].jsonMetainfoUnbound) {
970ed795
EL
4379 src = mputprintf(src,
4380 " if (field_%s.is_present())\n"
4381 , sdef->elements[i].name);
4382 }
3abe9331 4383 src = mputprintf(src,
970ed795 4384 " {\n"
3abe9331 4385 " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n "
4386 , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
4387 if (sdef->elements[i].jsonMetainfoUnbound) {
4388 src = mputprintf(src,
4389 "if (!field_%s.is_bound()) {\n"
4390 " enc_len += p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL);\n"
4391 " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"metainfo %s\");\n"
4392 " enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, \"\\\"unbound\\\"\");\n"
4393 " }\n"
4394 " else "
4395 , sdef->elements[i].name
4396 , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
4397 }
4398 src = mputprintf(src,
4399 "enc_len += field_%s.JSON_encode(%s_descr_, p_tok);\n"
970ed795 4400 " }\n\n"
970ed795
EL
4401 , sdef->elements[i].name, sdef->elements[i].typedescrname);
4402 }
4403 src = mputstr(src,
4404 " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
4405 " return enc_len;\n"
4406 "}\n\n");
4407
4408 // JSON decode, RT1
4409 src = mputprintf(src,
4410 "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
4411 "{\n"
509718e0 4412 " json_token_t j_token = JSON_TOKEN_NONE;\n"
4413 " int dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n"
4414 " if (JSON_TOKEN_ERROR == j_token) {\n"
970ed795
EL
4415 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
4416 " return JSON_ERROR_FATAL;\n"
4417 " }\n"
509718e0 4418 " else if (JSON_TOKEN_OBJECT_START != j_token) {\n"
970ed795
EL
4419 " return JSON_ERROR_INVALID_TOKEN;\n"
4420 " }\n"
4421 " bound_flag = TRUE;\n\n"
3abe9331 4422 , name);
4423 boolean has_metainfo_enabled = FALSE;
4424 for (i = 0; i < sdef->nElements; ++i) {
4425 if (sdef->elements[i].jsonMetainfoUnbound) {
4426 // initialize meta info states
4427 src = mputprintf(src,
4428 " int metainfo_%s = JSON_METAINFO_NONE;\n"
4429 , sdef->elements[i].name);
4430 has_metainfo_enabled = TRUE;
4431 }
4432 }
4433 src = mputstr(src,
4434 // Read name - value token pairs until we reach some other token
4435 "\n while (true) {\n"
509718e0 4436 " char* fld_name = 0;\n"
970ed795
EL
4437 " size_t name_len = 0;\n"
4438 " size_t buf_pos = p_tok.get_buf_pos();\n"
509718e0 4439 " dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n"
4440 " if (JSON_TOKEN_ERROR == j_token) {\n"
970ed795
EL
4441 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n"
4442 " return JSON_ERROR_FATAL;\n"
4443 " }\n"
4444 // undo the last action on the buffer
509718e0 4445 " else if (JSON_TOKEN_NAME != j_token) {\n"
970ed795
EL
4446 " p_tok.set_buf_pos(buf_pos);\n"
4447 " break;\n"
4448 " }\n"
3abe9331 4449 " else {\n ");
4450 if (has_metainfo_enabled) {
4451 // check for meta info
4452 src = mputstr(src,
4453 "boolean is_metainfo = FALSE;\n"
4454 " if (name_len > 9 && 0 == strncmp(fld_name, \"metainfo \", 9)) {\n"
4455 " fld_name += 9;\n"
4456 " name_len -= 9;\n"
4457 " is_metainfo = TRUE;\n"
4458 " }\n ");
4459 }
970ed795
EL
4460 for (i = 0; i < sdef->nElements; ++i) {
4461 src = mputprintf(src,
4462 // check field name
509718e0 4463 "if (%d == name_len && 0 == strncmp(fld_name, \"%s\", name_len)) {\n"
970ed795 4464 , (int)strlen(sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname)
3abe9331 4465 , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname);
4466 if (has_metainfo_enabled) {
4467 src = mputstr(src, " if (is_metainfo) {\n");
4468 if (sdef->elements[i].jsonMetainfoUnbound) {
4469 src = mputprintf(src,
4470 // check meta info
4471 " char* info_value = 0;\n"
4472 " size_t info_len = 0;\n"
4473 " dec_len += p_tok.get_next_token(&j_token, &info_value, &info_len);\n"
4474 " if (JSON_TOKEN_STRING == j_token && 9 == info_len &&\n"
4475 " 0 == strncmp(info_value, \"\\\"unbound\\\"\", 9)) {\n"
4476 " metainfo_%s = JSON_METAINFO_UNBOUND;\n"
4477 " }\n"
4478 " else {\n"
4479 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_VALUE_ERROR, \"%s\");\n"
4480 " return JSON_ERROR_FATAL;\n"
4481 " }\n"
4482 , sdef->elements[i].name, sdef->elements[i].dispname);
4483 }
4484 else {
4485 src = mputprintf(src,
4486 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_NOT_APPLICABLE, \"%s\");\n"
4487 " return JSON_ERROR_FATAL;\n"
4488 , sdef->elements[i].dispname);
4489 }
4490 src = mputstr(src,
4491 " }\n"
4492 " else {\n");
4493 if (sdef->elements[i].jsonMetainfoUnbound) {
4494 src = mputstr(src, " buf_pos = p_tok.get_buf_pos();\n");
4495 }
4496 }
4497 src = mputprintf(src,
4498 " int ret_val = field_%s.JSON_decode(%s_descr_, p_tok, p_silent);\n"
4499 " if (0 > ret_val) {\n"
4500 " if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n"
4501 , sdef->elements[i].name, sdef->elements[i].typedescrname);
4502 if (sdef->elements[i].jsonMetainfoUnbound) {
4503 src = mputprintf(src,
4504 // undo the last action on the buffer, check if the invalid token was a null token
4505 " p_tok.set_buf_pos(buf_pos);\n"
4506 " p_tok.get_next_token(&j_token, NULL, NULL);\n"
4507 " if (JSON_TOKEN_LITERAL_NULL == j_token) {\n"
4508 " if (JSON_METAINFO_NONE == metainfo_%s) {\n"
4509 // delay reporting an error for now, there might be meta info later
4510 " metainfo_%s = JSON_METAINFO_NEEDED;\n"
4511 " continue;\n"
4512 " }\n"
4513 " else if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n"
4514 // meta info already found
4515 " continue;\n"
4516 " }\n"
4517 " }\n"
4518 , sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name);
4519 }
4520 src = mputprintf(src,
4521 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n"
4522 " }\n"
4523 " return JSON_ERROR_FATAL;\n"
4524 " }\n"
4525 " dec_len += ret_val;\n"
970ed795 4526 , sdef->elements[i].dispname);
3abe9331 4527 if (has_metainfo_enabled) {
4528 src = mputstr(src, " }\n");
4529 }
4530 src = mputstr(src,
4531 " }\n"
4532 " else ");
970ed795 4533 }
3abe9331 4534 src = mputprintf(src,
970ed795
EL
4535 "{\n"
4536 // invalid field name
509718e0 4537 " char* fld_name2 = mcopystrn(fld_name, name_len);\n"
3abe9331 4538 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, %sJSON_DEC_INVALID_NAME_ERROR, fld_name2);\n"
970ed795 4539 // if this is set to a warning, skip the value of the field
509718e0 4540 " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
4541 " if (JSON_TOKEN_NUMBER != j_token && JSON_TOKEN_STRING != j_token &&\n"
4542 " JSON_TOKEN_LITERAL_TRUE != j_token && JSON_TOKEN_LITERAL_FALSE != j_token &&\n"
4543 " JSON_TOKEN_LITERAL_NULL != j_token) {\n"
4544 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name2);\n"
4545 " Free(fld_name2);\n"
970ed795
EL
4546 " return JSON_ERROR_FATAL;\n"
4547 " }\n"
509718e0 4548 " Free(fld_name2);\n"
970ed795
EL
4549 " }\n"
4550 " }\n"
4551 " }\n\n"
509718e0 4552 " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n"
4553 " if (JSON_TOKEN_OBJECT_END != j_token) {\n"
970ed795
EL
4554 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_OBJECT_END_TOKEN_ERROR, \"\");\n"
4555 " return JSON_ERROR_FATAL;\n"
3abe9331 4556 " }\n\n "
4557 , has_metainfo_enabled ? "is_metainfo ?\n JSON_DEC_METAINFO_NAME_ERROR : " : "");
4558 // Check if every field has been set and handle meta info
970ed795 4559 for (i = 0; i < sdef->nElements; ++i) {
3abe9331 4560 if (sdef->elements[i].jsonMetainfoUnbound) {
4561 src = mputprintf(src,
4562 "if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n"
4563 " field_%s.clean_up();\n"
4564 " }\n"
4565 " else if (JSON_METAINFO_NEEDED == metainfo_%s) {\n"
4566 // no meta info was found for this field, report the delayed error
4567 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n"
4568 " }\n"
4569 " else "
4570 , sdef->elements[i].name, sdef->elements[i].name
4571 , sdef->elements[i].name, sdef->elements[i].dispname);
4572 }
970ed795 4573 src = mputprintf(src,
3abe9331 4574 "if (!field_%s.is_bound()) {\n"
970ed795
EL
4575 , sdef->elements[i].name);
4576 if (sdef->elements[i].jsonDefaultValue) {
4577 src = mputprintf(src,
4578 " field_%s.JSON_decode(%s_descr_, DUMMY_BUFFER, p_silent);\n"
4579 , sdef->elements[i].name, sdef->elements[i].typedescrname);
4580 }
4581 else if (sdef->elements[i].isOptional) {
4582 src = mputprintf(src,
4583 " field_%s = OMIT_VALUE;\n"
4584 , sdef->elements[i].name);
4585 } else {
4586 src = mputprintf(src,
4587 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_MISSING_FIELD_ERROR, \"%s\");\n"
4588 " return JSON_ERROR_FATAL;\n"
4589 , sdef->elements[i].dispname);
4590 }
4591 src = mputstr(src,
4592 " }\n");
4593 }
4594 src = mputstr(src,
509718e0 4595 "\n return dec_len;\n"
970ed795
EL
4596 "}\n\n");
4597 }
4598
4599 /* end of class definition */
4600 def = mputstr(def, "};\n\n");
4601
4602 output->header.class_defs = mputstr(output->header.class_defs, def);
4603 Free(def);
4604
4605 output->source.methods = mputstr(output->source.methods, src);
4606 Free(src);
4607}
4608
4609
4610static char *genRawFieldDecodeLimit(char *src, const struct_def *sdef,
4611 int i, const struct raw_option_struct *raw_options)
4612{
4613 /* number of arguments passed to min_of_ints() */
4614 int nof_args = 1;
4615 int j;
4616 for (j = 0; j < raw_options[i].lengthof; j++) {
4617 int field_index = raw_options[i].lengthoffield[j];
4618 if (i > field_index && sdef->elements[field_index].raw.unit!=-1)
4619 nof_args++;
4620 }
4621 if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[
4622 raw_options[i].extbitgroup-1].ext_bit != XDEFNO) nof_args++;
4623 if (nof_args > 1) {
4624 src = mputprintf(src, "min_of_ints(%d, limit", nof_args);
4625 for (j = 0; j < raw_options[i].lengthof; j++) {
4626 int field_index = raw_options[i].lengthoffield[j];
4627 if (i > field_index && sdef->elements[field_index].raw.unit != -1)
4628 src = mputprintf(src, ", value_of_length_field%d", field_index);
4629 }
4630 if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[
4631 raw_options[i].extbitgroup-1].ext_bit != XDEFNO)
4632 src = mputstr(src, ", group_limit");
4633 src = mputc(src, ')');
4634 } else {
4635 src = mputstr(src, "limit");
4636 }
4637 return src;
4638}
4639
4640static char *genRawDecodeRecordField(char *src, const struct_def *sdef,
4641 int i, const struct raw_option_struct *raw_options, boolean delayed_decode,
4642 int *prev_ext_group)
4643{
4644 int a;
4645 if(raw_options[i].ptrbase)
4646 src=mputprintf(src,
4647 " start_pos_of_field%d=p_buf.get_pos_bit();\n"
4648 ,i
4649 );
4650 if (*prev_ext_group != raw_options[i].extbitgroup) {
4651 *prev_ext_group = raw_options[i].extbitgroup;
4652 if(prev_ext_group &&
4653 sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){
4654 if(raw_options[i].pointerof) /* pointed field */
4655 src=mputprintf(src,
4656 " {size_t old_pos=p_buf.get_pos_bit();\n"
4657 " if(start_of_field%d!=-1 && start_pos_of_field%d!=-1){\n"
4658 " start_of_field%d=start_pos_of_field%d"
4659 "+(int)field_%s%s*%d+%d;\n"
4660 " p_buf.set_pos_bit(start_of_field%d);\n"
4661 " limit=end_of_available_data-start_of_field%d;\n"
4662 ,i
4663 ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase
4664 ,i
4665 ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase
4666 ,sdef->elements[raw_options[i].pointerof-1].name
4667 ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":""
4668 ,sdef->elements[raw_options[i].pointerof-1].raw.unit
4669 ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset
4670 ,i,i
4671 );
4672 src=mputprintf(src,
4673 " {\n"
4674 " cbyte* data=p_buf.get_read_data();\n"
4675 " int count=1;\n"
4676 " int rot=local_top_order==ORDER_LSB?0:7;\n"
4677 " while(((data[count-1]>>rot)&0x01)==%d && count*8<"
4678 "(int)limit) count++;\n"
4679 " if(limit) group_limit=count*8;\n"
4680 " }\n"
4681 ,sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit==
4682 XDEFYES?0:1
4683 );
4684 if(raw_options[i].pointerof) /* pointed field */
4685 src=mputstr(src,
4686 " } else group_limit=0;\n"
4687 " p_buf.set_pos_bit(old_pos);\n"
4688 " limit=end_of_available_data-old_pos;}\n"
4689 );
4690 }
4691 }
4692 if(sdef->elements[i].hasRaw && /* check the crosstag */
4693 sdef->elements[i].raw.crosstaglist.nElements){
4694 /* field index of the otherwise rule */
4695 int other = -1;
4696 boolean first_value = TRUE;
4697 int j;
4698 for (j = 0; j < sdef->elements[i].raw.crosstaglist.nElements; j++) {
4699 rawAST_coding_taglist* cur_choice =
4700 sdef->elements[i].raw.crosstaglist.list + j;
4701 if (cur_choice->nElements > 0) {
4702 /* this is a normal rule */
4703 if (first_value) {
4704 src = mputstr(src, " if (");
4705 first_value = FALSE;
4706 } else src = mputstr(src, " else if (");
4707 src = genRawFieldChecker(src, cur_choice, TRUE);
4708 /* set selected_field in the if's body */
4709 src = mputprintf(src, ") selected_field = %d;\n",
4710 cur_choice->fieldnum);
4711 } else {
4712 /* this is an otherwise rule */
4713 other = cur_choice->fieldnum;
4714 }
4715 }
4716 /* set selected_field to the field index of the otherwise rule or -1 */
4717 src = mputprintf(src, " else selected_field = %d;\n", other);
4718 }
4719 /* check the presence of optional field*/
4720 if(sdef->elements[i].isOptional){
4721 /* check if enough bits to decode the field*/
4722 src = mputstr(src, " if (limit > 0");
4723 for (a = 0; a < raw_options[i].lengthof; a++){
4724 int field_index = raw_options[i].lengthoffield[a];
4725 if (i > field_index) src = mputprintf(src,
4726 " && value_of_length_field%d > 0", field_index);
4727 }
4728 if (raw_options[i].extbitgroup &&
4729 sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){
4730 src = mputstr(src, " && group_limit > 0");
4731 }
4732 if(raw_options[i].pointerof){ /* valid pointer?*/
4733 src=mputprintf(src,
4734 " && start_of_field%d!=-1 && start_pos_of_field%d!=-1"
4735 ,i,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase
4736 );
4737 }
4738 if(sdef->elements[i].hasRaw &&
4739 sdef->elements[i].raw.presence.nElements)
4740 {
4741 src = mputstr(src, " && ");
4742 if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, '(');
4743 src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, TRUE);
4744 if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, ')');
4745 }
4746 if(sdef->elements[i].hasRaw &&
4747 sdef->elements[i].raw.crosstaglist.nElements)
4748 {
4749 src=mputstr(src,
4750 "&& selected_field!=-1"
4751 );
4752 }
4753 src=mputstr(src,
4754 "){\n"
4755 );
4756 }
4757 if(raw_options[i].pointerof){ /* pointed field */
4758 src=mputprintf(src,
4759 " start_of_field%d=start_pos_of_field%d"
4760 "+(int)field_%s%s*%d+%d;\n"
4761 ,i
4762 ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase
4763 ,sdef->elements[raw_options[i].pointerof-1].name
4764 ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":""
4765 ,sdef->elements[raw_options[i].pointerof-1].raw.unit
4766 ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset
4767 );
4768 src=mputprintf(src,
4769 " p_buf.set_pos_bit(start_of_field%d);\n"
4770 " limit=end_of_available_data-start_of_field%d;\n"
4771 ,i,i
4772 );
4773 }
4774 /* decoding of normal field */
4775 if (sdef->elements[i].isOptional) src = mputstr(src,
4776 " size_t fl_start_pos = p_buf.get_pos_bit();\n");
4777 src = mputprintf(src,
4778 " decoded_field_length = field_%s%s.RAW_decode(%s_descr_, p_buf, ",
4779 sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "",
4780 sdef->elements[i].typedescrname);
4781 if (delayed_decode) {
4782 /* the fixed field length is used as limit in case of delayed decoding */
4783 src = mputprintf(src, "%d", sdef->elements[i].raw.length);
4784 } else {
4785 src = genRawFieldDecodeLimit(src, sdef, i, raw_options);
4786 }
4787 src = mputprintf(src, ", local_top_order, %s",
4788 sdef->elements[i].isOptional ? "TRUE" : "no_err");
4789 if (sdef->elements[i].hasRaw &&
4790 sdef->elements[i].raw.crosstaglist.nElements > 0)
4791 src = mputstr(src, ", selected_field");
4792 for (a = 0; a < raw_options[i].lengthof; a++) {
4793 int field_index = raw_options[i].lengthoffield[a];
4794 /* number of elements in 'record of' or 'set of' */
4795 if (sdef->elements[field_index].raw.unit == -1) {
4796 src = mputprintf(src, ", value_of_length_field%d", field_index);
4797 break;
4798 }
4799 }
4800 src = mputstr(src, ");\n");
4801 if (delayed_decode) {
4802 src = mputprintf(src, " if (decoded_field_length != %d) return -1;\n",
4803 sdef->elements[i].raw.length);
4804 } else if (sdef->elements[i].isOptional) {
4805 src = mputprintf(src, " if (decoded_field_length < 1) {\n"
4806 " field_%s = OMIT_VALUE;\n" /* transform errors into omit */
4807 " p_buf.set_pos_bit(fl_start_pos);\n"
4808 " } else {\n", sdef->elements[i].name);
4809 } else {
4810 src = mputstr(src, " if (decoded_field_length < 0) return decoded_field_length;\n");
4811 }
4812 if(raw_options[i].tag_type && sdef->raw.taglist.list[raw_options[i].tag_type-1].nElements){
4813 rawAST_coding_taglist* cur_choice=
4814 sdef->raw.taglist.list+raw_options[i].tag_type-1;
4815 src=mputstr(src,
4816 " if(");
4817 src=genRawFieldChecker(src,cur_choice,FALSE);
4818 src=mputstr(src,
4819 ")");
4820 if(sdef->elements[i].isOptional){
4821 src=mputprintf(src,
4822 "{\n field_%s=OMIT_VALUE;\n"
4823 " p_buf.set_pos_bit(fl_start_pos);\n }\n"
4824 " else {\n"
4825 ,sdef->elements[i].name
4826 );
4827 }else src=mputstr(src, " return -1;\n");
4828 }
4829 if (!delayed_decode) {
4830 src=mputstr(src,
4831 " decoded_length+=decoded_field_length;\n"
4832 " limit-=decoded_field_length;\n"
4833 " last_decoded_pos=bigger(last_decoded_pos, p_buf.get_pos_bit());\n"
4834 );
4835 }
4836 if(raw_options[i].extbitgroup &&
4837 sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){
4838 src=mputstr(src,
4839 "group_limit-=decoded_field_length;\n"
4840 );
4841 }
4842 if(raw_options[i].lengthto){ /* if the field is lengthto store the value*/
4843 if(sdef->elements[i].raw.lengthindex){
4844 if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){
4845 src=mputprintf(src,
4846 " if(field_%s%s.%s().ispresent()){\n"
4847 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4848 ,sdef->elements[i].raw.lengthindex->nthfieldname
4849 );
4850 }
4851 src=mputprintf(src,
4852 " value_of_length_field%d+=(int)field_%s%s.%s%s()*%d;\n"
4853 ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4854 ,sdef->elements[i].raw.lengthindex->nthfieldname
4855 ,sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD?"()":""
4856 ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit
4857 );
4858 if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){
4859 src=mputstr(src,
4860 " }\n"
4861 );
4862 }
4863 }
4864 else if(sdef->elements[i].raw.union_member_num){
4865 int m;
4866 src = mputprintf(src, " switch (field_%s%s.get_selection()) {\n",
4867 sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "");
4868 for (m = 1; m < sdef->elements[i].raw.union_member_num + 1; m++) {
4869 src = mputprintf(src, " case %s%s%s:\n"
4870 " value_of_length_field%d += (int)field_%s%s.%s() * %d;\n"
4871 " break;\n", sdef->elements[i].raw.member_name[0],
4872 "::ALT_",
4873 sdef->elements[i].raw.member_name[m], i, sdef->elements[i].name,
4874 sdef->elements[i].isOptional ? "()" : "",
4875 sdef->elements[i].raw.member_name[m],
4876 sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit);
4877 }
4878 src = mputprintf(src, " default:\n"
4879 " value_of_length_field%d = 0;\n"
4880 " }\n", i);
4881 }
4882 else{
4883 src=mputprintf(src,
4884 " value_of_length_field%d+=(int)field_%s%s*%d;\n"
4885 ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4886 ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit
4887 );
4888 }
4889 }
4890 if(raw_options[i].pointerto){ /* store the start of pointed field*/
4891 src=mputprintf(src,
4892 " start_of_field%d=(int)field_%s%s+%d?1:-1;\n"
4893 ,sdef->elements[i].raw.pointerto
4894 ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":""
4895 ,sdef->elements[i].raw.ptroffset
4896 );
4897 }
4898 if (!delayed_decode) {
4899 /* mark the used bits in length area*/
4900 for (a = 0; a < raw_options[i].lengthof; a++) {
4901 int field_index = raw_options[i].lengthoffield[a];
4902 src = mputprintf(src,
4903 " value_of_length_field%d -= decoded_field_length;\n", field_index);
4904 if (i == field_index) src = mputprintf(src,
4905 " if (value_of_length_field%d < 0) return -1;\n", field_index);
4906 }
4907 }
4908 if(sdef->elements[i].isOptional){
4909 src=mputprintf(src,
4910 " }\n }\n%s"
4911 " else field_%s=OMIT_VALUE;\n"
4912 ,raw_options[i].tag_type?" }\n":"",sdef->elements[i].name
4913 );
4914 }
4915 return src;
4916}
4917
4918#ifdef __SUNPRO_C
4919#define SUNPRO_PUBLIC "public:\n"
4920#define SUNPRO_PRIVATE "private:\n"
4921#else
4922#define SUNPRO_PUBLIC
4923#define SUNPRO_PRIVATE
4924#endif
4925
4926void defRecordTemplate1(const struct_def *sdef, output_struct *output)
4927{
4928 int i;
4929 const char *name = sdef->name, *dispname = sdef->dispname;
4930 const char* kind_str = sdef->kind == SET ? "set" : "record";
4931 char *def = NULL, *src = NULL;
4932
4933 size_t mandatory_fields_count;
4934
4935 /* class declaration */
4936 output->header.class_decls = mputprintf(output->header.class_decls,
4937 "class %s_template;\n", name);
4938
4939 if(sdef->nElements <= 0) {
4940 defEmptyRecordTemplate(name, dispname, output);
4941 return;
4942 }
4943
4944 /* template class definition */
4945 def = mputprintf(def, "class %s_template : public Base_Template {\n", name);
4946
4947 /* data members */
4948 def = mputprintf(def,
4949 SUNPRO_PUBLIC
4950 "struct single_value_struct;\n"
4951 SUNPRO_PRIVATE
4952 "union {\n"
4953 "single_value_struct *single_value;\n"
4954 "struct {\n"
4955 "unsigned int n_values;\n"
4956 "%s_template *list_value;\n"
4957 "} value_list;\n"
4958 "};\n\n", name);
4959 /* the definition of single_value_struct must be put into the source file
4960 * because the types of optional fields may be incomplete in this position
4961 * of header file (e.g. due to type recursion) */
4962 src = mputprintf(src, "struct %s_template::single_value_struct {\n", name);
4963 for (i = 0; i < sdef->nElements; i++) {
4964 src = mputprintf(src, "%s_template field_%s;\n",
4965 sdef->elements[i].type, sdef->elements[i].name);
4966 }
4967 src = mputstr(src, "};\n\n");
4968
4969 /* set_specific function (used in field access members) */
4970 def = mputstr(def, "void set_specific();\n");
4971 src = mputprintf(src, "void %s_template::set_specific()\n"
4972 "{\n"
4973 "if (template_selection != SPECIFIC_VALUE) {\n"
4974 "template_sel old_selection = template_selection;\n"
4975 "clean_up();\n"
4976 "single_value = new single_value_struct;\n"
4977 "set_selection(SPECIFIC_VALUE);\n"
4978 "if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {\n",
4979 name);
4980 for (i = 0; i < sdef->nElements; i++) {
4981 src = mputprintf(src, "single_value->field_%s = %s;\n",
4982 sdef->elements[i].name,
4983 sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE");
4984 }
4985 src = mputstr(src, "}\n"
4986 "}\n"
4987 "}\n\n");
4988
4989 /* copy_value function */
4990 def = mputprintf(def, "void copy_value(const %s& other_value);\n", name);
4991 src = mputprintf(src,
4992 "void %s_template::copy_value(const %s& other_value)\n"
4993 "{\n"
4994 "single_value = new single_value_struct;\n", name, name);
4995 for (i = 0; i < sdef->nElements; i++) {
4996 src = mputprintf(src,
4997 "if (other_value.%s().is_bound()) {\n", sdef->elements[i].name);
4998 if (sdef->elements[i].isOptional) {
4999 /* If the value is present, "reach into" the OPTIONAL with operator()
5000 * and pass the contained object to the template's constructor.
5001 * Else set the template to omit. */
5002 src = mputprintf(src,
5003 " if (other_value.%s().ispresent()) single_value->field_%s = "
5004 "other_value.%s()();\n"
5005 " else single_value->field_%s = OMIT_VALUE;\n",
5006 sdef->elements[i].name, sdef->elements[i].name,
5007 sdef->elements[i].name, sdef->elements[i].name);
5008 } else {
5009 src = mputprintf(src,
5010 " single_value->field_%s = other_value.%s();\n",
5011 sdef->elements[i].name, sdef->elements[i].name);
5012 }
5013 src = mputprintf(src, "} else {\n"
5014 " single_value->field_%s.clean_up();\n"
5015 "}\n", sdef->elements[i].name);
5016 }
5017 src = mputstr(src, "set_selection(SPECIFIC_VALUE);\n"
5018 "}\n\n");
5019
5020 /* copy_template function */
5021 def = mputprintf(def, "void copy_template(const %s_template& "
5022 "other_value);\n\n", name);
5023 src = mputprintf(src,
5024 "void %s_template::copy_template(const %s_template& other_value)\n"
5025 "{\n"
5026 "switch (other_value.template_selection) {\n"
5027 "case SPECIFIC_VALUE:\n", name, name);
5028 src = mputstr(src,
5029 "single_value = new single_value_struct;\n");
5030 for (i = 0; i < sdef->nElements; i++) {
5031 src = mputprintf(src,
5032 "if (UNINITIALIZED_TEMPLATE != other_value.%s().get_selection()) {\n",
5033 sdef->elements[i].name);
5034 src = mputprintf(src,
5035 "single_value->field_%s = other_value.%s();\n",
5036 sdef->elements[i].name, sdef->elements[i].name);
5037 src = mputprintf(src, "} else {\n"
5038 "single_value->field_%s.clean_up();\n"
5039 "}\n", sdef->elements[i].name);
5040 }
5041 src = mputprintf(src,
5042 "case OMIT_VALUE:\n"
5043 "case ANY_VALUE:\n"
5044 "case ANY_OR_OMIT:\n"
5045 "break;\n"
5046 "case VALUE_LIST:\n"
5047 "case COMPLEMENTED_LIST:\n"
5048 "value_list.n_values = other_value.value_list.n_values;\n"
5049 "value_list.list_value = new %s_template[value_list.n_values];\n"
5050 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
5051 "list_count++)\n"
5052 "value_list.list_value[list_count].copy_template("
5053 "other_value.value_list.list_value[list_count]);\n"
5054 "break;\n"
5055 "default:\n"
5056 "TTCN_error(\"Copying an uninitialized/unsupported template of type "
5057 "%s.\");\n"
5058 "break;\n"
5059 "}\n"
5060 "set_selection(other_value);\n"
5061 "}\n\n", name, dispname);
5062
5063 /* default constructor */
5064 def = mputprintf(def, "public:\n"
5065 "%s_template();\n", name);
5066 src = mputprintf(src, "%s_template::%s_template()\n"
5067 "{\n"
5068 "}\n\n", name, name);
5069
5070 /* constructor t1_template(template_sel other_value) */
5071 def = mputprintf(def, "%s_template(template_sel other_value);\n", name);
5072 src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n"
5073 " : Base_Template(other_value)\n"
5074 "{\n"
5075 "check_single_selection(other_value);\n"
5076 "}\n\n", name, name);
5077
5078 /* constructor t1_template(const t1& other_value) */
5079 def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name);
5080 src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n"
5081 "{\n"
5082 "copy_value(other_value);\n"
5083 "}\n\n", name, name, name);
5084
5085 /* constructor t1_template(const OPTIONAL<t1>& other_value) */
5086 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n",
5087 name, name);
5088 src = mputprintf(src,
5089 "%s_template::%s_template(const OPTIONAL<%s>& other_value)\n"
5090 "{\n"
5091 "switch (other_value.get_selection()) {\n"
5092 "case OPTIONAL_PRESENT:\n"
5093 "copy_value((const %s&)other_value);\n"
5094 "break;\n"
5095 "case OPTIONAL_OMIT:\n"
5096 "set_selection(OMIT_VALUE);\n"
5097 "break;\n"
5098 "default:\n"
5099 "TTCN_error(\"Creating a template of type %s from an unbound optional "
5100 "field.\");\n"
5101 "}\n"
5102 "}\n\n", name, name, name, name, dispname);
5103
5104 /* copy constructor */
5105 def = mputprintf(def, "%s_template(const %s_template& other_value);\n",
5106 name, name);
5107 src = mputprintf(src, "%s_template::%s_template(const %s_template& "
5108 "other_value)\n"
5109 ": Base_Template()\n" /* yes, the base class _default_ constructor */
5110 "{\n"
5111 "copy_template(other_value);\n"
5112 "}\n\n", name, name, name);
5113
5114 /* destructor */
5115 def = mputprintf(def, "~%s_template();\n", name);
5116 src = mputprintf(src, "%s_template::~%s_template()\n"
5117 "{\n"
5118 "clean_up();\n"
5119 "}\n\n", name, name);
5120
5121 /* assignment operator <- template_sel */
5122 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
5123 name);
5124 src = mputprintf(src,
5125 "%s_template& %s_template::operator=(template_sel other_value)\n"
5126 "{\n"
5127 "check_single_selection(other_value);\n"
5128 "clean_up();\n"
5129 "set_selection(other_value);\n"
5130 "return *this;\n"
5131 "}\n\n", name, name);
5132
5133 /* assignment operator <- value */
5134 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
5135 name, name);
5136
5137 src = mputprintf(src,
5138 "%s_template& %s_template::operator=(const %s& other_value)\n"
5139 "{\n"
5140 "clean_up();\n"
5141 "copy_value(other_value);\n"
5142 "return *this;\n"
5143 "}\n\n", name, name, name);
5144
5145 /* assignment operator <- optional value */
5146 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
5147 "other_value);\n", name, name);
5148
5149 src = mputprintf(src,
5150 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
5151 "{\n"
5152 "clean_up();\n"
5153 "switch (other_value.get_selection()) {\n"
5154 "case OPTIONAL_PRESENT:\n"
5155 "copy_value((const %s&)other_value);\n"
5156 "break;\n"
5157 "case OPTIONAL_OMIT:\n"
5158 "set_selection(OMIT_VALUE);\n"
5159 "break;\n"
5160 "default:\n"
5161 "TTCN_error(\"Assignment of an unbound optional field to a template "
5162 "of type %s.\");\n"
5163 "}\n"
5164 "return *this;\n"
5165 "}\n\n", name, name, name, name, dispname);
5166
5167 /* assignment operator <- template*/
5168 def = mputprintf(def,
5169 "%s_template& operator=(const %s_template& other_value);\n",
5170 name, name);
5171
5172 src = mputprintf(src,
5173 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
5174 "{\n"
5175 "if (&other_value != this) {\n"
5176 "clean_up();\n"
5177 "copy_template(other_value);\n"
5178 "}\n"
5179 "return *this;\n"
5180 "}\n\n", name, name, name);
5181
5182 /* match operation (template matching) */
3abe9331 5183 def = mputprintf(def, "boolean match(const %s& other_value, boolean legacy "
5184 "= FALSE) const;\n", name);
970ed795
EL
5185
5186 src = mputprintf(src,
3abe9331 5187 "boolean %s_template::match(const %s& other_value, boolean legacy) const\n"
970ed795
EL
5188 "{\n"
5189 "if (!other_value.is_bound()) return FALSE;\n"
5190 "switch (template_selection) {\n"
5191 "case ANY_VALUE:\n"
5192 "case ANY_OR_OMIT:\n"
5193 "return TRUE;\n"
5194 "case OMIT_VALUE:\n"
5195 "return FALSE;\n"
5196 "case SPECIFIC_VALUE:\n", name, name);
5197 for (i = 0; i < sdef->nElements; i++) {
5198 src = mputprintf(src,"if(!other_value.%s().is_bound()) return FALSE;\n", sdef->elements[i].name);
5199 if (sdef->elements[i].isOptional) src = mputprintf(src,
5200 "if((other_value.%s().ispresent() ? "
3abe9331 5201 "!single_value->field_%s.match((const %s&)other_value.%s(), legacy) : "
5202 "!single_value->field_%s.match_omit(legacy)))",
970ed795
EL
5203 sdef->elements[i].name, sdef->elements[i].name,
5204 sdef->elements[i].type, sdef->elements[i].name,
5205 sdef->elements[i].name);
5206 else src = mputprintf(src,
3abe9331 5207 "if(!single_value->field_%s.match(other_value.%s(), legacy))",
970ed795
EL
5208 sdef->elements[i].name, sdef->elements[i].name);
5209 src = mputstr(src, "return FALSE;\n");
5210 }
5211 src = mputprintf(src,
5212 "return TRUE;\n"
5213 "case VALUE_LIST:\n"
5214 "case COMPLEMENTED_LIST:\n"
5215 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
5216 "list_count++)\n"
3abe9331 5217 "if (value_list.list_value[list_count].match(other_value, legacy)) "
970ed795
EL
5218 "return template_selection == VALUE_LIST;\n"
5219 "return template_selection == COMPLEMENTED_LIST;\n"
5220 "default:\n"
5221 "TTCN_error(\"Matching an uninitialized/unsupported template of "
5222 "type %s.\");\n"
5223 "}\n"
5224 "return FALSE;\n"
5225 "}\n\n", dispname);
5226
5227 /* is_bound */
5228 def = mputstr(def, "boolean is_bound() const;\n");
5229
5230 src = mputprintf(src, "boolean %s_template::is_bound() const\n"
5231 "{\n"
5232 "if (template_selection == UNINITIALIZED_TEMPLATE && !is_ifpresent) "
5233 "return FALSE;\n", name);
5234 src = mputstr(src, "if (template_selection != SPECIFIC_VALUE) return TRUE;\n");
5235 for (i = 0; i < sdef->nElements; i++) {
5236 if (sdef->elements[i].isOptional) {
5237 src = mputprintf(src,
5238 "if (single_value->field_%s.is_omit() ||"
5239 " single_value->field_%s.is_bound()) return TRUE;\n",
5240 sdef->elements[i].name, sdef->elements[i].name);
5241 } else {
5242 src = mputprintf(src,
5243 "if (single_value->field_%s.is_bound()) return TRUE;\n",
5244 sdef->elements[i].name);
5245 }
5246 }
5247 src = mputstr(src, "return FALSE;\n"
5248 "}\n\n");
5249
5250 /* is_value */
5251 def = mputstr(def, "boolean is_value() const;\n");
5252
5253 src = mputprintf(src, "boolean %s_template::is_value() const\n"
5254 "{\n"
5255 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) "
5256 "return FALSE;\n", name);
5257 for (i = 0; i < sdef->nElements; i++) {
5258 if (sdef->elements[i].isOptional) {
5259 src = mputprintf(src,
5260 "if (!single_value->field_%s.is_omit() &&"
5261 " !single_value->field_%s.is_value()) return FALSE;\n",
5262 sdef->elements[i].name, sdef->elements[i].name);
5263 } else {
5264 src = mputprintf(src,
5265 "if (!single_value->field_%s.is_value()) return FALSE;\n",
5266 sdef->elements[i].name);
5267 }
5268 }
5269 src = mputstr(src, "return TRUE;\n"
5270 "}\n\n");
5271
5272 /* clean_up function */
5273 def = mputstr(def, "void clean_up();\n");
5274 src = mputprintf(src,
5275 "void %s_template::clean_up()\n"
5276 "{\n"
5277 "switch (template_selection) {\n"
5278 "case SPECIFIC_VALUE:\n"
5279 "delete single_value;\n"
5280 "break;\n"
5281 "case VALUE_LIST:\n"
5282 "case COMPLEMENTED_LIST:\n"
5283 "delete [] value_list.list_value;\n"
5284 "default:\n"
5285 "break;\n"
5286 "}\n"
5287 "template_selection = UNINITIALIZED_TEMPLATE;\n"
5288 "}\n\n", name);
5289
5290 /* valueof operation */
5291 def = mputprintf(def, "%s valueof() const;\n", name);
5292
5293 src = mputprintf(src, "%s %s_template::valueof() const\n"
5294 "{\n"
5295 "if (template_selection != SPECIFIC_VALUE || is_ifpresent)\n"
5296 "TTCN_error(\"Performing valueof or send operation on a non-specific "
5297 "template of type %s.\");\n"
5298 "%s ret_val;\n", name, name, dispname, name);
5299 for (i = 0; i < sdef->nElements; i++) {
5300 if (sdef->elements[i].isOptional) {
5301 src = mputprintf(src,
5302 "if (single_value->field_%s.is_omit()) "
5303 "ret_val.%s() = OMIT_VALUE;\n"
5304 "else ",
5305 sdef->elements[i].name, sdef->elements[i].name);
5306 }
5307 src = mputprintf(src, "if (single_value->field_%s.is_bound()) {\n"
5308 "ret_val.%s() = single_value->field_%s.valueof();\n"
5309 "}\n",
5310 sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name);
5311 }
5312 src = mputstr(src, "return ret_val;\n"
5313 "}\n\n");
5314
5315 /* void set_type(template_sel, int) function */
5316 def = mputstr(def,
5317 "void set_type(template_sel template_type, "
5318 "unsigned int list_length);\n");
5319
5320 src = mputprintf(src,
5321 "void %s_template::set_type(template_sel template_type, "
5322 "unsigned int list_length)\n"
5323 "{\n"
5324 "if (template_type != VALUE_LIST "
5325 "&& template_type != COMPLEMENTED_LIST)\n"
5326 "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n"
5327 "clean_up();\n"
5328 "set_selection(template_type);\n"
5329 "value_list.n_values = list_length;\n"
5330 "value_list.list_value = new %s_template[list_length];\n"
5331 "}\n\n", name, dispname, name);
5332
5333 /* list_item(int) function */
5334
5335 def = mputprintf(def,
5336 "%s_template& list_item(unsigned int list_index) const;\n", name);
5337
5338 src = mputprintf(src,
5339 "%s_template& %s_template::list_item(unsigned int list_index) const\n"
5340 "{\n"
5341 "if (template_selection != VALUE_LIST "
5342 "&& template_selection != COMPLEMENTED_LIST)\n"
5343 "TTCN_error(\"Accessing a list element of a non-list template of "
5344 "type %s.\");\n"
5345 "if (list_index >= value_list.n_values)\n"
5346 "TTCN_error(\"Index overflow in a value list template of type "
5347 "%s.\");\n"
5348 "return value_list.list_value[list_index];\n"
5349 "}\n\n", name, name, dispname, dispname);
5350
5351 /* template field access functions (non-const & const) */
5352 for (i = 0; i < sdef->nElements; i++) {
5353 def = mputprintf(def, "%s_template& %s();\n",
5354 sdef->elements[i].type, sdef->elements[i].name);
5355 src = mputprintf(src, "%s_template& %s_template::%s()\n"
5356 "{\n"
5357 "set_specific();\n"
5358 "return single_value->field_%s;\n"
5359 "}\n\n",
5360 sdef->elements[i].type, name, sdef->elements[i].name,
5361 sdef->elements[i].name);
5362 def = mputprintf(def, "const %s_template& %s() const;\n",
5363 sdef->elements[i].type, sdef->elements[i].name);
5364 src = mputprintf(src, "const %s_template& %s_template::%s() const\n"
5365 "{\n"
5366 "if (template_selection != SPECIFIC_VALUE)\n"
5367 "TTCN_error(\"Accessing field %s of a non-specific "
5368 "template of type %s.\");\n"
5369 "return single_value->field_%s;\n"
5370 "}\n\n",
5371 sdef->elements[i].type, name, sdef->elements[i].name,
5372 sdef->elements[i].dispname, dispname, sdef->elements[i].name);
5373 }
5374
5375 /* sizeof operation */
5376 def = mputstr(def, "int size_of() const;\n");
5377 src = mputprintf(src,
5378 "int %s_template::size_of() const\n"
5379 "{\n"
5380 " if (is_ifpresent) TTCN_error(\"Performing sizeof() operation on a "
5381 "template of type %s which has an ifpresent attribute.\");\n"
5382 " switch (template_selection)\n"
5383 " {\n"
5384 " case SPECIFIC_VALUE:\n",
5385 name, dispname);
5386 mandatory_fields_count = 0;
5387 for (i = 0; i < sdef->nElements; i++)
5388 if (!sdef->elements[i].isOptional) mandatory_fields_count++;
5389 if(sdef->nElements == mandatory_fields_count){
5390 src = mputprintf(src," return %lu;\n",
5391 (unsigned long) mandatory_fields_count);
5392 }else{
5393 src = mputprintf(src,
5394 " {"
5395 " int ret_val = %lu;\n", (unsigned long) mandatory_fields_count);
5396 for (i = 0; i < sdef->nElements; i++)
5397 if (sdef->elements[i].isOptional)
5398 src = mputprintf(src,
5399 " if (single_value->field_%s.is_present()) ret_val++;\n",
5400 sdef->elements[i].name);
5401 src = mputstr(src,
5402 " return ret_val;\n"
5403 " }\n");
5404 }
5405 src = mputprintf(src,
5406
5407 " case VALUE_LIST:\n"
5408 " {\n"
5409 " if (value_list.n_values<1)\n"
5410 " TTCN_error(\"Internal error: Performing sizeof() operation on a "
5411 "template of type %s containing an empty list.\");\n"
5412 " int item_size = value_list.list_value[0].size_of();\n"
5413 " for (unsigned int l_idx = 1; l_idx < value_list.n_values; l_idx++)\n"
5414 " {\n"
5415 " if (value_list.list_value[l_idx].size_of()!=item_size)\n"
5416 " TTCN_error(\"Performing sizeof() operation on a template "
5417 "of type %s containing a value list with different sizes.\");\n"
5418 " }\n"
5419 " return item_size;\n"
5420 " }\n"
5421 " case OMIT_VALUE:\n"
5422 " TTCN_error(\"Performing sizeof() operation on a template of type %s "
5423 "containing omit value.\");\n"
5424 " case ANY_VALUE:\n"
5425 " case ANY_OR_OMIT:\n"
5426 " TTCN_error(\"Performing sizeof() operation on a template of type %s "
5427 "containing */? value.\");\n"
5428 " case COMPLEMENTED_LIST:\n"
5429 " TTCN_error(\"Performing sizeof() operation on a template of type %s "
5430 "containing complemented list.\");\n"
5431 " default:\n"
5432 " TTCN_error(\"Performing sizeof() operation on an "
5433 "uninitialized/unsupported template of type %s.\");\n"
5434 " }\n"
5435 " return 0;\n"
5436 "}\n\n",
5437 dispname,dispname,dispname,dispname,dispname,dispname);
5438
5439 /* log function */
5440 def = mputstr(def, "void log() const;\n");
5441 src = mputprintf(src,
5442 "void %s_template::log() const\n"
5443 "{\n"
5444 "switch (template_selection) {\n"
5445 "case SPECIFIC_VALUE:\n", name);
5446 for (i = 0; i < sdef->nElements; i++) {
5447 src = mputstr(src, "TTCN_Logger::log_event_str(\"");
5448 if (i == 0) src = mputc(src, '{');
5449 else src = mputc(src, ',');
5450 src = mputprintf(src, " %s := \");\n"
5451 "single_value->field_%s.log();\n",
5452 sdef->elements[i].dispname, sdef->elements[i].name);
5453 }
5454 src = mputstr(src,
5455 "TTCN_Logger::log_event_str(\" }\");\n"
5456 "break;\n"
5457 "case COMPLEMENTED_LIST:\n"
5458 "TTCN_Logger::log_event_str(\"complement \");\n"
5459 "case VALUE_LIST:\n"
5460 "TTCN_Logger::log_char('(');\n"
5461 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
5462 "list_count++) {\n"
5463 "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n"
5464 "value_list.list_value[list_count].log();\n"
5465 "}\n"
5466 "TTCN_Logger::log_char(')');\n"
5467 "break;\n"
5468 "default:\n"
5469 "log_generic();\n"
5470 "}\n"
5471 "log_ifpresent();\n"
5472 "}\n\n");
5473
5474 /* log_match function */
3abe9331 5475 def = mputprintf(def, "void log_match(const %s& match_value, "
5476 "boolean legacy = FALSE) const;\n", name);
970ed795 5477 src = mputprintf(src,
3abe9331 5478 "void %s_template::log_match(const %s& match_value, boolean legacy) const\n"
5479 "{\n"
970ed795
EL
5480 "if(TTCN_Logger::VERBOSITY_COMPACT"
5481 " == TTCN_Logger::get_matching_verbosity()){\n"
3abe9331 5482 "if(match(match_value, legacy)){\n"
970ed795
EL
5483 "TTCN_Logger::print_logmatch_buffer();\n"
5484 "TTCN_Logger::log_event_str(\" matched\");\n"
5485 "} else{\n"
5486 "if (template_selection == SPECIFIC_VALUE) {\n"
5487 "size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();\n"
5488 , name, name);
5489 for (i = 0; i < sdef->nElements; i++) {
5490 if (sdef->elements[i].isOptional){
5491 src = mputprintf(src,
5492 "if (match_value.%s().ispresent()){\n"
3abe9331 5493 "if(!single_value->field_%s.match(match_value.%s(), legacy)){\n"
970ed795 5494 "TTCN_Logger::log_logmatch_info(\".%s\");\n"
3abe9331 5495 "single_value->field_%s.log_match(match_value.%s(), legacy);\n"
970ed795
EL
5496 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
5497 "}\n"
5498 "} else {\n"
3abe9331 5499 "if (!single_value->field_%s.match_omit(legacy)){\n "
970ed795
EL
5500 "TTCN_Logger::log_logmatch_info(\".%s := omit with \");\n"
5501 "TTCN_Logger::print_logmatch_buffer();\n"
5502 "single_value->field_%s.log();\n"
5503 "TTCN_Logger::log_event_str(\" unmatched\");\n"
5504 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
5505 "}\n"
5506 "}\n"
5507 , sdef->elements[i].name, sdef->elements[i].name,
5508 sdef->elements[i].name, sdef->elements[i].dispname,
5509 sdef->elements[i].name, sdef->elements[i].name,
5510 sdef->elements[i].name, sdef->elements[i].dispname,
5511 sdef->elements[i].name);
5512 }else{
5513 src = mputprintf(src,
3abe9331 5514 "if(!single_value->field_%s.match(match_value.%s(), legacy)){\n"
970ed795 5515 "TTCN_Logger::log_logmatch_info(\".%s\");\n"
3abe9331 5516 "single_value->field_%s.log_match(match_value.%s(), legacy);\n"
970ed795
EL
5517 "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n"
5518 "}\n",sdef->elements[i].name, sdef->elements[i].name,
5519 sdef->elements[i].dispname, sdef->elements[i].name,
5520 sdef->elements[i].name);
5521 }
5522 }
5523
5524 src = mputstr(src,"}else {\n"
5525 "TTCN_Logger::print_logmatch_buffer();\n"
5526 "match_value.log();\n"
5527 "TTCN_Logger::log_event_str(\" with \");\n"
5528 "log();\n"
5529 "TTCN_Logger::log_event_str(\" unmatched\");\n"
5530 "}\n"
5531 "}\n"
5532 "return;\n"
5533 "}\n"
5534 "if (template_selection == SPECIFIC_VALUE) {\n");
5535 for (i = 0; i < sdef->nElements; i++) {
5536 src = mputstr(src, "TTCN_Logger::log_event_str(\"");
5537 if (i == 0) src = mputc(src, '{');
5538 else src = mputc(src, ',');
5539 src = mputprintf(src, " %s := \");\n", sdef->elements[i].dispname);
5540 if (sdef->elements[i].isOptional) src = mputprintf(src,
5541 "if (match_value.%s().ispresent()) "
3abe9331 5542 "single_value->field_%s.log_match(match_value.%s(), legacy);\n"
970ed795
EL
5543 "else {\n"
5544 "TTCN_Logger::log_event_str(\"omit with \");\n"
5545 "single_value->field_%s.log();\n"
3abe9331 5546 "if (single_value->field_%s.match_omit(legacy)) "
970ed795
EL
5547 "TTCN_Logger::log_event_str(\" matched\");\n"
5548 "else TTCN_Logger::log_event_str(\" unmatched\");\n"
5549 "}\n",
5550 sdef->elements[i].name, sdef->elements[i].name,
5551 sdef->elements[i].name, sdef->elements[i].name,
5552 sdef->elements[i].name);
5553 else src = mputprintf(src,
3abe9331 5554 "single_value->field_%s.log_match(match_value.%s(), legacy);\n",
970ed795
EL
5555 sdef->elements[i].name, sdef->elements[i].name);
5556 }
5557 src = mputstr(src,
5558 "TTCN_Logger::log_event_str(\" }\");\n"
5559 "} else {\n"
5560 "match_value.log();\n"
5561 "TTCN_Logger::log_event_str(\" with \");\n"
5562 "log();\n"
3abe9331 5563 "if (match(match_value, legacy)) TTCN_Logger::log_event_str(\" matched\");\n"
970ed795
EL
5564 "else TTCN_Logger::log_event_str(\" unmatched\");\n"
5565 "}\n"
5566 "}\n\n");
5567
5568 /*encode_text function*/
5569 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
5570 src = mputprintf(src,
5571 "void %s_template::encode_text(Text_Buf& text_buf) const\n"
5572 "{\n"
5573 "encode_text_base(text_buf);\n"
5574 "switch (template_selection) {\n"
5575 "case SPECIFIC_VALUE:\n", name);
5576 for (i = 0; i < sdef->nElements; i++) {
5577 src = mputprintf(src, "single_value->field_%s.encode_text(text_buf);\n",
5578 sdef->elements[i].name);
5579 }
5580 src = mputprintf(src,
5581 "case OMIT_VALUE:\n"
5582 "case ANY_VALUE:\n"
5583 "case ANY_OR_OMIT:\n"
5584 "break;\n"
5585 "case VALUE_LIST:\n"
5586 "case COMPLEMENTED_LIST:\n"
5587 "text_buf.push_int(value_list.n_values);\n"
5588 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
5589 "list_count++)\n"
5590 "value_list.list_value[list_count].encode_text(text_buf);\n"
5591 "break;\n"
5592 "default:\n"
5593 "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported "
5594 "template of type %s.\");\n"
5595 "}\n"
5596 "}\n\n", dispname);
5597
5598 /*decode_text function*/
5599 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
5600 src = mputprintf(src,
5601 "void %s_template::decode_text(Text_Buf& text_buf)\n"
5602 "{\n"
5603 "clean_up();\n"
5604 "decode_text_base(text_buf);\n"
5605 "switch (template_selection) {\n"
5606 "case SPECIFIC_VALUE:\n"
5607 "single_value = new single_value_struct;\n", name);
5608 for (i = 0; i < sdef->nElements; i++) {
5609 src = mputprintf(src, "single_value->field_%s.decode_text(text_buf);\n",
5610 sdef->elements[i].name);
5611 }
5612 src = mputprintf(src,
5613 "case OMIT_VALUE:\n"
5614 "case ANY_VALUE:\n"
5615 "case ANY_OR_OMIT:\n"
5616 "break;\n"
5617 "case VALUE_LIST:\n"
5618 "case COMPLEMENTED_LIST:\n"
5619 "value_list.n_values = text_buf.pull_int().get_val();\n"
5620 "value_list.list_value = new %s_template[value_list.n_values];\n"
5621 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
5622 "list_count++)\n"
5623 "value_list.list_value[list_count].decode_text(text_buf);\n"
5624 "break;\n"
5625 "default:\n"
5626 "TTCN_error(\"Text decoder: An unknown/unsupported selection was "
5627 "received in a template of type %s.\");\n"
5628 "}\n"
5629 "}\n\n", name, dispname);
5630
5631 /* set_param() */
5632 def = mputstr(def, "void set_param(Module_Param& param);\n");
5633 src = mputprintf(src,
5634 "void %s_template::set_param(Module_Param& param)\n"
5635 "{\n"
5636 " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n"
5637 " param.get_id()->next_name()) {\n"
5638 // Haven't reached the end of the module parameter name
5639 // => the name refers to one of the fields, not to the whole record
5640 " char* param_field = param.get_id()->get_current_name();\n"
5641 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
5642 " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n"
5643 " \" name for %s template type `%s'\");\n"
5644 " }\n"
5645 " ", name, kind_str, dispname);
5646 for (i = 0; i < sdef->nElements; i++) {
5647 src = mputprintf(src,
5648 "if (strcmp(\"%s\", param_field) == 0) {\n"
5649 " %s().set_param(param);\n"
5650 " return;\n"
5651 " } else ",
5652 sdef->elements[i].dispname, sdef->elements[i].name);
5653 }
5654 src = mputprintf(src,
5655 "param.error(\"Field `%%s' not found in %s template type `%s'\", param_field);\n"
5656 " }\n"
5657 " param.basic_check(Module_Param::BC_TEMPLATE, \"%s template\");\n"
3f84031e 5658 " Module_Param_Ptr m_p = &param;\n"
3abe9331 5659 " if (param.get_type() == Module_Param::MP_Reference) {\n"
3f84031e 5660 " m_p = param.get_referenced_param();\n"
3abe9331 5661 " }\n"
3f84031e 5662 " switch (m_p->get_type()) {\n"
970ed795
EL
5663 " case Module_Param::MP_Omit:\n"
5664 " *this = OMIT_VALUE;\n"
5665 " break;\n"
5666 " case Module_Param::MP_Any:\n"
5667 " *this = ANY_VALUE;\n"
5668 " break;\n"
5669 " case Module_Param::MP_AnyOrNone:\n"
5670 " *this = ANY_OR_OMIT;\n"
5671 " break;\n"
5672 " case Module_Param::MP_List_Template:\n"
3abe9331 5673 " case Module_Param::MP_ComplementList_Template: {\n"
3f84031e 5674 " %s_template new_temp;\n"
5675 " new_temp.set_type(m_p->get_type()==Module_Param::MP_List_Template ? "
5676 "VALUE_LIST : COMPLEMENTED_LIST, m_p->get_size());\n"
5677 " for (size_t p_i=0; p_i<m_p->get_size(); p_i++) {\n"
5678 " new_temp.list_item(p_i).set_param(*m_p->get_elem(p_i));\n"
970ed795 5679 " }\n"
3f84031e 5680 " *this = new_temp;\n"
3abe9331 5681 " break; }\n"
970ed795 5682 " case Module_Param::MP_Value_List:\n"
3f84031e 5683 " if (%lu<m_p->get_size()) {\n"
5684 " param.error(\"%s template of type %s has %lu fields but list value has %%d fields\", (int)m_p->get_size());\n"
970ed795 5685 " }\n",
3abe9331 5686 kind_str, dispname, kind_str, name, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements);
970ed795
EL
5687 for (i = 0; i < sdef->nElements; ++i) {
5688 src = mputprintf(src,
3f84031e 5689 " if (m_p->get_size()>%lu && m_p->get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*m_p->get_elem(%lu));\n",
970ed795
EL
5690 (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i);
5691 }
5692 src = mputstr(src,
5693 " break;\n"
5694 " case Module_Param::MP_Assignment_List: {\n"
3f84031e 5695 " Vector<bool> value_used(m_p->get_size());\n"
5696 " value_used.resize(m_p->get_size(), false);\n");
970ed795
EL
5697 for (i = 0; i < sdef->nElements; ++i) {
5698 src = mputprintf(src,
3f84031e 5699 " for (size_t val_idx=0; val_idx<m_p->get_size(); val_idx++) {\n"
5700 " Module_Param* const curr_param = m_p->get_elem(val_idx);\n"
970ed795
EL
5701 " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n"
5702 " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n"
5703 " %s().set_param(*curr_param);\n"
5704 " }\n"
5705 " value_used[val_idx]=true;\n"
5706 " }\n"
5707 " }\n"
5708 , sdef->elements[i].dispname, sdef->elements[i].name);
5709 }
5710 src = mputprintf(src,
3f84031e 5711 " for (size_t val_idx=0; val_idx<m_p->get_size(); val_idx++) if (!value_used[val_idx]) {\n"
5712 " m_p->get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", m_p->get_elem(val_idx)->get_id()->get_name());\n"
970ed795
EL
5713 " break;\n"
5714 " }\n"
5715 " } break;\n"
5716 " default:\n"
5717 " param.type_error(\"%s template\", \"%s\");\n"
5718 " }\n"
3f84031e 5719 " is_ifpresent = param.get_ifpresent() || m_p->get_ifpresent();\n"
970ed795 5720 "}\n\n", dispname, kind_str, dispname);
3abe9331 5721
5722 /* get_param() */
5723 def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
5724 src = mputprintf(src,
5725 "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n"
5726 "{\n"
5727 " if (param_name.next_name()) {\n"
5728 // Haven't reached the end of the module parameter name
5729 // => the name refers to one of the fields, not to the whole record
5730 " char* param_field = param_name.get_current_name();\n"
5731 " if (param_field[0] >= '0' && param_field[0] <= '9') {\n"
5732 " TTCN_error(\"Unexpected array index in module parameter reference, \"\n"
5733 " \"expected a valid field name for %s template type `%s'\");\n"
5734 " }\n"
5735 " ", name, kind_str, dispname);
5736 for (i = 0; i < sdef->nElements; i++) {
5737 src = mputprintf(src,
5738 "if (strcmp(\"%s\", param_field) == 0) {\n"
5739 " return %s().get_param(param_name);\n"
5740 " } else ",
5741 sdef->elements[i].dispname, sdef->elements[i].name);
5742 }
5743 src = mputprintf(src,
5744 "TTCN_error(\"Field `%%s' not found in %s type `%s'\", param_field);\n"
5745 " }\n"
3f84031e 5746 " Module_Param* m_p = NULL;\n"
3abe9331 5747 " switch (template_selection) {\n"
5748 " case UNINITIALIZED_TEMPLATE:\n"
3f84031e 5749 " m_p = new Module_Param_Unbound();\n"
3abe9331 5750 " break;\n"
5751 " case OMIT_VALUE:\n"
3f84031e 5752 " m_p = new Module_Param_Omit();\n"
3abe9331 5753 " break;\n"
5754 " case ANY_VALUE:\n"
3f84031e 5755 " m_p = new Module_Param_Any();\n"
3abe9331 5756 " break;\n"
5757 " case ANY_OR_OMIT:\n"
3f84031e 5758 " m_p = new Module_Param_AnyOrNone();\n"
3abe9331 5759 " break;\n"
5760 " case SPECIFIC_VALUE: {\n"
3f84031e 5761 " m_p = new Module_Param_Assignment_List();\n"
3abe9331 5762 , kind_str, dispname);
5763 for (i = 0; i < sdef->nElements; i++) {
5764 src = mputprintf(src,
5765 " Module_Param* mp_field_%s = single_value->field_%s.get_param(param_name);\n"
5766 " mp_field_%s->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n"
3f84031e 5767 " m_p->add_elem(mp_field_%s);\n"
3abe9331 5768 , sdef->elements[i].name, sdef->elements[i].name
5769 , sdef->elements[i].name, sdef->elements[i].dispname
5770 , sdef->elements[i].name);
5771 }
5772 src = mputstr(src,
5773 " break; }\n"
5774 " case VALUE_LIST:\n"
5775 " case COMPLEMENTED_LIST: {\n"
5776 " if (template_selection == VALUE_LIST) {\n"
3f84031e 5777 " m_p = new Module_Param_List_Template();\n"
3abe9331 5778 " }\n"
5779 " else {\n"
3f84031e 5780 " m_p = new Module_Param_ComplementList_Template();\n"
3abe9331 5781 " }\n"
3f84031e 5782 " for (size_t i_i = 0; i_i < value_list.n_values; ++i_i) {\n"
5783 " m_p->add_elem(value_list.list_value[i_i].get_param(param_name));\n"
3abe9331 5784 " }\n"
5785 " break; }\n"
5786 " default:\n"
5787 " break;\n"
5788 " }\n"
5789 " if (is_ifpresent) {\n"
3f84031e 5790 " m_p->set_ifpresent();\n"
3abe9331 5791 " }\n"
3f84031e 5792 " return m_p;\n"
3abe9331 5793 "}\n\n");
970ed795
EL
5794
5795 /* check template restriction */
5796 def = mputstr(def, "void check_restriction(template_res t_res, "
3abe9331 5797 "const char* t_name=NULL, boolean legacy = FALSE) const;\n");
970ed795
EL
5798 src = mputprintf(src,
5799 "void %s_template::check_restriction("
3abe9331 5800 "template_res t_res, const char* t_name, boolean legacy) const\n"
970ed795
EL
5801 "{\n"
5802 "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
5803 "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
5804 "case TR_OMIT:\n"
5805 "if (template_selection==OMIT_VALUE) return;\n"
5806 "case TR_VALUE:\n"
5807 "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n",
5808 name);
5809 for (i = 0; i < sdef->nElements; i++) {
5810 src = mputprintf(src, "single_value->field_%s.check_restriction("
5811 "t_res, t_name ? t_name : \"%s\");\n",
5812 sdef->elements[i].name, dispname);
5813 }
5814 src = mputprintf(src,
5815 "return;\n"
5816 "case TR_PRESENT:\n"
3abe9331 5817 "if (!match_omit(legacy)) return;\n"
970ed795
EL
5818 "break;\n"
5819 "default:\n"
5820 "return;\n"
5821 "}\n"
5822 "TTCN_error(\"Restriction `%%s' on template of type %%s "
5823 "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n"
5824 "}\n\n", dispname);
5825
5826 defCommonRecordTemplate(name, &def, &src);
5827
5828 def = mputstr(def, "};\n\n");
5829
5830 output->header.class_defs = mputstr(output->header.class_defs, def);
5831 Free(def);
5832
5833 output->source.methods = mputstr(output->source.methods, src);
5834 Free(src);
5835}
5836
5837static void defEmptyRecordClass(const struct_def *sdef,
5838 output_struct *output)
5839{
5840 const char *name = sdef->name, *dispname = sdef->dispname;
5841 char *def = NULL, *src = NULL;
5842 boolean ber_needed = sdef->isASN1 && enable_ber();
5843 boolean raw_needed = sdef->hasRaw && enable_raw();
5844 boolean text_needed = sdef->hasText && enable_text();
5845 boolean xer_needed = sdef->hasXer && enable_xer();
5846 boolean json_needed = sdef->hasJson && enable_json();
5847
5848 def = mputprintf(def,
5849#ifndef NDEBUG
5850 "// written by %s in " __FILE__ " at line %d\n"
5851#endif
5852 "class %s : public Base_Type {\n"
5853 "boolean bound_flag;\n"
5854 "public:\n"
5855#ifndef NDEBUG
5856 , __FUNCTION__, __LINE__
5857#endif
5858 , name);
5859
5860 /* default ctor */
5861 def = mputprintf(def, "%s();\n", name);
5862 src = mprintf("%s::%s()\n"
5863 "{\n"
5864 "bound_flag = FALSE;\n"
5865 "}\n\n", name, name);
5866
5867 /* ctor from NULL_VALUE (i.e. {}) */
5868 def = mputprintf(def, "%s(null_type other_value);\n", name);
5869 src = mputprintf(src, "%s::%s(null_type)\n"
5870 "{\n"
5871 "bound_flag = TRUE;\n"
5872 "}\n\n", name, name);
5873
5874 /* copy ctor */
5875 def = mputprintf(def, "%s(const %s& other_value);\n", name, name);
5876 src = mputprintf(src, "%s::%s(const %s& other_value)\n"
5877 "{\n"
5878 "other_value.must_bound(\"Copying an unbound value of "
5879 "type %s.\");\n"
5880 "bound_flag = TRUE;\n"
5881 "}\n\n", name, name, name, dispname);
5882
5883 /* assignment op: from NULL_VALUE */
5884 def = mputprintf(def, "%s& operator=(null_type other_value);\n", name);
5885 src = mputprintf(src, "%s& %s::operator=(null_type)\n"
5886 "{\n"
5887 "bound_flag = TRUE;\n"
5888 "return *this;\n"
5889 "}\n\n", name, name);
5890
5891 /* assignment op: from itself */
5892 def = mputprintf(def, "%s& operator=(const %s& other_value);\n", name,
5893 name);
5894 src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n"
5895 "{\n"
5896 "other_value.must_bound(\"Assignment of an unbound value of type "
5897 "%s.\");\n"
5898 "bound_flag = TRUE;\n"
5899 "return *this;\n"
5900 "}\n\n", name, name, name, dispname);
5901
5902 /* comparison op: with NULL_VALUE */
5903 def = mputstr(def, "boolean operator==(null_type other_value) const;\n");
5904 src = mputprintf(src,
5905 "boolean %s::operator==(null_type) const\n"
5906 "{\n"
5907 "must_bound(\"Comparison of an unbound value of type %s.\");\n"
5908 "return TRUE;\n"
5909 "}\n\n", name, dispname);
5910
5911 /* comparison op: with itself */
5912 def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n",
5913 name);
5914 src = mputprintf(src,
5915 "boolean %s::operator==(const %s& other_value) const\n"
5916 "{\n"
5917 "must_bound(\"Comparison of an unbound value of type %s.\");\n"
5918 "other_value.must_bound(\"Comparison of an unbound value of type "
5919 "%s.\");\n"
5920 "return TRUE;\n"
5921 "}\n\n", name, name, dispname, dispname);
5922
5923 /* non-equal operators */
5924 def = mputprintf(def,
5925 "inline boolean operator!=(null_type other_value) const "
5926 "{ return !(*this == other_value); }\n"
5927 "inline boolean operator!=(const %s& other_value) const "
5928 "{ return !(*this == other_value); }\n", name);
5929
5930
5931 /* is_bound function */
5932 def = mputstr(def, "inline boolean is_bound() const "
5933 "{ return bound_flag; }\n");
5934
5935 /* is_present function */
5936 def = mputstr(def,
5937 "inline boolean is_present() const { return is_bound(); }\n");
5938
5939 /* is_value function */
5940 def = mputstr(def, "inline boolean is_value() const "
5941 "{ return bound_flag; }\n");
5942
5943 /* clean_up function */
5944 def = mputstr(def, "inline void clean_up() "
5945 "{ bound_flag = FALSE; }\n");
5946
5947 /* must_bound function */
5948 def = mputstr(def, "inline void must_bound(const char *err_msg) const "
5949 "{ if (!bound_flag) TTCN_error(\"%s\", err_msg); }\n");
5950
5951 /* log function */
5952 def = mputstr(def, "void log() const;\n");
5953 src = mputprintf(src, "void %s::log() const\n"
5954 "{\n"
5955 "if (bound_flag) TTCN_Logger::log_event_str(\"{ }\");\n"
5956 "else TTCN_Logger::log_event_unbound();\n"
5957 "}\n\n", name);
5958
5959 /* set_param function */
3abe9331 5960 def = mputstr(def, "void set_param(Module_Param& param);\n");
5961 src = mputprintf(src, "void %s::set_param(Module_Param& param)\n"
970ed795
EL
5962 "{\n"
5963 " param.basic_check(Module_Param::BC_VALUE, \"empty record/set value (i.e. { })\");\n"
3abe9331 5964 " Module_Param_Ptr mp = &param;\n"
5965 " if (param.get_type() == Module_Param::MP_Reference) {\n"
5966 " mp = param.get_referenced_param();\n"
5967 " }\n"
5968 " if (mp->get_type()!=Module_Param::MP_Value_List || mp->get_size()>0) {\n"
970ed795
EL
5969 " param.type_error(\"empty record/set value (i.e. { })\", \"%s\");\n"
5970 " }\n"
5971 " bound_flag = TRUE;\n"
5972 "}\n\n", name, dispname);
3abe9331 5973
5974 /* get param function */
5975 def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
5976 src = mputprintf(src,
5977 "Module_Param* %s::get_param(Module_Param_Name& /* param_name */) const\n"
5978 "{\n"
5979 " if (!is_bound()) {\n"
5980 " return new Module_Param_Unbound();\n"
5981 " }\n"
5982 " return new Module_Param_Value_List();\n"
5983 "}\n\n", name);
970ed795
EL
5984
5985 /* encode_text function */
5986 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
5987 src = mputprintf(src, "void %s::encode_text(Text_Buf& /*text_buf*/) const\n"
5988 "{\n"
5989 "must_bound(\"Text encoder: Encoding an unbound value of type %s.\");\n"
5990 "}\n\n", name, dispname);
5991
5992 /* decode_text function */
5993 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
5994 src = mputprintf(src, "void %s::decode_text(Text_Buf& /*text_buf*/)\n"
5995 "{\n"
5996 "bound_flag = TRUE;\n"
5997 "}\n\n", name);
5998
5999 if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
6000 def_encdec(name, &def, &src, ber_needed, raw_needed,
6001 text_needed, xer_needed, json_needed, FALSE);
6002
6003 /* BER functions */
6004 if(ber_needed) {
6005 /* BER_encode_TLV() */
6006 src=mputprintf
6007 (src,
6008 "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,"
6009 " unsigned p_coding) const\n"
6010 "{\n"
6011 " BER_chk_descr(p_td);\n"
6012 " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n"
6013 " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
6014 " return new_tlv;\n"
6015 "}\n"
6016 "\n"
6017 , name
6018 );
6019
6020 /* BER_decode_TLV() */
6021 src=mputprintf
6022 (src,
6023 "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,"
6024 " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n"
6025 "{\n"
6026 " BER_chk_descr(p_td);\n"
6027 " ASN_BER_TLV_t stripped_tlv;\n"
6028 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
6029 " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n"
6030 " stripped_tlv.chk_constructed_flag(TRUE);\n"
6031 " bound_flag=TRUE;\n"
6032 " return TRUE;\n"
6033 "}\n"
6034 "\n"
6035 , name, sdef->dispname
6036 );
6037 } /* if ber_needed */
6038 if(text_needed){
6039 src = mputprintf(src,
6040 "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td,"
6041 "TTCN_Buffer& p_buf) const{\n"
6042 " int encoded_length=0;\n"
6043 " if(p_td.text->begin_encode){\n"
6044 " p_buf.put_cs(*p_td.text->begin_encode);\n"
6045 " encoded_length+=p_td.text->begin_encode->lengthof();\n"
6046 " }\n"
6047 " if(!bound_flag) {\n"
6048 " TTCN_EncDec_ErrorContext::error\n"
6049 " (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n"
6050 " }\n"
6051 " if(p_td.text->end_encode){\n"
6052 " p_buf.put_cs(*p_td.text->end_encode);\n"
6053 " encoded_length+=p_td.text->end_encode->lengthof();\n"
6054 " }\n"
6055 " return encoded_length;\n"
6056 "}\n"
6057 ,name
6058 );
6059 src = mputprintf(src,
6060 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
6061 " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n"
509718e0 6062 " bound_flag = TRUE;\n"
970ed795
EL
6063 " int decoded_length=0;\n"
6064 " if(p_td.text->begin_decode){\n"
6065 " int tl;\n"
6066 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
6067 " if(no_err)return -1;\n"
6068 " TTCN_EncDec_ErrorContext::error\n"
6069 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
6070 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
6071 ", p_td.name);\n"
6072 " return 0;\n"
6073 " }\n"
6074 " decoded_length+=tl;\n"
6075 " p_buf.increase_pos(tl);\n"
6076 " }\n"
6077 " if(p_td.text->end_decode){\n"
6078 " int tl;\n"
6079 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
6080 " if(no_err)return -1;\n"
6081 " TTCN_EncDec_ErrorContext::error\n"
6082 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
6083 " not found for '%%s': \",(const char*)*(p_td.text->end_decode)"
6084 ", p_td.name);\n"
6085 " return 0;\n"
6086 " }\n"
6087 " decoded_length+=tl;\n"
6088 " p_buf.increase_pos(tl);\n"
6089 " }\n"
970ed795
EL
6090 " return decoded_length;\n"
6091 "}\n"
6092 ,name
6093 );
6094
6095 }
6096 /* RAW functions */
6097 if (raw_needed) {
6098 src = mputprintf(src,
6099 "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td, "
6100 "RAW_enc_tree& /*myleaf*/) const\n"
6101 "{\n"
6102 "if (!bound_flag) TTCN_EncDec_ErrorContext::error"
6103 "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value of "
6104 "type %%s.\", p_td.name);\n"
6105 "return 0;\n"
6106 "}\n\n", name);
6107
6108 src = mputprintf(src,
6109 "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, "
6110 "TTCN_Buffer& p_buf, int, raw_order_t, boolean, int, boolean)\n"
6111 "{\n"
6112 "bound_flag = TRUE;\n"
6113 "return p_buf.increase_pos_padd(p_td.raw->prepadding) + "
6114 "p_buf.increase_pos_padd(p_td.raw->padding);\n"
6115 "}\n\n", name);
6116 }
6117
6118 if (xer_needed) { /* XERSTUFF codegen for empty record/SEQUENCE */
6119 src=mputprintf(src,
6120 "boolean %s::can_start(const char *p_name, const char *p_uri, "
6121 "const XERdescriptor_t& p_td, unsigned int p_flavor) {\n"
6122 " boolean e_xer = is_exer(p_flavor);\n"
6123 " if (e_xer && (p_td.xer_bits & UNTAGGED)) return false;\n"
6124 " else return check_name(p_name, p_td, e_xer) && (!e_xer || check_namespace(p_uri, p_td));\n"
6125 "}\n\n"
6126 , name
6127
6128 );
6129 src = mputprintf(src,
af710487 6130 "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, "
6131 "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const{\n"
970ed795
EL
6132 " int encoded_length=(int)p_buf.get_len();\n"
6133 " int is_indented = !is_canonical(p_flavor);\n"
6134 " int e_xer = is_exer(p_flavor);\n"
6135 " if (is_indented) do_indent(p_buf, p_indent);\n"
6136 " p_buf.put_c('<');\n"
6137 " if (e_xer) write_ns_prefix(p_td, p_buf);\n"
6138 " p_buf.put_s((size_t)p_td.namelens[e_xer]-2, (cbyte*)p_td.names[e_xer]);\n"
6139 " p_buf.put_s(2 + is_indented, (cbyte*)\"/>\\n\");\n"
6140 " return (int)p_buf.get_len() - encoded_length;\n"
6141 "}\n\n"
6142 , name);
6143 src = mputprintf(src,
6144#ifndef NDEBUG
6145 "// written by %s in " __FILE__ " at %d\n"
6146#endif
6147 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, "
af710487 6148 "unsigned int p_flavor, embed_values_dec_struct_t*)\n"
970ed795
EL
6149 "{\n"
6150 " int e_xer = is_exer(p_flavor);\n"
6151 " bound_flag = true;\n"
6152 " int rd_ok, depth=-1;\n"
6153 " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n"
6154 " int type = p_reader.NodeType();\n"
6155 " if (type==XML_READER_TYPE_ELEMENT) {\n"
6156 " verify_name(p_reader, p_td, e_xer);\n"
6157 " depth=p_reader.Depth();\n"
6158 " if (p_reader.IsEmptyElement()) {\n"
6159 " rd_ok = p_reader.Read(); break;\n"
6160 " }\n"
6161 " else if ((p_flavor & XER_MASK) == XER_CANONICAL) {\n"
6162 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, "
6163 "\"Expected an empty element tag\");\n"
6164 " }\n"
6165 " }\n"
6166 " else if (type == XML_READER_TYPE_END_ELEMENT && depth != -1) {\n"
6167 " verify_end(p_reader, p_td, depth, e_xer);\n"
6168 " rd_ok = p_reader.Read(); break;\n"
6169 " }\n"
6170 " }\n"
6171 " return 1;\n"
6172 "}\n\n"
6173#ifndef NDEBUG
6174 , __FUNCTION__, __LINE__
6175#endif
6176 , name);
6177 }
6178 if (json_needed) {
6179 // JSON encode, RT1
6180 src = mputprintf(src,
6181 "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
6182 "{\n"
6183 " if (!is_bound()) {\n"
6184 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
6185 " \"Encoding an unbound value of type %s.\");\n"
6186 " return -1;\n"
6187 " }\n\n"
6188 " return p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL) + \n"
6189 " p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n"
6190 "}\n\n"
6191 , name, dispname);
6192
6193 // JSON decode, RT1
6194 src = mputprintf(src,
6195 "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n"
6196 "{\n"
6197 " json_token_t token = JSON_TOKEN_NONE;\n"
6198 " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n"
6199 " if (JSON_TOKEN_ERROR == token) {\n"
6200 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
6201 " return JSON_ERROR_FATAL;\n"
6202 " }\n"
6203 " else if (JSON_TOKEN_OBJECT_START != token) {\n"
6204 " return JSON_ERROR_INVALID_TOKEN;\n"
6205 " }\n\n"
6206 " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n"
6207 " if (JSON_TOKEN_OBJECT_END != token) {\n"
6208 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n"
6209 " return JSON_ERROR_FATAL;\n"
6210 " }\n\n"
6211 " bound_flag = true;\n\n"
6212 " return dec_len;\n"
6213 "}\n\n"
6214 , name);
6215 }
6216
6217 /* closing class definition */
6218 def = mputstr(def, "};\n\n");
6219
6220 output->header.class_defs = mputstr(output->header.class_defs, def);
6221 Free(def);
6222
6223 output->source.methods = mputstr(output->source.methods, src);
6224 Free(src);
6225
6226 output->header.function_prototypes =
6227 mputprintf(output->header.function_prototypes,
6228 "extern boolean operator==(null_type null_value, const %s& "
6229 "other_value);\n", name);
6230 output->source.function_bodies =
6231 mputprintf(output->source.function_bodies,
6232 "boolean operator==(null_type, const %s& other_value)\n"
6233 "{\n"
6234 "other_value.must_bound(\"Comparison of an unbound value of type "
6235 "%s.\");\n"
6236 "return TRUE;\n"
6237 "}\n\n", name, dispname);
6238
6239 output->header.function_prototypes =
6240 mputprintf(output->header.function_prototypes,
6241 "inline boolean operator!=(null_type null_value, const %s& "
6242 "other_value) "
6243 "{ return !(null_value == other_value); }\n", name);
6244}
6245
6246static void defEmptyRecordTemplate(const char *name, const char *dispname,
6247 output_struct *output)
6248{
6249 char *def = NULL, *src = NULL;
6250
6251 /* class definition */
6252 def = mprintf("class %s_template : public Base_Template {\n"
6253 "struct {\n"
6254 "unsigned int n_values;\n"
6255 "%s_template *list_value;\n"
6256 "} value_list;\n", name, name);
6257
6258 /* copy_template function */
6259 def = mputprintf(def, "void copy_template(const %s_template& "
6260 "other_value);\n\n", name);
6261 src = mputprintf(src,
6262 "void %s_template::copy_template(const %s_template& other_value)\n"
6263 "{\n"
6264 "set_selection(other_value);\n"
6265 "switch (template_selection) {\n"
6266 "case OMIT_VALUE:\n"
6267 "case ANY_VALUE:\n"
6268 "case ANY_OR_OMIT:\n"
6269 "case SPECIFIC_VALUE:\n"
6270 "break;\n"
6271 "case VALUE_LIST:\n"
6272 "case COMPLEMENTED_LIST:\n"
6273 "value_list.n_values = other_value.value_list.n_values;\n"
6274 "value_list.list_value = new %s_template[value_list.n_values];\n"
6275 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
6276 "list_count++)\n"
6277 "value_list.list_value[list_count].copy_template("
6278 "other_value.value_list.list_value[list_count]);\n"
6279 "break;\n"
6280 "default:\n"
6281 "TTCN_error(\"Copying an uninitialized/unsupported template of type "
6282 "%s.\");\n"
6283 "break;\n"
6284 "}\n"
6285 "}\n\n", name, name, name, dispname);
6286
6287 /* default ctor */
6288 def = mputprintf(def, "public:\n"
6289 "%s_template();\n", name);
6290 src = mputprintf(src, "%s_template::%s_template()\n"
6291 "{\n"
6292 "}\n\n", name, name);
6293
6294 /* ctor for generic wildcards */
6295 def = mputprintf(def, "%s_template(template_sel other_value);\n", name);
6296 src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n"
6297 " : Base_Template(other_value)\n"
6298 "{\n"
6299 "check_single_selection(other_value);\n"
6300 "}\n\n", name, name);
6301
6302 /* ctor for value {} */
6303 def = mputprintf(def, "%s_template(null_type other_value);\n", name);
6304 src = mputprintf(src, "%s_template::%s_template(null_type)\n"
6305 " : Base_Template(SPECIFIC_VALUE)\n"
6306 "{\n"
6307 "}\n\n", name, name);
6308
6309 /* ctor for specific value */
6310 def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name);
6311 src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n"
6312 " : Base_Template(SPECIFIC_VALUE)\n"
6313 "{\n"
6314 "other_value.must_bound(\"Creating a template from an unbound value of "
6315 "type %s.\");\n"
6316 "}\n\n", name, name, name, dispname);
6317
6318 /* ctor for optional value */
6319 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n",
6320 name, name);
6321 src = mputprintf(src, "%s_template::%s_template(const OPTIONAL<%s>& "
6322 "other_value)\n"
6323 "{\n"
6324 "switch (other_value.get_selection()) {\n"
6325 "case OPTIONAL_PRESENT:\n"
6326 "set_selection(SPECIFIC_VALUE);\n"
6327 "break;\n"
6328 "case OPTIONAL_OMIT:\n"
6329 "set_selection(OMIT_VALUE);\n"
6330 "break;\n"
6331 "default:\n"
6332 "TTCN_error(\"Creating a template of type %s from an unbound optional "
6333 "field.\");\n"
6334 "}\n"
6335 "}\n\n", name, name, name, dispname);
6336
6337 /* copy ctor */
6338 def = mputprintf(def, "%s_template(const %s_template& other_value);\n",
6339 name, name);
6340 src = mputprintf(src, "%s_template::%s_template(const %s_template& "
6341 "other_value)\n"
6342 ": Base_Template()" /* yes, the base class _default_ constructor */
6343 "{\n"
6344 "copy_template(other_value);\n"
6345 "}\n\n", name, name, name);
6346
6347 /* dtor */
6348 def = mputprintf(def, "~%s_template();\n", name);
6349 src = mputprintf(src, "%s_template::~%s_template()\n"
6350 "{\n"
6351 "clean_up();\n"
6352 "}\n\n", name, name);
6353
6354 /* clean_up function */
6355 def = mputstr(def, "void clean_up();\n");
6356 src = mputprintf(src, "void %s_template::clean_up()\n"
6357 "{\n"
6358 "if (template_selection == VALUE_LIST || "
6359 "template_selection == COMPLEMENTED_LIST)\n"
6360 "delete [] value_list.list_value;\n"
6361 "template_selection = UNINITIALIZED_TEMPLATE;\n"
6362 "}\n\n", name);
6363
6364 /* assignment op for generic wildcards */
6365 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
6366 name);
6367 src = mputprintf(src, "%s_template& %s_template::operator=(template_sel "
6368 "other_value)\n"
6369 "{\n"
6370 "check_single_selection(other_value);\n"
6371 "clean_up();\n"
6372 "set_selection(other_value);\n"
6373 "return *this;\n"
6374 "}\n\n", name, name);
6375
6376 /* assignment op for value {} */
6377 def = mputprintf(def, "%s_template& operator=(null_type other_value);\n",
6378 name);
6379 src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n"
6380 "{\n"
6381 "clean_up();\n"
6382 "set_selection(SPECIFIC_VALUE);\n"
6383 "return *this;\n"
6384 "}\n\n", name, name);
6385
6386 /* assignment op for specific value */
6387 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
6388 name, name);
6389 src = mputprintf(src, "%s_template& %s_template::operator=(const %s& "
6390 "other_value)\n"
6391 "{\n"
6392 "other_value.must_bound(\"Assignment of an unbound value of type %s "
6393 "to a template.\");\n"
6394 "clean_up();\n"
6395 "set_selection(SPECIFIC_VALUE);\n"
6396 "return *this;\n"
6397 "}\n\n", name, name, name, dispname);
6398
6399 /* assignment op for optional value */
6400 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
6401 "other_value);\n", name, name);
6402 src = mputprintf(src, "%s_template& %s_template::operator="
6403 "(const OPTIONAL<%s>& other_value)\n"
6404 "{\n"
6405 "clean_up();\n"
6406 "switch (other_value.get_selection()) {\n"
6407 "case OPTIONAL_PRESENT:\n"
6408 "set_selection(SPECIFIC_VALUE);\n"
6409 "break;\n"
6410 "case OPTIONAL_OMIT:\n"
6411 "set_selection(OMIT_VALUE);\n"
6412 "break;\n"
6413 "default:\n"
6414 "TTCN_error(\"Assignment of an unbound optional field to a template "
6415 "of type %s.\");\n"
6416 "}\n"
6417 "return *this;\n"
6418 "}\n\n", name, name, name, dispname);
6419
6420 /* assignment op for itself */
6421 def = mputprintf(def, "%s_template& operator=(const %s_template& "
6422 "other_value);\n", name, name);
6423 src = mputprintf(src, "%s_template& %s_template::operator="
6424 "(const %s_template& other_value)\n"
6425 "{\n"
6426 "if (&other_value != this) {\n"
6427 "clean_up();\n"
6428 "set_selection(other_value);\n"
6429 "}\n"
6430 "return *this;\n"
6431 "}\n\n", name, name, name);
6432
6433 /* match operation with {} */
3abe9331 6434 def = mputstr(def, "boolean match(null_type other_value, boolean legacy "
6435 "= FALSE) const;\n");
6436 src = mputprintf(src, "boolean %s_template::match(null_type other_value,"
6437 "boolean) const\n"
970ed795
EL
6438 "{\n"
6439 "switch (template_selection) {\n"
6440 "case ANY_VALUE:\n"
6441 "case ANY_OR_OMIT:\n"
6442 "case SPECIFIC_VALUE:\n"
6443 "return TRUE;\n"
6444 "case OMIT_VALUE:\n"
6445 "return FALSE;\n"
6446 "case VALUE_LIST:\n"
6447 "case COMPLEMENTED_LIST:\n"
6448 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
6449 "list_count++)\n"
6450 "if (value_list.list_value[list_count].match(other_value)) "
6451 "return template_selection == VALUE_LIST;\n"
6452 "return template_selection == COMPLEMENTED_LIST;\n"
6453 "default:\n"
6454 "TTCN_error(\"Matching an uninitialized/unsupported template of "
6455 "type %s.\");\n"
6456 "}\n"
6457 "return FALSE;\n"
6458 "}\n\n", name, dispname);
6459
6460 /* match operation with specific value */
3abe9331 6461 def = mputprintf(def, "boolean match(const %s& other_value, boolean legacy "
6462 "= FALSE) const;\n", name);
6463 src = mputprintf(src, "boolean %s_template::match(const %s& other_value, "
6464 "boolean) const\n"
970ed795
EL
6465 "{\n"
6466 "if (!other_value.is_bound()) return FALSE;"
6467 "return match(NULL_VALUE);\n"
6468 "}\n\n", name, name);
6469
6470 /* valueof operation */
6471 def = mputprintf(def, "%s valueof() const;\n", name);
6472 src = mputprintf(src, "%s %s_template::valueof() const\n"
6473 "{\n"
6474 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) "
6475 "TTCN_error(\"Performing a valueof or send operation on a "
6476 "non-specific template of type %s.\");\n"
6477 "return NULL_VALUE;\n"
6478 "}\n\n", name, name, dispname);
6479
6480 /* void set_type(template_sel, int) function */
6481 def = mputstr(def,
6482 "void set_type(template_sel template_type, "
6483 "unsigned int list_length);\n");
6484
6485 src = mputprintf(src,
6486 "void %s_template::set_type(template_sel template_type, "
6487 "unsigned int list_length)\n"
6488 "{\n"
6489 "if (template_type != VALUE_LIST "
6490 "&& template_type != COMPLEMENTED_LIST)\n"
6491 "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n"
6492 "clean_up();\n"
6493 "set_selection(template_type);\n"
6494 "value_list.n_values = list_length;\n"
6495 "value_list.list_value = new %s_template[list_length];\n"
6496 "}\n\n", name, dispname, name);
6497
6498 /* list_item(int) function */
6499
6500 def = mputprintf(def,
6501 "%s_template& list_item(unsigned int list_index) const;\n", name);
6502
6503 src = mputprintf(src,
6504 "%s_template& %s_template::list_item(unsigned int list_index) const\n"
6505 "{\n"
6506 "if (template_selection != VALUE_LIST "
6507 "&& template_selection != COMPLEMENTED_LIST)\n"
6508 "TTCN_error(\"Accessing a list element of a non-list template of "
6509 "type %s.\");\n"
6510 "if (list_index >= value_list.n_values)\n"
6511 "TTCN_error(\"Index overflow in a value list template of type "
6512 "%s.\");\n"
6513 "return value_list.list_value[list_index];\n"
6514 "}\n\n", name, name, dispname, dispname);
6515
6516 /* log function */
6517 def = mputstr(def, "void log() const;\n");
6518 src = mputprintf(src, "void %s_template::log() const\n"
6519 "{\n"
6520 "switch (template_selection) {\n"
6521 "case SPECIFIC_VALUE:\n"
6522 "TTCN_Logger::log_event_str(\"{ }\");\n"
6523 "break;\n"
6524 "case COMPLEMENTED_LIST:\n"
6525 "TTCN_Logger::log_event_str(\"complement \");\n"
6526 "case VALUE_LIST:\n"
6527 "TTCN_Logger::log_char('(');\n"
6528 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
6529 "list_count++) {\n"
6530 "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n"
6531 "value_list.list_value[list_count].log();\n"
6532 "}\n"
6533 "TTCN_Logger::log_char(')');\n"
6534 "break;\n"
6535 "default:\n"
6536 "log_generic();\n"
6537 "}\n"
6538 "log_ifpresent();\n"
6539 "}\n\n", name);
6540
6541 /* log_match function */
3abe9331 6542 def = mputprintf(def, "void log_match(const %s& match_value, "
6543 "boolean legacy = FALSE) const;\n", name);
6544 src = mputprintf(src, "void %s_template::log_match(const %s& match_value, "
6545 "boolean) const\n"
970ed795
EL
6546 "{\n"
6547 "match_value.log();\n"
6548 "TTCN_Logger::log_event_str(\" with \");\n"
6549 "log();\n"
6550 "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n"
6551 "else TTCN_Logger::log_event_str(\" unmatched\");\n"
6552 "}\n\n", name, name);
6553
6554 /* encode_text function */
6555 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
6556 src = mputprintf(src, "void %s_template::encode_text(Text_Buf& text_buf) "
6557 "const\n"
6558 "{\n"
6559 "encode_text_base(text_buf);\n"
6560 "switch (template_selection) {\n"
6561 "case OMIT_VALUE:\n"
6562 "case ANY_VALUE:\n"
6563 "case ANY_OR_OMIT:\n"
6564 "case SPECIFIC_VALUE:\n"
6565 "break;\n"
6566 "case VALUE_LIST:\n"
6567 "case COMPLEMENTED_LIST:\n"
6568 "text_buf.push_int(value_list.n_values);\n"
6569 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
6570 "list_count++)\n"
6571 "value_list.list_value[list_count].encode_text(text_buf);\n"
6572 "break;\n"
6573 "default:\n"
6574 "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported "
6575 "template of type %s.\");\n"
6576 "}\n"
6577 "}\n\n", name, dispname);
6578
6579 /* decode_text function */
6580 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
6581 src = mputprintf(src, "void %s_template::decode_text(Text_Buf& text_buf)\n"
6582 "{\n"
6583 "clean_up();\n"
6584 "decode_text_base(text_buf);\n"
6585 "switch (template_selection) {\n"
6586 "case OMIT_VALUE:\n"
6587 "case ANY_VALUE:\n"
6588 "case ANY_OR_OMIT:\n"
6589 "case SPECIFIC_VALUE:\n"
6590 "break;\n"
6591 "case VALUE_LIST:\n"
6592 "case COMPLEMENTED_LIST:\n"
6593 "value_list.n_values = text_buf.pull_int().get_val();\n"
6594 "value_list.list_value = new %s_template[value_list.n_values];\n"
6595 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
6596 "list_count++)\n"
6597 "value_list.list_value[list_count].decode_text(text_buf);\n"
6598 "break;\n"
6599 "default:\n"
6600 "TTCN_error(\"Text decoder: An unknown/unsupported selection was "
6601 "received in a template of type %s.\");\n"
6602 "}\n"
6603 "}\n\n", name, name, dispname);
6604
6605 /* set_param() */
3abe9331 6606 def = mputstr(def, "void set_param(Module_Param& param);\n");
970ed795 6607 src = mputprintf(src,
3abe9331 6608 "void %s_template::set_param(Module_Param& param)\n"
970ed795
EL
6609 "{\n"
6610 " param.basic_check(Module_Param::BC_TEMPLATE, \"empty record/set template\");\n"
3abe9331 6611 " Module_Param_Ptr mp = &param;\n"
6612 " if (param.get_type() == Module_Param::MP_Reference) {\n"
6613 " mp = param.get_referenced_param();\n"
6614 " }\n"
6615 " switch (mp->get_type()) {\n"
970ed795
EL
6616 " case Module_Param::MP_Omit:\n"
6617 " *this = OMIT_VALUE;\n"
6618 " break;\n"
6619 " case Module_Param::MP_Any:\n"
6620 " *this = ANY_VALUE;\n"
6621 " break;\n"
6622 " case Module_Param::MP_AnyOrNone:\n"
6623 " *this = ANY_OR_OMIT;\n"
6624 " break;\n"
6625 " case Module_Param::MP_List_Template:\n"
3abe9331 6626 " case Module_Param::MP_ComplementList_Template: {\n"
6627 " %s_template temp;\n"
6628 " temp.set_type(mp->get_type()==Module_Param::MP_List_Template ? "
6629 "VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());\n"
6630 " for (size_t p_i=0; p_i<mp->get_size(); p_i++) {\n"
6631 " temp.list_item(p_i).set_param(*mp->get_elem(p_i));\n"
970ed795 6632 " }\n"
3abe9331 6633 " *this = temp;\n"
6634 " break; }\n"
970ed795 6635 " case Module_Param::MP_Value_List:\n"
3abe9331 6636 " if (mp->get_size()>0) param.type_error(\"empty record/set template\", \"%s\");\n"
970ed795
EL
6637 " *this = NULL_VALUE;\n"
6638 " break;\n"
6639 " default:\n"
6640 " param.type_error(\"empty record/set template\", \"%s\");\n"
6641 " }\n"
3abe9331 6642 " is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();\n"
6643 "}\n\n", name, name, dispname, dispname);
6644
6645 /* get_param() */
6646 def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
6647 src = mputprintf(src,
6648 "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n"
6649 "{\n"
6650 " Module_Param* mp = NULL;\n"
6651 " switch (template_selection) {\n"
6652 " case UNINITIALIZED_TEMPLATE:\n"
6653 " mp = new Module_Param_Unbound();\n"
6654 " break;\n"
6655 " case OMIT_VALUE:\n"
6656 " mp = new Module_Param_Omit();\n"
6657 " break;\n"
6658 " case ANY_VALUE:\n"
6659 " mp = new Module_Param_Any();\n"
6660 " break;\n"
6661 " case ANY_OR_OMIT:\n"
6662 " mp = new Module_Param_AnyOrNone();\n"
6663 " break;\n"
6664 " case SPECIFIC_VALUE:\n"
6665 " mp = new Module_Param_Value_List();\n"
6666 " break;\n"
6667 " case VALUE_LIST:\n"
6668 " case COMPLEMENTED_LIST: {\n"
6669 " if (template_selection == VALUE_LIST) {\n"
6670 " mp = new Module_Param_List_Template();\n"
6671 " }\n"
6672 " else {\n"
6673 " mp = new Module_Param_ComplementList_Template();\n"
6674 " }\n"
6675 " for (size_t i = 0; i < value_list.n_values; ++i) {\n"
6676 " mp->add_elem(value_list.list_value[i].get_param(param_name));\n"
6677 " }\n"
6678 " break; }\n"
6679 " default:\n"
6680 " break;\n"
6681 " }\n"
6682 " if (is_ifpresent) {\n"
6683 " mp->set_ifpresent();\n"
6684 " }\n"
6685 " return mp;\n"
6686 "}\n\n", name);
970ed795
EL
6687
6688 /* check template restriction */
6689 def = mputstr(def, "void check_restriction(template_res t_res, "
3abe9331 6690 "const char* t_name=NULL, boolean legacy = FALSE) const;\n");
970ed795
EL
6691 src = mputprintf(src,
6692 "void %s_template::check_restriction("
3abe9331 6693 "template_res t_res, const char* t_name, boolean legacy) const\n"
970ed795
EL
6694 "{\n"
6695 "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
6696 "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
6697 "case TR_OMIT:\n"
6698 "if (template_selection==OMIT_VALUE) return;\n"
6699 "case TR_VALUE:\n"
6700 "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n"
6701 "return;\n"
6702 "case TR_PRESENT:\n"
3abe9331 6703 "if (!match_omit(legacy)) return;\n"
970ed795
EL
6704 "break;\n"
6705 "default:\n"
6706 "return;\n"
6707 "}\n"
6708 "TTCN_error(\"Restriction `%%s' on template of type %%s "
6709 "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n"
6710 "}\n\n", name, dispname);
6711
6712 defCommonRecordTemplate(name, &def, &src);
6713
6714 def = mputstr(def, "};\n\n");
6715
6716 output->header.class_defs = mputstr(output->header.class_defs, def);
6717 Free(def);
6718
6719 output->source.methods = mputstr(output->source.methods, src);
6720 Free(src);
6721}
6722
6723static void defCommonRecordTemplate(const char *name,
6724 char **def, char **src)
6725{
6726 /* TTCN-3 ispresent() function */
3abe9331 6727 *def = mputstr(*def, "boolean is_present(boolean legacy = FALSE) const;\n");
970ed795 6728 *src = mputprintf(*src,
3abe9331 6729 "boolean %s_template::is_present(boolean legacy) const\n"
970ed795
EL
6730 "{\n"
6731 "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n"
3abe9331 6732 "return !match_omit(legacy);\n"
970ed795
EL
6733 "}\n\n", name);
6734
6735 /* match_omit() */
3abe9331 6736 *def = mputstr(*def, "boolean match_omit(boolean legacy = FALSE) const;\n");
970ed795 6737 *src = mputprintf(*src,
3abe9331 6738 "boolean %s_template::match_omit(boolean legacy) const\n"
970ed795
EL
6739 "{\n"
6740 "if (is_ifpresent) return TRUE;\n"
6741 "switch (template_selection) {\n"
6742 "case OMIT_VALUE:\n"
6743 "case ANY_OR_OMIT:\n"
6744 "return TRUE;\n"
6745 "case VALUE_LIST:\n"
6746 "case COMPLEMENTED_LIST:\n"
3abe9331 6747 "if (legacy) {\n"
970ed795
EL
6748 "for (unsigned int l_idx=0; l_idx<value_list.n_values; l_idx++)\n"
6749 "if (value_list.list_value[l_idx].match_omit())\n"
6750 "return template_selection==VALUE_LIST;\n"
6751 "return template_selection==COMPLEMENTED_LIST;\n"
3abe9331 6752 "} // else fall through\n"
970ed795
EL
6753 "default:\n"
6754 "return FALSE;\n"
6755 "}\n"
6756 "return FALSE;\n"
6757 "}\n\n", name);
6758}
6759
6760/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
6761
6762void defRecordClass2(const struct_def *sdef, output_struct *output)
6763{
6764 size_t i;
6765 size_t optional_num = 0;
6766 const char *name = sdef->name;
6767 char *def = NULL, *src = NULL;
6768
6769 boolean xer_needed = sdef->hasXer && enable_xer();
6770 boolean raw_needed = sdef->hasRaw && enable_raw();
6771 boolean has_optional = FALSE;
6772 boolean has_default = FALSE;
6773
6774 const char* base_class = (sdef->nElements==0) ? "Empty_Record_Type" : "Record_Type";
6775
6776 /* class declaration code */
6777 output->header.class_decls = mputprintf(output->header.class_decls,
6778 "class %s;\n", name);
6779
6780 /* class definition and source code */
6781 def=mputprintf(def, "class %s : public %s {\n", name, base_class);
6782
6783 /* data members */
6784 for (i = 0; i < sdef->nElements; i++) {
6785 if(sdef->elements[i].isOptional) {
6786 optional_num++;
6787 def = mputprintf(def, " OPTIONAL<%s> field_%s;\n",
6788 sdef->elements[i].type,
6789 sdef->elements[i].name);
6790 } else {
6791 def = mputprintf(def, " %s field_%s;\n",
6792 sdef->elements[i].type, sdef->elements[i].name);
6793 }
6794 }
6795 if (sdef->nElements) {
6796 def = mputprintf(def, " Base_Type* fld_vec[%lu];\n", (unsigned long)sdef->nElements);
6797 }
6798
6799 /* default constructor */
6800 if (sdef->nElements==0) {
6801 def = mputprintf(def, "public:\n"
6802 " %s();\n", name);
6803 src = mputprintf(src,
6804 "%s::%s() : Empty_Record_Type() {}\n\n",
6805 name, name);
6806 } else {
6807 def = mputstr(def, " void init_vec();\n");
6808 src = mputprintf(src, "void %s::init_vec() { ", name);
6809 for (i = 0; i < sdef->nElements; i++) {
6810 src = mputprintf(src, "fld_vec[%lu]=&field_%s; ",
6811 (unsigned long)i, sdef->elements[i].name);
6812 }
6813 src = mputstr(src, " }\n\n");
6814
6815 def = mputprintf(def, "public:\n"
6816 " %s();\n", name);
6817 src = mputprintf(src,
6818 "%s::%s() : Record_Type() { init_vec(); }\n\n", name, name);
6819 }
6820
6821 /* copy constructor */
6822 if (sdef->nElements) {
6823 def = mputprintf(def, " %s(const %s& other_value);\n", name, name);
6824 src = mputprintf(src, "%s::%s(const %s& other_value) : Record_Type(other_value)\n", name, name, name);
6825 src = mputstr(src, "{\n"
6826 " if(!other_value.is_bound()) "
6827 "TTCN_error(\"Copying an unbound record/set value.\");\n"
6828 "bound_flag = TRUE;\n");
6829 for (i = 0; i < sdef->nElements; i++) {
6830 src = mputprintf(src,
6831 "if (other_value.field_%s.is_bound() )\n"
6832 " field_%s = other_value.field_%s;\n",
6833 sdef->elements[i].name, sdef->elements[i].name,
6834 sdef->elements[i].name);
6835 }
6836
6837 src = mputstr(src, "init_vec();\n"
6838 "}\n\n");
6839 } else {
6840 def = mputprintf(def, " %s(const %s& other_value): %s(other_value) {}\n", name, name, base_class);
6841 }
6842
6843 if (sdef->nElements>0) { /* constructor by fields */
6844 def = mputprintf(def, " %s(", name);
6845 src = mputprintf(src, "%s::%s(", name, name);
6846 for (i = 0; i < sdef->nElements; i++) {
6847 char *tmp = NULL;
6848 if (i > 0) tmp = mputstr(tmp, ",\n ");
6849 if (sdef->elements[i].isOptional)
6850 tmp = mputprintf
6851 (tmp,
6852 "const OPTIONAL<%s>& par_%s",
6853 sdef->elements[i].type, sdef->elements[i].name);
6854 else
6855 tmp = mputprintf
6856 (tmp,
6857 "const %s& par_%s",
6858 sdef->elements[i].type, sdef->elements[i].name);
6859 def = mputstr(def, tmp);
6860 src = mputstr(src, tmp);
6861 Free(tmp);
6862 }
6863 def = mputstr(def, ");\n");
6864 src = mputprintf(src, ") : ");
6865 for (i = 0; i < sdef->nElements; i++) {
6866 if (i > 0) src = mputstr(src, ",\n ");
6867 src = mputprintf(src, "field_%s(par_%s)", sdef->elements[i].name,
6868 sdef->elements[i].name);
6869 }
6870 src = mputstr(src, "\n"
6871 "{\n"
6872 "init_vec();\n"
6873 "bound_flag = TRUE;\n"
6874 "}\n\n");
6875 } else { /* constructor from null */
6876 def = mputprintf(def, " %s(null_type) {bound_flag = TRUE;}\n", name);
6877 }
6878
6879 /* assignment operators */
6880 def = mputprintf(def, "inline %s& operator=(const %s& other_value) "
6881 "{ set_value(&other_value); return *this; }\n\n", name, name);
6882 if (sdef->nElements == 0) {
6883 def = mputprintf(def, "inline %s& operator=(null_type) "
6884 "{ bound_flag = TRUE; return *this; }\n", name);
6885 }
6886
6887 /* == operator */
6888 def = mputprintf(def, "inline boolean operator==(const %s& other_value) "
6889 "const { return is_equal(&other_value); }\n", name);
6890 /* != operator */
6891 def = mputprintf(def,
6892 " inline boolean operator!=(const %s& other_value) const\n"
6893 " { return !is_equal(&other_value); }\n\n", name);
6894
6895 for (i = 0; i < sdef->nElements; i++) {
6896 if(sdef->elements[i].isOptional)
6897 def = mputprintf
6898 (def,
6899 " inline OPTIONAL<%s>& %s()\n"
6900 " {return field_%s;}\n"
6901 " inline const OPTIONAL<%s>& %s() const\n"
6902 " {return field_%s;}\n",
6903 sdef->elements[i].type, sdef->elements[i].name,
6904 sdef->elements[i].name,
6905 sdef->elements[i].type, sdef->elements[i].name,
6906 sdef->elements[i].name);
6907 else def = mputprintf
6908 (def,
6909 " inline %s& %s()\n"
6910 " {return field_%s;}\n"
6911 " inline const %s& %s() const\n"
6912 " {return field_%s;}\n",
6913 sdef->elements[i].type, sdef->elements[i].name,
6914 sdef->elements[i].name, sdef->elements[i].type,
6915 sdef->elements[i].name, sdef->elements[i].name);
6916
6917 }
6918
6919 /* override virtual functions where needed */
6920 def = mputprintf(def,
6921 "Base_Type* clone() const { return new %s(*this); }\n"
6922 "const TTCN_Typedescriptor_t* get_descriptor() const;\n"
6923 "boolean is_set() const { return %s; }\n",
6924 name,
6925 (sdef->kind==SET) ? "TRUE" : "FALSE");
6926 src = mputprintf(src,
6927 "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n",
6928 name, name);
6929
6930 if (sdef->nElements > 0) {
6931
6932 /* field access functions */
6933 def = mputprintf(def,
6934 "Base_Type* get_at(int index_value) { return fld_vec[index_value]; }\n"
6935 "const Base_Type* get_at(int index_value) const { return fld_vec[index_value]; }\n\n"
6936 "int get_count() const { return %lu; }\n", (unsigned long)sdef->nElements);
6937
6938 /* override if there are optional fields */
6939 if (optional_num) {
6940 def = mputprintf(def,
6941 "int optional_count() const { return %lu; }\n", (unsigned long)optional_num);
6942 }
6943
6944 if (sdef->opentype_outermost)
6945 def = mputstr(def, "boolean is_opentype_outermost() const { return TRUE; }\n");
6946
6947 /* FIXME: use static member in Record_Type and initialize somewhere */
6948 if (default_as_optional)
6949 def = mputstr(def, "boolean default_as_optional() const { return TRUE; }\n");
6950
6951 for (i = 0; i < sdef->nElements; i++) {
6952 if (sdef->elements[i].isOptional) {
6953 has_optional = TRUE;
6954 break;
6955 }
6956 }
6957
6958 for (i = 0; i < sdef->nElements; i++) {
6959 if (sdef->elements[i].isDefault) {
6960 has_default = TRUE;
6961 break;
6962 }
6963 }
6964 def = mputstr(def,
6965 "static const TTCN_Typedescriptor_t* fld_descriptors[];\n"
6966 "const TTCN_Typedescriptor_t* fld_descr(int p_index) const;\n\n"
6967 "static const char* fld_names[];\n"
6968 "const char* fld_name(int p_index) const;\n\n");
6969
6970 src = mputprintf(src, "const TTCN_Typedescriptor_t* %s::fld_descriptors[] = ", name);
6971 for (i = 0; i < sdef->nElements; i++) {
6972 src = mputprintf(src, "%c &%s_descr_",
6973 (i ? ',' : '{'), sdef->elements[i].typedescrname);
6974 }
6975 src = mputstr(src, " };\n");
6976 src = mputprintf(src,
6977 "const TTCN_Typedescriptor_t* %s::fld_descr(int p_index) const "
6978 "{ return fld_descriptors[p_index]; }\n\n", name);
6979
6980 src = mputprintf(src, "const char* %s::fld_names[] = ", name);
6981 for (i = 0; i < sdef->nElements; i++) {
6982 src = mputprintf(src, "%c \"%s\"",
6983 (i ? ',' : '{'), sdef->elements[i].dispname);
6984 }
6985 src = mputstr(src, " };\n");
6986
6987 src = mputprintf(src,
6988 "const char* %s::fld_name(int p_index) const "
6989 "{ return fld_names[p_index]; }\n\n", name);
6990
6991 if (has_optional) {
6992 def = mputstr(def,
6993 "static const int optional_indexes[];\n"
6994 "const int* get_optional_indexes() const;\n\n");
6995 src = mputprintf(src, "const int %s::optional_indexes[] = { ", name);
6996 for (i = 0; i < sdef->nElements; i++) {
6997 if (sdef->elements[i].isOptional) {
6998 src = mputprintf(src, "%lu, ", (unsigned long)i);
6999 }
7000 }
7001 src = mputstr(src, "-1 };\n");
7002 src = mputprintf(src,
7003 "const int* %s::get_optional_indexes() const "
7004 "{ return optional_indexes; }\n\n", name);
7005 }
7006
7007 if (has_default) {
7008 def = mputstr(def,
7009 "static const default_struct default_indexes[];\n"
7010 "const default_struct* get_default_indexes() const;\n");
7011 src = mputprintf(src, "const Record_Type::default_struct %s::default_indexes[] = { ", name);
7012 for (i = 0; i < sdef->nElements; i++) {
7013 if (sdef->elements[i].isDefault) {
7014 src = mputprintf(src, "{%lu,&%s}, ",
7015 (unsigned long)i, sdef->elements[i].defvalname);
7016 }
7017 }
7018 src = mputstr(src, "{-1,NULL} };\n");
7019 src = mputprintf(src,
7020 "const Record_Type::default_struct* %s::get_default_indexes() const "
7021 "{ return default_indexes; }\n", name);
7022 }
7023
7024 if (raw_needed) {
7025 struct raw_option_struct *raw_options;
7026 boolean haslengthto, haspointer, hascrosstag, has_ext_bit;
7027 boolean generate_raw_function = FALSE;
7028
7029 raw_options = (struct raw_option_struct*)
7030 Malloc(sdef->nElements * sizeof(*raw_options));
7031
7032 set_raw_options(sdef, raw_options, &haslengthto,
7033 &haspointer, &hascrosstag, &has_ext_bit);
7034
7035 /* set the value of generate_raw_function: if the coding/decoding is too
7036 complex for this type then generate the functions, otherwise generate
7037 helper functions only which are called by the default RAW enc/dec
7038 functions */
7039 if (haslengthto || haspointer || hascrosstag) {
7040 generate_raw_function = TRUE;
7041 goto check_generate_end;
7042 }
7043 for (i = 0; i < sdef->nElements; i++) {
7044 if (raw_options[i].lengthto || raw_options[i].lengthof ||
7045 raw_options[i].lengthoffield || raw_options[i].pointerto ||
7046 raw_options[i].pointerof || raw_options[i].ptrbase ||
7047 raw_options[i].extbitgroup || raw_options[i].tag_type ||
7048 raw_options[i].delayed_decode || raw_options[i].nof_dependent_fields
7049 || raw_options[i].dependent_fields) {
7050 generate_raw_function = TRUE;
7051 goto check_generate_end;
7052 }
7053 }
7054 for (i = 0; i < sdef->nElements; i++) {
7055 if (raw_options[i].lengthof || raw_options[i].lengthoffield ||
7056 raw_options[i].nof_dependent_fields ||
7057 raw_options[i].dependent_fields) {
7058 generate_raw_function = TRUE;
7059 goto check_generate_end;
7060 }
7061 }
7062 if (sdef->raw.ext_bit_goup_num || sdef->raw.ext_bit_groups ||
7063 sdef->raw.lengthto || sdef->raw.lengthindex ||
7064 sdef->raw.taglist.nElements || sdef->raw.crosstaglist.nElements ||
7065 sdef->raw.presence.fieldnum || sdef->raw.presence.fields ||
7066 sdef->raw.member_name) {
7067 generate_raw_function = TRUE;
7068 goto check_generate_end;
7069 }
7070 for (i = 0; i < sdef->nElements; i++) {
7071 if (sdef->elements[i].hasRaw) {
7072 generate_raw_function = TRUE;
7073 goto check_generate_end;
7074 }
7075 }
7076check_generate_end:
7077
7078 if (generate_raw_function) {
7079 def = mputprintf(def,
7080 "int RAW_encode(const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n"
7081 "virtual int RAW_encode_negtest(const Erroneous_descriptor_t *, const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n"
7082 "int RAW_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, "
7083 "int, raw_order_t, boolean no_err = FALSE, "
7084 "int sel_field = -1, boolean first_call = TRUE);\n");
7085 src = generate_raw_coding(src, sdef, raw_options, haspointer,
7086 hascrosstag, has_ext_bit);
7087 } else { /* generate helper functions for the default RAW enc/dec */
7088 if (has_ext_bit)
7089 def = mputstr(def,"boolean raw_has_ext_bit() const { return TRUE; }\n");
7090 }
7091 for (i = 0; i < sdef->nElements; i++) {
7092 Free(raw_options[i].lengthoffield);
7093 Free(raw_options[i].dependent_fields);
7094 }
7095 Free(raw_options);
7096 } /* if (raw_needed) */
7097
7098 if (xer_needed) { /* XERSTUFF codegen for record/SEQUENCE in RT2 */
7099 size_t num_attributes = 0;
7100
7101 /* XER descriptors needed because of the xer antipattern */
7102 def = mputstr(def,
7103 "static const XERdescriptor_t* xer_descriptors[];\n"
7104 "const XERdescriptor_t* xer_descr(int p_index) const;\n"
7105 "virtual boolean can_start_v(const char *name, const char *prefix, "
7106 "XERdescriptor_t const& xd, unsigned int flavor);\n"
7107 "static boolean can_start (const char *name, const char *prefix, "
7108 "XERdescriptor_t const& xd, unsigned int flavor);\n");
7109 src = mputprintf(src, "const XERdescriptor_t* %s::xer_descriptors[] = ", name);
7110 for (i = 0; i < sdef->nElements; i++) {
7111 src = mputprintf(src, "%c &%s_xer_",
7112 (i ? ',' : '{'), sdef->elements[i].typegen);
7113 }
7114 src = mputstr(src, " };\n");
7115 src = mputprintf(src,
7116 "const XERdescriptor_t* %s::xer_descr(int p_index) const "
7117 "{ return xer_descriptors[p_index]; }\n"
7118 /* The virtual can_start_v hands off to the static can_start.
7119 * We must make a virtual call in Record_Type::XER_decode because
7120 * we don't know the actual type (derived from Record_Type) */
7121 "boolean %s::can_start_v(const char *p_name, const char *p_uri, "
7122 "XERdescriptor_t const& p_td, unsigned int p_flavor)\n"
7123 "{ return can_start(p_name, p_uri, p_td, p_flavor); }\n"
7124 "boolean %s::can_start(const char *p_name, const char *p_uri, "
7125 "XERdescriptor_t const& p_td, unsigned int p_flavor) {\n"
7126 " boolean e_xer = is_exer(p_flavor);\n"
7127 " 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"
7128 , name , name, name);
7129 for (i = 0; i < sdef->nElements; i++) {
7130 src = mputprintf(src,
7131 " else if (%s::can_start(p_name, p_uri, %s_xer_, p_flavor)) return true;\n"
7132 , sdef->elements[i].type, sdef->elements[i].typegen);
7133 }
7134 src = mputstr(src,
7135 " return false;\n"
7136 "}\n\n");
7137 /* end of antipattern */
7138
7139 /* calculate num_attributes in compile time */
7140 for ( i=0; i < sdef->nElements; ++i ) {
7141 if (sdef->elements[i].xerAttribute
7142 ||(sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) ++num_attributes;
7143 else if (num_attributes) break;
7144 }
7145
7146 /* generate helper virtual functions for XER encdec */
7147 if (num_attributes) {
7148 def = mputprintf(def,
7149 "int get_xer_num_attr() const { return %lu; }\n",
7150 (unsigned long)num_attributes);
7151 }
7152 }
7153 else { /* XER not needed */
7154 def = mputstr(def,
7155 "boolean can_start_v(const char *, const char *, XERdescriptor_t const&, unsigned int)\n"
7156 "{ return FALSE; }\n"
7157 );
7158 } /* if (xer_needed) */
7159 } /* if (sdef->nElements > 0) */
7160
7161 /* end of class definition */
7162 def = mputstr(def, "};\n\n");
7163
7164 output->header.class_defs = mputstr(output->header.class_defs, def);
7165 Free(def);
7166
7167 output->source.methods = mputstr(output->source.methods, src);
7168 Free(src);
7169}
7170
7171void defRecordTemplate2(const struct_def *sdef, output_struct *output)
7172{
7173 int i;
7174 const char *name = sdef->name;
7175 char *def = NULL, *src = NULL;
7176
7177 const char* base_class = (sdef->nElements==0) ? "Empty_Record_Template" : "Record_Template";
7178
7179 /* class declaration */
7180 output->header.class_decls = mputprintf(output->header.class_decls,
7181 "class %s_template;\n", name);
7182
7183 /* template class definition */
7184 def = mputprintf(def, "class %s_template : public %s {\n", name, base_class);
7185
7186 if (sdef->nElements>0) {
7187 /* set_specific function (used in field access members) */
7188 def = mputstr(def, "void set_specific();\n");
7189 src = mputprintf(src, "void %s_template::set_specific()\n"
7190 "{\n"
7191 "if (template_selection != SPECIFIC_VALUE) {\n"
7192 "%s"
7193 "clean_up();\n"
7194 "single_value.n_elements = %lu;\n"
7195 "single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);\n"
7196 "set_selection(SPECIFIC_VALUE);\n",
7197 name, sdef->nElements ? "boolean was_any = (template_selection == ANY_VALUE || template_selection == ANY_OR_OMIT);\n" : "",
7198 (unsigned long)sdef->nElements);
7199 for (i = 0; i < sdef->nElements; i++) {
7200 src = mputprintf(src,
7201 "single_value.value_elements[%d] = was_any ? new %s_template(%s) : new %s_template;\n",
7202 i, sdef->elements[i].type,
7203 sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE",
7204 sdef->elements[i].type);
7205 }
7206 src = mputstr(src,
7207 "}\n"
7208 "}\n\n");
7209 }
7210
7211 /* default constructor */
7212 def = mputprintf(def, "public:\n"
7213 "%s_template(): %s() {}\n", name, base_class);
7214
7215 if (sdef->nElements==0) {
7216 /* ctor for value {} */
7217 def = mputprintf(def, "%s_template(null_type) : "
7218 "Empty_Record_Template() { set_selection(SPECIFIC_VALUE); }\n",
7219 name);
7220 }
7221
7222 /* constructor t1_template(template_sel other_value) */
7223 def = mputprintf(def, "%s_template(template_sel other_value): "
7224 "%s(other_value) {}\n", name, base_class);
7225
7226 /* constructor t1_template(const t1& other_value) */
7227 def = mputprintf(def, "%s_template(const %s& other_value): "
7228 "%s() { copy_value(&other_value); }\n",
7229 name, name, base_class);
7230
7231 /* constructor t1_template(const OPTIONAL<t1>& other_value) */
7232 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value): "
7233 "%s() { copy_optional(&other_value); }\n",
7234 name, name, base_class);
7235
7236 /* copy constructor */
7237 def = mputprintf(def, "%s_template(const %s_template& other_value): %s() "
7238 "{ copy_template(other_value); }\n", name, name, base_class);
7239
7240 /* assignment operator <- template_sel */
7241 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
7242 name);
7243 src = mputprintf(src,
7244 "%s_template& %s_template::operator=(template_sel other_value)\n"
7245 "{\n"
7246 "check_single_selection(other_value);\n"
7247 "clean_up();\n"
7248 "set_selection(other_value);\n"
7249 "return *this;\n"
7250 "}\n\n", name, name);
7251
7252 /* assignment operator <- value */
7253 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
7254 name, name);
7255 src = mputprintf(src,
7256 "%s_template& %s_template::operator=(const %s& other_value)\n"
7257 "{\n"
7258 "clean_up();\n"
7259 "copy_value(&other_value);\n"
7260 "return *this;\n"
7261 "}\n\n", name, name, name);
7262
7263 /* assignment operator <- optional value */
7264 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
7265 "other_value);\n", name, name);
7266 src = mputprintf(src,
7267 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
7268 "{\n"
7269 "clean_up();\n"
7270 "copy_optional(&other_value);\n"
7271 "return *this;\n"
7272 "}\n\n", name, name, name);
7273
7274 /* assignment operator <- template*/
7275 def = mputprintf(def,
7276 "%s_template& operator=(const %s_template& other_value);\n",
7277 name, name);
7278 src = mputprintf(src,
7279 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
7280 "{\n"
7281 "if (&other_value != this) {\n"
7282 "clean_up();\n"
7283 "copy_template(other_value);\n"
7284 "}\n"
7285 "return *this;\n"
7286 "}\n\n", name, name, name);
7287
7288 if (sdef->nElements==0) {
7289 /* assignment op for value {} */
7290 def = mputprintf(def, "%s_template& operator=(null_type other_value);\n",
7291 name);
7292 src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n"
7293 "{\n"
7294 "clean_up();\n"
7295 "set_selection(SPECIFIC_VALUE);\n"
7296 "return *this;\n"
7297 "}\n\n", name, name);
7298 }
7299
7300 /* match operation (template matching) */
3abe9331 7301 def = mputprintf(def, "inline boolean match(const %s& other_value, "
7302 "boolean legacy = FALSE) const "
7303 "{ return matchv(&other_value, legacy); }\n", name);
970ed795
EL
7304
7305 /* log_match */
3abe9331 7306 def = mputprintf(def, "inline void log_match(const %s& match_value, "
7307 "boolean legacy = FALSE) const "
7308 "{ log_matchv(&match_value, legacy); }\n", name);
970ed795
EL
7309
7310 /* valueof operation */
7311 def = mputprintf(def, "%s valueof() const;\n", name);
7312
7313 src = mputprintf(src, "%s %s_template::valueof() const\n"
7314 "{\n"
7315 "%s ret_val;\n"
7316 "valueofv(&ret_val);\n"
7317 "return ret_val;\n"
7318 "}\n\n", name, name, name);
7319
7320 /* list_item(int) function */
7321
7322 def = mputprintf(def,
7323 "inline %s_template& list_item(unsigned int list_index) const "
7324 "{ return *(static_cast<%s_template*>(get_list_item(list_index))); }\n", name, name);
7325
7326 if (sdef->nElements>0) {
7327 /* template field access functions (non-const & const) */
7328 for (i = 0; i < sdef->nElements; i++) {
7329 def = mputprintf(def,
7330 "%s_template& %s();\n"
7331 "const %s_template& %s() const;\n",
7332 sdef->elements[i].type, sdef->elements[i].name,
7333 sdef->elements[i].type, sdef->elements[i].name);
7334 src = mputprintf(src,
7335 "%s_template& %s_template::%s() { return *(static_cast<%s_template*>(get_at(%d))); }\n"
7336 "const %s_template& %s_template::%s() const { return *(static_cast<const %s_template*>(get_at(%d))); }\n",
7337 sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i,
7338 sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i);
7339 }
7340 }
7341
7342 /* virtual functions */
7343 def = mputprintf(def,
7344 "%s* create() const { return new %s_template; }\n"
7345 "const TTCN_Typedescriptor_t* get_descriptor() const;\n",
7346 base_class, name);
7347 src = mputprintf(src,
7348 "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const { return &%s_descr_; }\n",
7349 name, name);
7350
7351 if (sdef->nElements>0) {
7352 def = mputprintf(def, "const char* fld_name(int p_index) const;\n");
7353 src = mputprintf(src,
7354 "const char* %s_template::fld_name(int p_index) const { return %s::fld_names[p_index]; }\n",
7355 name, name);
7356 }
7357
7358 def = mputstr(def, "};\n\n");
7359
7360 output->header.class_defs = mputstr(output->header.class_defs, def);
7361 Free(def);
7362
7363 output->source.methods = mputstr(output->source.methods, src);
7364 Free(src);
7365}
7366
This page took 0.342944 seconds and 5 git commands to generate.