Commit | Line | Data |
---|---|---|
970ed795 EL |
1 | /////////////////////////////////////////////////////////////////////////////// |
2 | // Copyright (c) 2000-2014 Ericsson Telecom AB | |
3 | // All rights reserved. This program and the accompanying materials | |
4 | // are made available under the terms of the Eclipse Public License v1.0 | |
5 | // which accompanies this distribution, and is available at | |
6 | // http://www.eclipse.org/legal/epl-v10.html | |
7 | /////////////////////////////////////////////////////////////////////////////// | |
8 | #include <string.h> | |
9 | #include "datatypes.h" | |
10 | #include "../common/memory.h" | |
11 | #include "record.h" | |
12 | #include "encdec.h" | |
13 | ||
14 | #include "main.hh" | |
15 | #include "error.h" | |
16 | #include "ttcn3/compiler.h" | |
17 | ||
18 | static void defEmptyRecordClass(const struct_def *sdef, | |
19 | output_struct *output); | |
20 | ||
21 | static void defEmptyRecordTemplate(const char *name, const char *dispname, | |
22 | output_struct *output); | |
23 | ||
24 | /** this is common code for both empty and non-empty cases, called from | |
25 | * both functions for template generation */ | |
26 | static void defCommonRecordTemplate(const char *name, | |
27 | char **def, char **src); | |
28 | ||
29 | /** code generation for original runtime */ | |
30 | static void defRecordClass1(const struct_def *sdef, output_struct *output); | |
31 | static void defRecordTemplate1(const struct_def *sdef, output_struct *output); | |
32 | /** code generation for alternative runtime (TITAN_RUNTIME_2) */ | |
33 | static void defRecordClass2(const struct_def *sdef, output_struct *output); | |
34 | static void defRecordTemplate2(const struct_def *sdef, output_struct *output); | |
35 | ||
36 | void defRecordClass(const struct_def *sdef, output_struct *output) | |
37 | { | |
38 | if (use_runtime_2) defRecordClass2(sdef, output); | |
39 | else defRecordClass1(sdef, output); | |
40 | } | |
41 | ||
42 | void defRecordTemplate(const struct_def *sdef, output_struct *output) | |
43 | { | |
44 | if (use_runtime_2) defRecordTemplate2(sdef, output); | |
45 | else defRecordTemplate1(sdef, output); | |
46 | } | |
47 | ||
48 | struct raw_option_struct { | |
49 | boolean lengthto; /* indicates whether this field contains a length */ | |
50 | int lengthof; /* how many length indicators this field counted in */ | |
51 | int *lengthoffield; /* the list of length indicator field indices */ | |
52 | boolean pointerto; | |
53 | int pointerof; | |
54 | boolean ptrbase; | |
55 | int extbitgroup; | |
56 | int tag_type; | |
57 | boolean delayed_decode; /* indicates whether the field has to be decoded | |
58 | out of order (later) */ | |
59 | int nof_dependent_fields; /* list of fields that are to be decoded */ | |
60 | int *dependent_fields; /* after this field */ | |
61 | }; | |
62 | ||
63 | static char *genRawFieldDecodeLimit(char *src, const struct_def *sdef, | |
64 | int i, const struct raw_option_struct *raw_options); | |
65 | ||
66 | static char *genRawDecodeRecordField(char *src, const struct_def *sdef, | |
67 | int i, const struct raw_option_struct *raw_options, boolean delayed_decode, | |
68 | int *prev_ext_group); | |
69 | ||
70 | static void set_raw_options(const struct_def *sdef, | |
71 | struct raw_option_struct *raw_options, boolean* haslengthto, | |
72 | boolean* haspointer, boolean* hascrosstag, boolean* has_ext_bit); | |
73 | ||
74 | static char *generate_raw_coding(char *src, | |
75 | const struct_def *sdef, struct raw_option_struct *raw_options, | |
76 | boolean haspointer, boolean hascrosstag, boolean has_ext_bit); | |
77 | static char *generate_raw_coding_negtest(char *src, | |
78 | const struct_def *sdef, struct raw_option_struct *raw_options); | |
79 | ||
80 | void set_raw_options(const struct_def *sdef, | |
81 | struct raw_option_struct *raw_options, boolean *haslengthto, | |
82 | boolean *haspointer, boolean *hascrosstag, boolean *has_ext_bit) | |
83 | { | |
84 | int i; | |
85 | for (i = 0; i < sdef->nElements; i++) { | |
86 | raw_options[i].lengthto = FALSE; | |
87 | raw_options[i].lengthof = 0; | |
88 | raw_options[i].lengthoffield = NULL; | |
89 | raw_options[i].pointerto = FALSE; | |
90 | raw_options[i].pointerof = 0; | |
91 | raw_options[i].ptrbase = FALSE; | |
92 | raw_options[i].extbitgroup = 0; | |
93 | raw_options[i].tag_type = 0; | |
94 | raw_options[i].delayed_decode = FALSE; | |
95 | raw_options[i].nof_dependent_fields = 0; | |
96 | raw_options[i].dependent_fields = NULL; | |
97 | } | |
98 | *haslengthto = FALSE; | |
99 | *haspointer = FALSE; | |
100 | *hascrosstag = FALSE; | |
101 | *has_ext_bit = sdef->hasRaw && sdef->raw.extension_bit!=XDEFNO && | |
102 | sdef->raw.extension_bit!=XDEFDEFAULT; | |
103 | for(i=0;i<sdef->nElements;i++){ | |
104 | if(sdef->elements[i].hasRaw && | |
105 | sdef->elements[i].raw.crosstaglist.nElements){ | |
106 | *hascrosstag = TRUE; | |
107 | break; | |
108 | } | |
109 | } | |
110 | if(sdef->hasRaw){ /* fill tag_type. 0-No tag, >0 index of the tag + 1 */ | |
111 | for(i=0;i<sdef->raw.taglist.nElements;i++){ | |
112 | raw_options[sdef->raw.taglist.list[i].fieldnum].tag_type= i+1; | |
113 | } | |
114 | for(i=0;i<sdef->raw.ext_bit_goup_num;i++){ | |
115 | int k; | |
116 | for(k=sdef->raw.ext_bit_groups[i].from; | |
117 | k<=sdef->raw.ext_bit_groups[i].to;k++) | |
118 | raw_options[k].extbitgroup=i+1; | |
119 | } | |
120 | } | |
121 | for(i=0;i<sdef->nElements;i++){ | |
122 | if (sdef->elements[i].hasRaw && sdef->elements[i].raw.lengthto_num > 0) { | |
123 | int j; | |
124 | *haslengthto = TRUE; | |
125 | raw_options[i].lengthto = TRUE; | |
126 | for(j = 0; j < sdef->elements[i].raw.lengthto_num; j++) { | |
127 | int field_index = sdef->elements[i].raw.lengthto[j]; | |
128 | raw_options[field_index].lengthoffield = (int*) | |
129 | Realloc(raw_options[field_index].lengthoffield, | |
130 | (raw_options[field_index].lengthof + 1) * sizeof(int)); | |
131 | raw_options[field_index].lengthoffield[ | |
132 | raw_options[field_index].lengthof] = i; | |
133 | raw_options[field_index].lengthof++; | |
134 | } | |
135 | } | |
136 | if(sdef->elements[i].hasRaw && sdef->elements[i].raw.pointerto!=-1){ | |
137 | raw_options[i].pointerto = TRUE; | |
138 | raw_options[sdef->elements[i].raw.pointerto].pointerof=i+1; | |
139 | *haspointer = TRUE; | |
140 | raw_options[sdef->elements[i].raw.pointerbase].ptrbase = TRUE; | |
141 | } | |
142 | } | |
143 | if (sdef->kind == RECORD && *hascrosstag) { | |
144 | /* looking for fields that require delayed decoding because of | |
145 | forward references in CROSSTAG */ | |
146 | for (i = 0; i < sdef->nElements; i++) { | |
147 | int j; | |
148 | /* we are looking for a field index that is greater than i */ | |
149 | size_t max_index = i; | |
150 | if (!sdef->elements[i].hasRaw) continue; | |
151 | for (j = 0; j < sdef->elements[i].raw.crosstaglist.nElements; j++) { | |
152 | int k; | |
153 | rawAST_coding_taglist *crosstag = | |
154 | sdef->elements[i].raw.crosstaglist.list + j; | |
155 | for (k = 0; k < crosstag->nElements; k++) { | |
156 | rawAST_coding_field_list *keyid = crosstag->fields + k; | |
157 | if (keyid->nElements >= 1) { | |
158 | int field_index = keyid->fields[0].nthfield; | |
159 | if (field_index > max_index) max_index = field_index; | |
160 | } | |
161 | } | |
162 | } | |
163 | if (max_index > i) { | |
164 | raw_options[i].delayed_decode = TRUE; | |
165 | raw_options[max_index].nof_dependent_fields++; | |
166 | raw_options[max_index].dependent_fields = (int*) | |
167 | Realloc(raw_options[max_index].dependent_fields, | |
168 | raw_options[max_index].nof_dependent_fields * | |
169 | sizeof(*raw_options[max_index].dependent_fields)); | |
170 | raw_options[max_index].dependent_fields[ | |
171 | raw_options[max_index].nof_dependent_fields - 1] = i; | |
172 | } | |
173 | } | |
174 | } | |
175 | } | |
176 | ||
177 | char* generate_raw_coding(char* src, | |
178 | const struct_def *sdef, struct raw_option_struct *raw_options, | |
179 | boolean haspointer, boolean hascrosstag, boolean has_ext_bit) | |
180 | { | |
181 | int i; | |
182 | const char *name = sdef->name; | |
183 | ||
184 | if (sdef->kind == SET) { /* set decoder start */ | |
185 | size_t mand_num = 0; | |
186 | for (i = 0; i < sdef->nElements; i++) { | |
187 | if (!sdef->elements[i].isOptional) mand_num++; | |
188 | } | |
189 | src = mputprintf(src, "int %s::RAW_decode(const TTCN_Typedescriptor_t& " | |
190 | "p_td, TTCN_Buffer& p_buf, int limit, raw_order_t top_bit_ord, " | |
191 | "boolean, int, boolean)\n" | |
192 | "{\n" | |
193 | "bound_flag = TRUE;\n" | |
194 | "int prepaddlength = p_buf.increase_pos_padd(p_td.raw->prepadding);\n" | |
195 | "limit -= prepaddlength;\n" | |
196 | "int decoded_length = 0;\n" | |
197 | "int field_map[%lu];\n" | |
198 | "memset(field_map, 0, sizeof(field_map));\n", | |
199 | name, (unsigned long) sdef->nElements); | |
200 | if (mand_num > 0) | |
201 | src = mputstr(src, "size_t nof_mand_fields = 0;\n"); | |
202 | for (i = 0; i < sdef->nElements; i++) { | |
203 | if (sdef->elements[i].isOptional) | |
204 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
205 | sdef->elements[i].name); | |
206 | } | |
207 | src = mputstr(src, | |
208 | "raw_order_t local_top_order;\n" | |
209 | "if (p_td.raw->top_bit_order == TOP_BIT_INHERITED) " | |
210 | "local_top_order = top_bit_ord;\n" | |
211 | "else if (p_td.raw->top_bit_order == TOP_BIT_RIGHT) " | |
212 | "local_top_order = ORDER_MSB;\n" | |
213 | "else local_top_order = ORDER_LSB;\n" | |
214 | "while (limit > 0) {\n" | |
215 | "size_t fl_start_pos = p_buf.get_pos_bit();\n" | |
216 | ); | |
217 | for (i = 0; i < sdef->nElements; i++) { /* decoding fields with tag */ | |
218 | if (raw_options[i].tag_type && | |
219 | sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements > 0) { | |
220 | rawAST_coding_taglist* cur_choice = | |
221 | sdef->raw.taglist.list + raw_options[i].tag_type - 1; | |
222 | size_t j; | |
223 | boolean has_fixed = FALSE, has_variable = FALSE, flag_needed = FALSE; | |
224 | for (j = 0; j < cur_choice->nElements; j++) { | |
225 | if (cur_choice->fields[j].start_pos >= 0) { | |
226 | if (has_fixed || has_variable) flag_needed = TRUE; | |
227 | has_fixed = TRUE; | |
228 | } else { | |
229 | if (has_fixed) flag_needed = TRUE; | |
230 | has_variable = TRUE; | |
231 | } | |
232 | if (has_fixed && has_variable) break; | |
233 | } | |
234 | src = mputprintf(src, "if (field_map[%lu] == 0) {\n", | |
235 | (unsigned long) i); | |
236 | if (flag_needed) | |
237 | src = mputstr(src, "boolean already_failed = FALSE;\n"); | |
238 | if (has_fixed) { | |
239 | /* first check the fields we can precode | |
240 | * try to decode those key variables whose position we know | |
241 | * this way we might be able to step over bad values faster | |
242 | */ | |
243 | boolean first_fixed = TRUE; | |
244 | src = mputstr(src, "raw_order_t temporal_top_order;\n" | |
245 | "int temporal_decoded_length;\n"); | |
246 | for (j = 0; j < cur_choice->nElements; j++) { | |
247 | size_t k; | |
248 | rawAST_coding_field_list *cur_field_list = cur_choice->fields + j; | |
249 | if (cur_field_list->start_pos < 0) continue; | |
250 | if (!first_fixed) src = mputstr(src, "if (!already_failed) {\n"); | |
251 | for (k = cur_field_list->nElements - 1; k > 0; k--) { | |
252 | src = mputprintf(src, "if (%s_descr_.raw->top_bit_order == " | |
253 | "TOP_BIT_RIGHT) temporal_top_order = ORDER_MSB;\n" | |
254 | "else if (%s_descr_.raw->top_bit_order == TOP_BIT_LEFT) " | |
255 | "temporal_top_order = ORDER_LSB;\n" | |
256 | "else ", cur_field_list->fields[k - 1].typedescr, | |
257 | cur_field_list->fields[k - 1].typedescr); | |
258 | } | |
259 | src = mputprintf(src, "temporal_top_order = top_bit_ord;\n" | |
260 | "%s temporal_%lu;\n" | |
261 | "p_buf.set_pos_bit(fl_start_pos + %d);\n" | |
262 | "temporal_decoded_length = temporal_%lu.RAW_decode(%s_descr_, " | |
263 | "p_buf, limit, temporal_top_order, TRUE);\n" | |
264 | "p_buf.set_pos_bit(fl_start_pos);\n" | |
265 | "if (temporal_decoded_length > 0 && temporal_%lu == %s) {\n" | |
266 | "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, " | |
267 | "p_buf, limit, local_top_order, TRUE);\n" | |
268 | "if (decoded_field_length %s 0 && (", | |
269 | cur_field_list->fields[cur_field_list->nElements - 1].type, | |
270 | (unsigned long) j, cur_field_list->start_pos, (unsigned long) j, | |
271 | cur_field_list->fields[cur_field_list->nElements - 1].typedescr, | |
272 | (unsigned long) j, cur_field_list->value, | |
273 | sdef->elements[i].name, | |
274 | sdef->elements[i].isOptional ? "()" : "", | |
275 | sdef->elements[i].typedescrname, | |
276 | sdef->elements[i].isOptional ? ">" : ">="); | |
277 | src = genRawFieldChecker(src, cur_choice, TRUE); | |
278 | src = mputstr(src, ")) {\n" | |
279 | "decoded_length += decoded_field_length;\n" | |
280 | "limit -= decoded_field_length;\n"); | |
281 | if (!sdef->elements[i].isOptional) | |
282 | src = mputstr(src, "nof_mand_fields++;\n"); | |
283 | src = mputprintf(src, "field_map[%lu] = 1;\n" | |
284 | "continue;\n" | |
285 | "} else {\n" | |
286 | "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i); | |
287 | if (sdef->elements[i].isOptional) | |
288 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
289 | sdef->elements[i].name); | |
290 | if (flag_needed) src = mputstr(src, "already_failed = TRUE;\n"); | |
291 | src = mputstr(src, "}\n" | |
292 | "}\n"); | |
293 | if (first_fixed) first_fixed = FALSE; | |
294 | else src = mputstr(src, "}\n"); | |
295 | } | |
296 | } | |
297 | if (has_variable) { | |
298 | /* if there is one tag key whose position we don't know | |
299 | * and we couldn't decide yet if element can be decoded or not | |
300 | * than we have to decode it. | |
301 | */ | |
302 | if (flag_needed) src = mputstr(src, "if (!already_failed) {\n"); | |
303 | src = mputprintf(src, "int decoded_field_length = " | |
304 | "field_%s%s.RAW_decode(%s_descr_, p_buf, limit, " | |
305 | "local_top_order, TRUE);\n" | |
306 | "if (decoded_field_length %s 0 && (", | |
307 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
308 | sdef->elements[i].typedescrname, | |
309 | sdef->elements[i].isOptional ? ">" : ">="); | |
310 | src = genRawFieldChecker(src, cur_choice, TRUE); | |
311 | src = mputstr(src, ")) {\n" | |
312 | "decoded_length += decoded_field_length;\n" | |
313 | "limit -= decoded_field_length;\n"); | |
314 | if (!sdef->elements[i].isOptional) | |
315 | src = mputstr(src, "nof_mand_fields++;\n"); | |
316 | src = mputprintf(src, "field_map[%lu] = 1;\n" | |
317 | "continue;\n" | |
318 | "} else {\n" | |
319 | "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i); | |
320 | if (sdef->elements[i].isOptional) | |
321 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
322 | sdef->elements[i].name); | |
323 | src = mputstr(src, "}\n"); | |
324 | if (flag_needed) src = mputstr(src, "}\n"); | |
325 | } | |
326 | src = mputstr(src, "}\n"); | |
327 | } | |
328 | } | |
329 | for (i = 0; i < sdef->nElements; i++) { | |
330 | /* decoding fields without TAG */ | |
331 | if (!raw_options[i].tag_type) { | |
332 | boolean repeatable; | |
333 | if (sdef->elements[i].of_type && sdef->elements[i].hasRaw && | |
334 | sdef->elements[i].raw.repeatable == XDEFYES) repeatable = TRUE; | |
335 | else { | |
336 | repeatable = FALSE; | |
337 | src = mputprintf(src, "if (field_map[%lu] == 0) ", | |
338 | (unsigned long) i); | |
339 | } | |
340 | src = mputprintf(src, "{\n" | |
341 | "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, " | |
342 | "p_buf, limit, local_top_order, TRUE", | |
343 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
344 | sdef->elements[i].typedescrname); | |
345 | if (repeatable) | |
346 | src = mputprintf(src, ", -1, field_map[%lu] == 0", | |
347 | (unsigned long) i); | |
348 | src = mputprintf(src, ");\n" | |
349 | "if (decoded_field_length %s 0) {\n" | |
350 | "decoded_length += decoded_field_length;\n" | |
351 | "limit -= decoded_field_length;\n", | |
352 | sdef->elements[i].isOptional ? ">" : ">="); | |
353 | if (repeatable) { | |
354 | if (!sdef->elements[i].isOptional) src = mputprintf(src, | |
355 | "if (field_map[%lu] == 0) nof_mand_fields++;\n", | |
356 | (unsigned long) i); | |
357 | src = mputprintf(src, "field_map[%lu]++;\n", (unsigned long) i); | |
358 | } else { | |
359 | if (!sdef->elements[i].isOptional) | |
360 | src = mputstr(src, "nof_mand_fields++;\n"); | |
361 | src = mputprintf(src, "field_map[%lu] = 1;\n", (unsigned long) i); | |
362 | } | |
363 | src = mputstr(src, "continue;\n" | |
364 | "} else {\n" | |
365 | "p_buf.set_pos_bit(fl_start_pos);\n"); | |
366 | if (sdef->elements[i].isOptional) { | |
367 | if (repeatable) | |
368 | src = mputprintf(src, "if (field_map[%lu] == 0) ", | |
369 | (unsigned long) i); | |
370 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
371 | sdef->elements[i].name); | |
372 | } | |
373 | src = mputstr(src, "}\n" | |
374 | "}\n"); | |
375 | } | |
376 | } | |
377 | for (i = 0; i < sdef->nElements; i++){ | |
378 | /* decoding fields with tag OTHERWISE */ | |
379 | if (raw_options[i].tag_type && | |
380 | sdef->raw.taglist.list[raw_options[i].tag_type-1].nElements == 0) { | |
381 | src = mputprintf(src, "if (field_map[%lu] == 0) {\n" | |
382 | "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, " | |
383 | "p_buf, limit, local_top_order, TRUE);\n" | |
384 | "if (decoded_field_length %s 0) {\n" | |
385 | "decoded_length += decoded_field_length;\n" | |
386 | "limit -= decoded_field_length;\n", (unsigned long) i, | |
387 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
388 | sdef->elements[i].typedescrname, | |
389 | sdef->elements[i].isOptional ? ">" : ">="); | |
390 | if (!sdef->elements[i].isOptional) | |
391 | src = mputstr(src, "nof_mand_fields++;\n"); | |
392 | src = mputprintf(src, "field_map[%lu] = 1;\n" | |
393 | "continue;\n" | |
394 | "} else {\n" | |
395 | "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i); | |
396 | if (sdef->elements[i].isOptional) | |
397 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
398 | sdef->elements[i].name); | |
399 | src = mputstr(src, "}\n" | |
400 | "}\n"); | |
401 | } | |
402 | } | |
403 | src = mputstr(src, "break;\n" /* no field decoded successfully, quit */ | |
404 | "}\n"); | |
405 | if (mand_num > 0) src = mputprintf(src, | |
406 | "if (nof_mand_fields != %lu) return limit ? -1 : -TTCN_EncDec::ET_INCOMPL_MSG;\n", | |
407 | (unsigned long) mand_num); | |
408 | /* If not all required fields were decoded and there are no bits left, | |
409 | * that means that the last field was decoded successfully but used up | |
410 | * the buffer. Signal "incomplete". If there were bits left, that means that | |
411 | * no field could be decoded from them; signal an error. | |
412 | */ | |
413 | src = mputstr(src, "return decoded_length + prepaddlength + " | |
414 | "p_buf.increase_pos_padd(p_td.raw->padding);\n" | |
415 | "}\n\n"); | |
416 | } else { | |
417 | /* set decoder end, record decoder start */ | |
418 | int prev_ext_group = 0; | |
419 | src = mputprintf(src, | |
420 | "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, " | |
421 | "TTCN_Buffer& p_buf, int limit, raw_order_t top_bit_ord, boolean no_err, " | |
422 | "int, boolean)\n" | |
423 | "{ (void)no_err;\n" | |
424 | " bound_flag = TRUE;\n" | |
425 | " int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n" | |
426 | " limit-=prepaddlength;\n" | |
427 | " size_t last_decoded_pos = p_buf.get_pos_bit();\n" | |
428 | " int decoded_length = 0;\n" | |
429 | " int decoded_field_length = 0;\n" | |
430 | " raw_order_t local_top_order;\n" | |
431 | , name); | |
432 | if (hascrosstag) { | |
433 | src = mputstr(src, " int selected_field = -1;\n"); | |
434 | } | |
435 | if (sdef->raw.ext_bit_goup_num) { | |
436 | src=mputstr(src, " int group_limit = 0;\n"); | |
437 | } | |
438 | src=mputstr(src, | |
439 | " if(p_td.raw->top_bit_order==TOP_BIT_INHERITED)" | |
440 | "local_top_order=top_bit_ord;\n" | |
441 | " else if(p_td.raw->top_bit_order==TOP_BIT_RIGHT)local_top_order" | |
442 | "=ORDER_MSB;\n" | |
443 | " else local_top_order=ORDER_LSB;\n" | |
444 | ); | |
445 | if(has_ext_bit){ | |
446 | src=mputstr(src, | |
447 | " {\n" | |
448 | " cbyte* data=p_buf.get_read_data();\n" | |
449 | " int count=1;\n" | |
450 | " unsigned mask = 1 << (local_top_order==ORDER_LSB ? 0 : 7);\n" | |
451 | " if(p_td.raw->extension_bit==EXT_BIT_YES){\n" | |
452 | " while((data[count-1] & mask)==0 && count*8<(int)limit) count++;\n" | |
453 | " }\n" | |
454 | " else{\n" | |
455 | " while((data[count-1] & mask)!=0 && count*8<(int)limit) count++;\n" | |
456 | " }\n" | |
457 | " if(limit) limit=count*8;\n" | |
458 | " }\n" | |
459 | ); | |
460 | } | |
461 | if(haspointer) | |
462 | src=mputstr(src, | |
463 | " int end_of_available_data=last_decoded_pos+limit;\n"); | |
464 | for(i=0;i<sdef->nElements;i++){ | |
465 | if(raw_options[i].pointerof) | |
466 | src=mputprintf(src, | |
467 | " int start_of_field%lu=-1;\n" | |
468 | ,(unsigned long) i | |
469 | ); | |
470 | if(raw_options[i].ptrbase) | |
471 | src=mputprintf(src, | |
472 | " int start_pos_of_field%lu=-1;\n" | |
473 | ,(unsigned long) i | |
474 | ); | |
475 | if(raw_options[i].lengthto) | |
476 | src=mputprintf(src, | |
477 | " int value_of_length_field%lu = 0;\n" | |
478 | ,(unsigned long) i | |
479 | ); | |
480 | } | |
481 | for(i=0;i<sdef->nElements;i++){ /* decoding fields */ | |
482 | if (raw_options[i].delayed_decode) { | |
483 | int j; | |
484 | /* checking whether there are enough bits in the buffer to decode | |
485 | the field */ | |
486 | src = mputstr(src, " if ("); | |
487 | src = genRawFieldDecodeLimit(src, sdef, i, raw_options); | |
488 | src = mputprintf(src, " < %d) return -TTCN_EncDec::ET_LEN_ERR;\n", | |
489 | sdef->elements[i].raw.length); | |
490 | /* skipping over the field that has to be decoded later because of | |
491 | forward referencing in CROSSTAG */ | |
492 | src = mputprintf(src, | |
493 | " size_t start_of_field%lu = p_buf.get_pos_bit();\n" | |
494 | " p_buf.set_pos_bit(start_of_field%lu + %d);\n" | |
495 | " decoded_length += %d;\n" | |
496 | " last_decoded_pos += %d;\n" | |
497 | " limit -= %d;\n", | |
498 | (unsigned long) i, (unsigned long) i, sdef->elements[i].raw.length, | |
499 | sdef->elements[i].raw.length, | |
500 | sdef->elements[i].raw.length, sdef->elements[i].raw.length); | |
501 | for (j = 0; j < raw_options[i].lengthof; j++) { | |
502 | src = mputprintf(src, | |
503 | " value_of_length_field%d -= %d;\n", | |
504 | raw_options[i].lengthoffield[j], sdef->elements[i].raw.length); | |
505 | } | |
506 | } else { | |
507 | src = genRawDecodeRecordField(src, sdef, i, raw_options, FALSE, | |
508 | &prev_ext_group); | |
509 | if (raw_options[i].nof_dependent_fields > 0) { | |
510 | int j; | |
511 | for (j = 0; j < raw_options[i].nof_dependent_fields; j++) { | |
512 | int dependent_field_index = raw_options[i].dependent_fields[j]; | |
513 | /* seek to the beginning of the dependent field */ | |
514 | src = mputprintf(src, | |
515 | " p_buf.set_pos_bit(start_of_field%d);\n", | |
516 | dependent_field_index); | |
517 | /* decode the dependent field */ | |
518 | src = genRawDecodeRecordField(src, sdef, dependent_field_index, | |
519 | raw_options, TRUE, &prev_ext_group); | |
520 | } | |
521 | if (i < sdef->nElements - 1) { | |
522 | /* seek back if there are more regular fields to decode */ | |
523 | src = mputstr(src, | |
524 | " p_buf.set_pos_bit(last_decoded_pos);\n"); | |
525 | } | |
526 | } | |
527 | } | |
528 | } /* decoding fields*/ | |
529 | ||
530 | if(sdef->hasRaw && sdef->raw.presence.nElements > 0) | |
531 | { | |
532 | src = mputstr(src, " if ("); | |
533 | src = genRawFieldChecker(src, &sdef->raw.presence, FALSE); | |
534 | src = mputstr(src, ") return -1;\n"); | |
535 | } | |
536 | ||
537 | src=mputstr(src, | |
538 | " p_buf.set_pos_bit(last_decoded_pos);\n" | |
539 | " return decoded_length+prepaddlength+" | |
540 | "p_buf.increase_pos_padd(p_td.raw->padding);\n}\n\n"); | |
541 | } /* record decoder end */ | |
542 | ||
543 | src = mputprintf(src, /* encoder */ | |
544 | "int %s::RAW_encode(const TTCN_Typedescriptor_t&%s, " | |
545 | "RAW_enc_tree& myleaf) const {\n", name, | |
546 | use_runtime_2 ? " p_td" : ""); | |
547 | if (use_runtime_2) { | |
548 | src = mputstr(src, " if (err_descr) return RAW_encode_negtest(err_descr, p_td, myleaf);\n"); | |
549 | } | |
550 | src = mputprintf(src, | |
551 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
552 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
553 | " int encoded_length = 0;\n" | |
554 | " myleaf.isleaf = false;\n" | |
555 | " myleaf.body.node.num_of_nodes = %lu;\n" | |
556 | " myleaf.body.node.nodes = init_nodes_of_enc_tree(%lu);\n", | |
557 | (unsigned long)sdef->nElements, (unsigned long)sdef->nElements); | |
558 | /* init nodes */ | |
559 | for (i = 0; i < sdef->nElements; i++) { | |
560 | if (sdef->elements[i].isOptional) { | |
561 | src = mputprintf(src, | |
562 | " if (field_%s.ispresent()) {\n", sdef->elements[i].name); | |
563 | } | |
564 | src = mputprintf(src, | |
565 | " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(true, &myleaf, " | |
566 | "&(myleaf.curr_pos), %lu, %s_descr_.raw);\n", | |
567 | (unsigned long)i, (unsigned long)i, sdef->elements[i].typedescrname); | |
568 | if (sdef->elements[i].isOptional) { | |
569 | src = mputprintf(src, | |
570 | " }\n" | |
571 | " else myleaf.body.node.nodes[%lu] = NULL;\n", (unsigned long)i); | |
572 | } | |
573 | } | |
574 | for (i = 0; i < sdef->raw.ext_bit_goup_num; i++) { | |
575 | if (sdef->raw.ext_bit_groups[i].ext_bit != XDEFNO) { | |
576 | src = mputprintf(src, | |
577 | " {\n" | |
578 | " int node_idx = %d;\n" | |
579 | " while (node_idx <= %d && myleaf.body.node.nodes[node_idx] == NULL) node_idx++;\n" | |
580 | " if (myleaf.body.node.nodes[node_idx]) {\n" | |
581 | " myleaf.body.node.nodes[node_idx]->ext_bit_handling = 1;\n" | |
582 | " myleaf.body.node.nodes[node_idx]->ext_bit = %s;\n }\n" | |
583 | " node_idx = %d;\n" | |
584 | " while (node_idx >= %d && myleaf.body.node.nodes[node_idx] == NULL) node_idx--;\n" | |
585 | " if (myleaf.body.node.nodes[node_idx]) myleaf.body.node.nodes[node_idx]" | |
586 | "->ext_bit_handling += 2;\n" | |
587 | " }\n", | |
588 | sdef->raw.ext_bit_groups[i].from, | |
589 | sdef->raw.ext_bit_groups[i].to, | |
590 | sdef->raw.ext_bit_groups[i].ext_bit == XDEFYES ? "EXT_BIT_YES" : "EXT_BIT_REVERSE", | |
591 | sdef->raw.ext_bit_groups[i].to, | |
592 | sdef->raw.ext_bit_groups[i].from); | |
593 | } | |
594 | } | |
595 | for (i = 0; i < sdef->nElements; i++) { | |
596 | /* encoding fields */ | |
597 | if (sdef->elements[i].isOptional) { | |
598 | src = mputprintf(src, | |
599 | " if (field_%s.ispresent()) {\n", sdef->elements[i].name); | |
600 | } | |
601 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex == NULL | |
602 | && sdef->elements[i].raw.union_member_num == 0) { | |
603 | /* encoding of lenghto fields */ | |
604 | int a; | |
605 | src = mputprintf(src, | |
606 | " encoded_length += %d;\n" | |
607 | " myleaf.body.node.nodes[%lu]->calc = CALC_LENGTH;\n" | |
608 | " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n" | |
609 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.num_of_fields = %d;\n" | |
610 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.unit = %d;\n" | |
611 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields = " | |
612 | "init_lengthto_fields_list(%d);\n" | |
613 | " myleaf.body.node.nodes[%lu]->length = %d;\n", | |
614 | sdef->elements[i].raw.fieldlength, (unsigned long)i, | |
615 | (unsigned long)i, sdef->elements[i].typedescrname, | |
616 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
617 | (unsigned long)i, sdef->elements[i].raw.unit, | |
618 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
619 | (unsigned long)i, sdef->elements[i].raw.fieldlength); | |
620 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
621 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
622 | src = mputprintf(src, | |
623 | " if (field_%s.ispresent()) {\n", | |
624 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
625 | } | |
626 | src = mputprintf(src, | |
627 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].level = " | |
628 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
629 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].pos = " | |
630 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", | |
631 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a], | |
632 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]); | |
633 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
634 | src = mputprintf(src, | |
635 | " } else {\n" | |
636 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].level = 0;\n" | |
637 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].pos = 0;\n" | |
638 | " }\n", (unsigned long)i, a, (unsigned long)i, a); | |
639 | } | |
640 | } | |
641 | } else if (raw_options[i].pointerto) { | |
642 | /* encoding of pointerto fields */ | |
643 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { | |
644 | src = mputprintf(src, | |
645 | " if (field_%s.ispresent()) {\n", | |
646 | sdef->elements[sdef->elements[i].raw.pointerto].name); | |
647 | } | |
648 | src = mputprintf(src, | |
649 | " encoded_length += %d;\n" | |
650 | " myleaf.body.node.nodes[%lu]->calc = CALC_POINTER;\n" | |
651 | " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n" | |
652 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.unit = %d;\n" | |
653 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.ptr_offset = %d;\n" | |
654 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.ptr_base = %d;\n" | |
655 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.target.level = " | |
656 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
657 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.target.pos = " | |
658 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n" | |
659 | " myleaf.body.node.nodes[%lu]->length = %d;\n", | |
660 | sdef->elements[i].raw.fieldlength,(unsigned long)i, | |
661 | (unsigned long)i, sdef->elements[i].typedescrname, | |
662 | (unsigned long)i, sdef->elements[i].raw.unit, | |
663 | (unsigned long)i, sdef->elements[i].raw.ptroffset, | |
664 | (unsigned long)i, sdef->elements[i].raw.pointerbase, | |
665 | (unsigned long)i, sdef->elements[i].raw.pointerto, | |
666 | (unsigned long)i, sdef->elements[i].raw.pointerto, | |
667 | (unsigned long)i, sdef->elements[i].raw.fieldlength); | |
668 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { | |
669 | src = mputprintf(src, | |
670 | " } else {\n" | |
671 | " INTEGER atm;\n" | |
672 | " atm = 0;\n" | |
673 | " encoded_length += atm.RAW_encode(%s_descr_" | |
674 | ", *myleaf.body.node.nodes[%lu]);\n" | |
675 | " }\n", | |
676 | sdef->elements[i].typedescrname, (unsigned long)i); | |
677 | } | |
678 | } else { | |
679 | /* encoding of normal fields */ | |
680 | src = mputprintf(src, | |
681 | " encoded_length += field_%s%s.RAW_encode(%s_descr_" | |
682 | ", *myleaf.body.node.nodes[%lu]);\n", | |
683 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
684 | sdef->elements[i].typedescrname, (unsigned long)i); | |
685 | } | |
686 | if (sdef->elements[i].isOptional) { | |
687 | src = mputstr(src, " }\n"); | |
688 | } | |
689 | } | |
690 | for (i = 0; i < sdef->nElements; i++) { | |
691 | /* fill presence, tag and crosstag */ | |
692 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex) { | |
693 | /* encoding of lenghto fields */ | |
694 | int a; | |
695 | if (sdef->elements[i].isOptional) { | |
696 | src = mputprintf(src, | |
697 | " if (field_%s.ispresent()) {\n", | |
698 | sdef->elements[i].name); | |
699 | } | |
700 | src = mputprintf(src, | |
701 | " if (myleaf.body.node.nodes[%lu]->body.node.nodes[%d]) {\n" | |
702 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
703 | "calc = CALC_LENGTH;\n" | |
704 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
705 | "coding_descr = &%s_descr_;\n" | |
706 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
707 | "calcof.lengthto.num_of_fields = %d;\n" | |
708 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
709 | "calcof.lengthto.unit = %d;\n" | |
710 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
711 | "calcof.lengthto.fields = " | |
712 | "init_lengthto_fields_list(%d);\n", | |
713 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
714 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
715 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
716 | sdef->elements[i].raw.lengthindex->typedescr, | |
717 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
718 | sdef->elements[i].raw.lengthto_num, | |
719 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
720 | sdef->elements[i].raw.unit, | |
721 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
722 | sdef->elements[i].raw.lengthto_num); | |
723 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
724 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
725 | src = mputprintf(src, | |
726 | " if (field_%s.ispresent()) {\n", | |
727 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
728 | } | |
729 | src = mputprintf(src, | |
730 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]" | |
731 | "->calcof.lengthto.fields[%d].level = " | |
732 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
733 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]" | |
734 | "->calcof.lengthto.fields[%d].pos = " | |
735 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", | |
736 | (unsigned long)i,sdef->elements[i].raw.lengthindex->nthfield, | |
737 | a, sdef->elements[i].raw.lengthto[a], | |
738 | (unsigned long)i,sdef->elements[i].raw.lengthindex->nthfield, | |
739 | a, sdef->elements[i].raw.lengthto[a]); | |
740 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
741 | src = mputprintf(src, | |
742 | " } else {\n" | |
743 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
744 | "calcof.lengthto.fields[%d].level = 0;\n" | |
745 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
746 | "calcof.lengthto.fields[%d].pos = 0;\n" | |
747 | " }\n", | |
748 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a, | |
749 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a); | |
750 | } | |
751 | } | |
752 | src = mputstr(src, " }\n"); | |
753 | if (sdef->elements[i].isOptional) { | |
754 | src = mputstr(src, " }\n"); | |
755 | } | |
756 | } | |
757 | if (raw_options[i].lengthto && sdef->elements[i].raw.union_member_num) { | |
758 | /* encoding of lenghto fields */ | |
759 | int a; | |
760 | if (sdef->elements[i].isOptional) { | |
761 | src = mputprintf(src, | |
762 | " if (field_%s.ispresent()) ", sdef->elements[i].name); | |
763 | } | |
764 | ||
765 | src = mputprintf(src, | |
766 | " {\n" | |
767 | " int sel_field = 0;\n" | |
768 | " while (myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field] == NULL) " | |
769 | "{ sel_field++; }\n" | |
770 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" | |
771 | "calc = CALC_LENGTH;\n" | |
772 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" | |
773 | "calcof.lengthto.num_of_fields = %d;\n" | |
774 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" | |
775 | "calcof.lengthto.unit = %d;\n" | |
776 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" | |
777 | "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", | |
778 | (unsigned long)i,(unsigned long)i, | |
779 | (unsigned long)i,sdef->elements[i].raw.lengthto_num, | |
780 | (unsigned long)i,sdef->elements[i].raw.unit, | |
781 | (unsigned long)i,sdef->elements[i].raw.lengthto_num); | |
782 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
783 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
784 | src = mputprintf(src, | |
785 | " if (field_%s.ispresent()) {\n", | |
786 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
787 | } | |
788 | src = mputprintf(src, | |
789 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" | |
790 | "->calcof.lengthto.fields[%d].level = " | |
791 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
792 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" | |
793 | "->calcof.lengthto.fields[%d].pos = " | |
794 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", | |
795 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a], | |
796 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]); | |
797 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
798 | src = mputprintf(src, | |
799 | " }else{\n" | |
800 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" | |
801 | "->calcof.lengthto.fields[%d].level = 0;\n" | |
802 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" | |
803 | "->calcof.lengthto.fields[%d].pos = 0;\n" | |
804 | " }\n", | |
805 | (unsigned long)i, a, | |
806 | (unsigned long)i, a); | |
807 | } | |
808 | } | |
809 | src = mputstr(src, | |
810 | " }\n"); | |
811 | } | |
812 | if (raw_options[i].tag_type && sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements) { | |
813 | /* tag */ | |
814 | rawAST_coding_taglist *cur_choice = | |
815 | sdef->raw.taglist.list + raw_options[i].tag_type - 1; | |
816 | src = mputstr(src, " if ("); | |
817 | if (sdef->elements[i].isOptional) { | |
818 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); | |
819 | } | |
820 | src = genRawFieldChecker(src, cur_choice, FALSE); | |
821 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); | |
822 | src = mputstr(src,") {\n"); | |
823 | src = genRawTagChecker(src, cur_choice); | |
824 | src=mputstr(src," }\n"); | |
825 | } | |
826 | if (sdef->elements[i].hasRaw && sdef->elements[i].raw.presence.nElements) { | |
827 | /* presence */ | |
828 | src = mputstr(src, " if ("); | |
829 | if (sdef->elements[i].isOptional) { | |
830 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); | |
831 | } | |
832 | src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, FALSE); | |
833 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); | |
834 | src = mputstr(src, ") {\n"); | |
835 | src = genRawTagChecker(src, &sdef->elements[i].raw.presence); | |
836 | src = mputstr(src," }\n"); | |
837 | } | |
838 | if (sdef->elements[i].hasRaw && | |
839 | sdef->elements[i].raw.crosstaglist.nElements) { | |
840 | /* crosstag */ | |
841 | int a; | |
842 | if (sdef->elements[i].isOptional) { | |
843 | src = mputprintf(src, | |
844 | " if (field_%s.ispresent()) {\n", | |
845 | sdef->elements[i].name); | |
846 | } | |
847 | src = mputprintf(src, | |
848 | " switch (field_%s%s.get_selection()) {\n", | |
849 | sdef->elements[i].name,sdef->elements[i].isOptional ? "()" : ""); | |
850 | for (a = 0; a < sdef->elements[i].raw.crosstaglist.nElements; a++) { | |
851 | rawAST_coding_taglist *cur_choice = | |
852 | sdef->elements[i].raw.crosstaglist.list + a; | |
853 | if (cur_choice->nElements > 0) { | |
854 | src = mputprintf(src, " case %s%s%s:\n" | |
855 | " if (", sdef->elements[i].type, | |
856 | "::ALT_", cur_choice->fieldName); | |
857 | src = genRawFieldChecker(src, cur_choice, FALSE); | |
858 | src = mputstr(src, ") {\n"); | |
859 | if (!strcmp(cur_choice->fields[0].value, "OMIT_VALUE")) { | |
860 | if (cur_choice->fields[0].nElements != 1) | |
861 | NOTSUPP("omit value with multiple fields in CROSSTAG"); | |
862 | /* eliminating the corresponding encoded leaf, which will have | |
863 | the same effect as if the referred field had been omit */ | |
864 | src = mputprintf(src, | |
865 | " encoded_length -= myleaf.body.node.nodes[%d]->length;\n" | |
866 | " delete myleaf.body.node.nodes[%d];\n" | |
867 | " myleaf.body.node.nodes[%d] = NULL;\n", | |
868 | cur_choice->fields[0].fields[0].nthfield, | |
869 | cur_choice->fields[0].fields[0].nthfield, | |
870 | cur_choice->fields[0].fields[0].nthfield); | |
871 | } else { | |
872 | int ll; | |
873 | src = mputprintf(src, | |
874 | " RAW_enc_tr_pos pr_pos;\n" | |
875 | " pr_pos.level = myleaf.curr_pos.level + %d;\n" | |
876 | " int new_pos[] = { ", | |
877 | cur_choice->fields[0].nElements); | |
878 | for (ll = 0; ll < cur_choice->fields[0].nElements; ll++) { | |
879 | if (ll > 0) src = mputstr(src, ", "); | |
880 | src = mputprintf(src, "%d", | |
881 | cur_choice->fields[0].fields[ll].nthfield); | |
882 | } | |
883 | src = mputprintf(src, " };\n" | |
884 | " pr_pos.pos = init_new_tree_pos(myleaf.curr_pos, %d, " | |
885 | "new_pos);\n", | |
886 | cur_choice->fields[0].nElements); | |
887 | if (cur_choice->fields[0].value[0] == ' ') { | |
888 | /* the value is a string literal (the encoder can be called | |
889 | on that object directly */ | |
890 | src = mputprintf(src, | |
891 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" | |
892 | " if (temp_leaf != NULL)\n" | |
893 | " %s.RAW_encode(%s_descr_,*temp_leaf);\n" | |
894 | " else\n" | |
895 | " TTCN_EncDec_ErrorContext::error\n" | |
896 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged," | |
897 | " but omitted value.\");\n", | |
898 | cur_choice->fields[0].value, | |
899 | cur_choice->fields[0].fields[ | |
900 | cur_choice->fields[0].nElements - 1].typedescr); | |
901 | } else { | |
902 | /* a temporary object needs to be created for encoding */ | |
903 | src = mputprintf(src, | |
904 | " %s new_val(%s);\n" | |
905 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" | |
906 | " if (temp_leaf != NULL)\n" | |
907 | " new_val.RAW_encode(%s_descr_,*temp_leaf);\n" | |
908 | " else\n" | |
909 | " TTCN_EncDec_ErrorContext::error\n" | |
910 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged," | |
911 | " but omitted value.\");\n", | |
912 | cur_choice->fields[0].fields[ | |
913 | cur_choice->fields[0].nElements - 1].type, | |
914 | cur_choice->fields[0].value, | |
915 | cur_choice->fields[0].fields[ | |
916 | cur_choice->fields[0].nElements - 1].typedescr); | |
917 | } | |
918 | src = mputstr(src, " free_tree_pos(pr_pos.pos);\n"); | |
919 | } | |
920 | src = mputstr(src, " }\n" | |
921 | " break;\n"); | |
922 | } | |
923 | } | |
924 | src = mputstr(src, " default:;\n" | |
925 | " }\n"); | |
926 | if (sdef->elements[i].isOptional) src = mputstr(src, " }\n"); | |
927 | } | |
928 | } | |
929 | /* presence */ | |
930 | if (sdef->hasRaw && sdef->raw.presence.nElements > 0) { | |
931 | src = mputstr(src, " if ("); | |
932 | src = genRawFieldChecker(src, &sdef->raw.presence, FALSE); | |
933 | src = mputstr(src,") {\n"); | |
934 | src = genRawTagChecker(src, &sdef->raw.presence); | |
935 | src = mputstr(src," }\n"); | |
936 | } | |
937 | src = mputstr(src, " return myleaf.length = encoded_length;\n}\n\n"); | |
938 | ||
939 | if (use_runtime_2) | |
940 | src = generate_raw_coding_negtest(src, sdef, raw_options); | |
941 | return src; | |
942 | } | |
943 | ||
944 | char *generate_raw_coding_negtest(char *src, const struct_def *sdef, | |
945 | struct raw_option_struct *raw_options) | |
946 | { | |
947 | int i; | |
948 | const char *name = sdef->name; | |
949 | src = mputprintf(src, | |
950 | /* Count the nodes and discover the new node order only. No node creation | |
951 | or encoding. */ | |
952 | "int %s::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr, " | |
953 | "const TTCN_Typedescriptor_t& /*p_td*/, RAW_enc_tree& myleaf) const\n" | |
954 | "{\n" | |
955 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
956 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
957 | " int idx_map[%lu];\n" | |
958 | " for (int idx_map_idx = 0; idx_map_idx < %lu; ++idx_map_idx)\n" | |
959 | " idx_map[idx_map_idx] = -1;\n" | |
960 | " (void)idx_map;\n" | |
961 | " int encoded_length = 0;\n" | |
962 | " int num_fields = get_count();\n" | |
963 | " myleaf.isleaf = false;\n" | |
964 | " myleaf.body.node.num_of_nodes = 0;\n" | |
965 | " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n" | |
966 | " if ((p_err_descr->omit_before != -1) &&\n" | |
967 | " (field_idx < p_err_descr->omit_before))\n" | |
968 | " continue;\n" | |
969 | " const Erroneous_values_t *err_vals = p_err_descr->get_field_err_values(field_idx);\n" | |
970 | " const Erroneous_descriptor_t *emb_descr = p_err_descr->get_field_emb_descr(field_idx);\n" | |
971 | " if (err_vals && err_vals->before)\n" | |
972 | " ++myleaf.body.node.num_of_nodes;\n" | |
973 | " if (err_vals && err_vals->value) {\n" | |
974 | " if (err_vals->value->errval) {\n" | |
975 | " // Field is modified, but it's still there. Otherwise, it's\n" | |
976 | " // initialized to `-1'.\n" | |
977 | " idx_map[field_idx] = -2;\n" | |
978 | " ++myleaf.body.node.num_of_nodes;\n" | |
979 | " }\n" | |
980 | " } else {\n" | |
981 | " if (emb_descr) idx_map[field_idx] = -2;\n" | |
982 | " else idx_map[field_idx] = myleaf.body.node.num_of_nodes;\n" | |
983 | " ++myleaf.body.node.num_of_nodes;\n" | |
984 | " }\n" | |
985 | " if (err_vals && err_vals->after)\n" | |
986 | " ++myleaf.body.node.num_of_nodes;\n" | |
987 | " if ((p_err_descr->omit_after != -1) &&\n" | |
988 | " (field_idx >= p_err_descr->omit_after))\n" | |
989 | " break;\n" | |
990 | " }\n", | |
991 | name, (unsigned long)sdef->nElements, (unsigned long)sdef->nElements); | |
992 | /* Init nodes. */ | |
993 | src = mputprintf(src, | |
994 | " myleaf.body.node.nodes =\n" | |
995 | " init_nodes_of_enc_tree(myleaf.body.node.num_of_nodes);\n" | |
996 | " TTCN_EncDec_ErrorContext e_c;\n" | |
997 | " int node_pos = 0;\n" | |
998 | " int next_optional_idx = 0;\n" | |
999 | " const int *my_optional_indexes = get_optional_indexes();\n" | |
1000 | " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n" | |
1001 | " boolean is_optional_field = my_optional_indexes &&\n" | |
1002 | " (my_optional_indexes[next_optional_idx] == field_idx);\n" | |
1003 | " if ((p_err_descr->omit_before != -1) &&\n" | |
1004 | " (field_idx < p_err_descr->omit_before)) {\n" | |
1005 | " if (is_optional_field) ++next_optional_idx;\n" | |
1006 | " continue;\n" | |
1007 | " }\n" | |
1008 | " const Erroneous_values_t *err_vals =\n" | |
1009 | " p_err_descr->get_field_err_values(field_idx);\n" | |
1010 | " if (err_vals && err_vals->before) {\n" | |
1011 | " if (err_vals->before->errval == NULL)\n" | |
1012 | " TTCN_error(\"internal error: erroneous before value missing\");\n" | |
1013 | " if (err_vals->before->raw) {\n" | |
1014 | " myleaf.body.node.nodes[node_pos] =\n" | |
1015 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1016 | " node_pos, err_vals->before->errval" | |
1017 | "->get_descriptor()->raw);\n" | |
1018 | " } else {\n" | |
1019 | " if (err_vals->before->type_descr == NULL)\n" | |
1020 | " TTCN_error(\"internal error: erroneous before typedescriptor " | |
1021 | "missing\");\n" | |
1022 | " myleaf.body.node.nodes[node_pos] =\n" | |
1023 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1024 | " node_pos, err_vals->before->type_descr->raw);\n" | |
1025 | " }\n" | |
1026 | " ++node_pos;\n" | |
1027 | " }\n" | |
1028 | " if (err_vals && err_vals->value) {\n" | |
1029 | " if (err_vals->value->errval) {\n" | |
1030 | " e_c.set_msg(\"'%%s'(erroneous value): \", fld_name(field_idx));\n" | |
1031 | " if (err_vals->value->raw) {\n" | |
1032 | " myleaf.body.node.nodes[node_pos] =\n" | |
1033 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1034 | " node_pos, err_vals->value->errval" | |
1035 | "->get_descriptor()->raw);\n" | |
1036 | " } else {\n" | |
1037 | " if (err_vals->value->type_descr == NULL)\n" | |
1038 | " TTCN_error(\"internal error: erroneous value typedescriptor " | |
1039 | "missing\");\n" | |
1040 | " myleaf.body.node.nodes[node_pos] =\n" | |
1041 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1042 | " node_pos, err_vals->value->type_descr->raw);\n" | |
1043 | " }\n" | |
1044 | " ++node_pos;\n" | |
1045 | " }\n" | |
1046 | " } else {\n" | |
1047 | " e_c.set_msg(\"'%%s': \", fld_name(field_idx));\n" | |
1048 | " if (!is_optional_field || get_at(field_idx)->ispresent()) {\n" | |
1049 | " myleaf.body.node.nodes[node_pos] =\n" | |
1050 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1051 | " node_pos, fld_descr(field_idx)->raw);\n" | |
1052 | " } else {\n" | |
1053 | " // `omitted' field.\n" | |
1054 | " myleaf.body.node.nodes[node_pos] = NULL;\n" | |
1055 | " }\n" | |
1056 | " ++node_pos;\n" | |
1057 | " }\n" | |
1058 | " if (err_vals && err_vals->after) {\n" | |
1059 | " if (err_vals->after->errval == NULL)\n" | |
1060 | " TTCN_error(\"internal error: erroneous before value missing\");\n" | |
1061 | " if (err_vals->after->raw) {\n" | |
1062 | " myleaf.body.node.nodes[node_pos] =\n" | |
1063 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1064 | " node_pos, err_vals->after->errval" | |
1065 | "->get_descriptor()->raw);\n" | |
1066 | " } else {\n" | |
1067 | " if (err_vals->after->type_descr == NULL)\n" | |
1068 | " TTCN_error(\"internal error: erroneous after typedescriptor " | |
1069 | "missing\");\n" | |
1070 | " myleaf.body.node.nodes[node_pos] =\n" | |
1071 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1072 | " node_pos, err_vals->after->type_descr->raw);\n" | |
1073 | " }\n" | |
1074 | " ++node_pos;\n" | |
1075 | " }\n" | |
1076 | " if (is_optional_field) ++next_optional_idx;\n" | |
1077 | " if ((p_err_descr->omit_after != -1) &&\n" | |
1078 | " (field_idx >= p_err_descr->omit_after))\n" | |
1079 | " break;\n" | |
1080 | " }\n"); | |
1081 | /* Handling of the tricky attributes. A simple integer array will be used | |
1082 | to track changes (field positions) in the record. | |
1083 | int idx_map[n_fields] = { | |
1084 | -1 (= field 0. was omitted), | |
1085 | 1 (= field 1. can be found at index 1.), | |
1086 | -2 (= field 2. is still at index 2., but its value has changed) }; */ | |
1087 | for (i = 0; i < sdef->raw.ext_bit_goup_num; i++) { | |
1088 | if (sdef->raw.ext_bit_groups[i].ext_bit != XDEFNO) { | |
1089 | src = mputprintf(src, | |
1090 | " {\n" | |
1091 | " bool in_between_modified = false;\n" | |
1092 | " for (int idx_map_idx = %d; idx_map_idx <= %d; ++idx_map_idx)\n" | |
1093 | " if (idx_map[idx_map_idx] < 0) {\n" | |
1094 | " in_between_modified = true;\n" | |
1095 | " break;\n" | |
1096 | " }\n" | |
1097 | " if (idx_map[%d] < 0 || idx_map[%d] < 0 ||\n" | |
1098 | " %d != idx_map[%d] - idx_map[%d] || in_between_modified) {\n" | |
1099 | " e_c.set_msg(\"Field #%d and/or #%d: \");\n" | |
1100 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1101 | " \"Conflicting negative testing attributes, extension bit " | |
1102 | "group #%d will be ignored\");\n" | |
1103 | " } else {\n" | |
1104 | " int node_idx = idx_map[%d];\n" | |
1105 | " while (node_idx <= idx_map[%d] &&\n" | |
1106 | " myleaf.body.node.nodes[node_idx] == NULL)\n" | |
1107 | " node_idx++;\n" | |
1108 | " if (myleaf.body.node.nodes[node_idx]) {\n" | |
1109 | " myleaf.body.node.nodes[node_idx]->ext_bit_handling = 1;\n" | |
1110 | " myleaf.body.node.nodes[node_idx]->ext_bit = %s;\n" | |
1111 | " }\n" | |
1112 | " node_idx = idx_map[%d];\n" | |
1113 | " while (node_idx >= idx_map[%d] &&\n" | |
1114 | " myleaf.body.node.nodes[node_idx] == NULL)\n" | |
1115 | " node_idx--;\n" | |
1116 | " if (myleaf.body.node.nodes[node_idx])\n" | |
1117 | " myleaf.body.node.nodes[node_idx]->ext_bit_handling += 2;\n" | |
1118 | " }\n" | |
1119 | " }\n", | |
1120 | sdef->raw.ext_bit_groups[i].from, | |
1121 | sdef->raw.ext_bit_groups[i].to, | |
1122 | sdef->raw.ext_bit_groups[i].from, | |
1123 | sdef->raw.ext_bit_groups[i].to, | |
1124 | sdef->raw.ext_bit_groups[i].to - sdef->raw.ext_bit_groups[i].from, | |
1125 | sdef->raw.ext_bit_groups[i].to, | |
1126 | sdef->raw.ext_bit_groups[i].from, | |
1127 | sdef->raw.ext_bit_groups[i].from, | |
1128 | sdef->raw.ext_bit_groups[i].to, i, | |
1129 | sdef->raw.ext_bit_groups[i].from, | |
1130 | sdef->raw.ext_bit_groups[i].to, | |
1131 | sdef->raw.ext_bit_groups[i].ext_bit == XDEFYES ? "EXT_BIT_YES" : "EXT_BIT_REVERSE", | |
1132 | sdef->raw.ext_bit_groups[i].to, | |
1133 | sdef->raw.ext_bit_groups[i].from); | |
1134 | } | |
1135 | } | |
1136 | for (i = 0; i < sdef->nElements; i++) { | |
1137 | if (sdef->elements[i].isOptional) { | |
1138 | src = mputprintf(src, | |
1139 | " if (field_%s.ispresent()) {\n", | |
1140 | sdef->elements[i].name); | |
1141 | } | |
1142 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex == NULL | |
1143 | && sdef->elements[i].raw.union_member_num == 0) { | |
1144 | /* Encoding of lenghto fields. */ | |
1145 | int a; | |
1146 | src = mputprintf(src, | |
1147 | " if (idx_map[%lu] < 0) {\n" | |
1148 | " e_c.set_msg(\"Field '%s': \");\n" | |
1149 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1150 | " \"Conflicting negative testing attributes, LENGTHTO " | |
1151 | "attribute will be ignored\");\n" | |
1152 | " } else {\n" | |
1153 | " bool negtest_confl_lengthto = false;\n", | |
1154 | (unsigned long)i, sdef->elements[i].name); | |
1155 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1156 | src = mputprintf(src, | |
1157 | " if (idx_map[%lu] < 0) {\n" | |
1158 | " negtest_confl_lengthto = true;\n" | |
1159 | " e_c.set_msg(\"Field '%s': \");\n" | |
1160 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1161 | " \"Conflicting negative testing attributes, LENGTHTO " | |
1162 | "attribute will be ignored\");\n" | |
1163 | " }\n", | |
1164 | (unsigned long)sdef->elements[i].raw.lengthto[a], | |
1165 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1166 | } | |
1167 | src = mputprintf(src, | |
1168 | " if (!negtest_confl_lengthto) {\n" | |
1169 | " encoded_length += %d;\n" | |
1170 | " myleaf.body.node.nodes[idx_map[%lu]]->calc = CALC_LENGTH;\n" | |
1171 | " myleaf.body.node.nodes[idx_map[%lu]]->coding_descr = &%s_descr_;\n" | |
1172 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.num_of_fields = %d;\n" | |
1173 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.unit = %d;\n" | |
1174 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields = " | |
1175 | "init_lengthto_fields_list(%d);\n" | |
1176 | " myleaf.body.node.nodes[idx_map[%lu]]->length = %d;\n", | |
1177 | sdef->elements[i].raw.fieldlength, (unsigned long)i, | |
1178 | (unsigned long)i, sdef->elements[i].typedescrname, | |
1179 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
1180 | (unsigned long)i, sdef->elements[i].raw.unit, | |
1181 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
1182 | (unsigned long)i, sdef->elements[i].raw.fieldlength); | |
1183 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1184 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1185 | src = mputprintf(src, | |
1186 | " if (field_%s.ispresent()) {\n", | |
1187 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1188 | } | |
1189 | src = mputprintf(src, | |
1190 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields[%lu].level = " | |
1191 | "myleaf.body.node.nodes[idx_map[%lu]]->curr_pos.level;\n" | |
1192 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields[%lu].pos = " | |
1193 | "myleaf.body.node.nodes[idx_map[%lu]]->curr_pos.pos;\n", | |
1194 | (unsigned long)i, (unsigned long)a, | |
1195 | (unsigned long)sdef->elements[i].raw.lengthto[a], | |
1196 | (unsigned long)i, (unsigned long)a, | |
1197 | (unsigned long)sdef->elements[i].raw.lengthto[a]); | |
1198 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1199 | src = mputprintf(src, | |
1200 | " } else {\n" | |
1201 | " myleaf.body.node.nodes[idx_map[%lu]]->" | |
1202 | "calcof.lengthto.fields[%lu].level = 0;\n" | |
1203 | " myleaf.body.node.nodes[idx_map[%lu]]->" | |
1204 | "calcof.lengthto.fields[%lu].pos = 0;\n" | |
1205 | " }\n", | |
1206 | (unsigned long)i, (unsigned long)a, | |
1207 | (unsigned long)i, (unsigned long)a); | |
1208 | } | |
1209 | } | |
1210 | /* Closing inner index check. */ | |
1211 | src = mputstr(src, | |
1212 | " }\n"); | |
1213 | /* Closing outer index check. */ | |
1214 | src = mputstr(src, | |
1215 | " }\n"); | |
1216 | } else if (raw_options[i].pointerto) { | |
1217 | /* Encoding of pointerto fields. */ | |
1218 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { | |
1219 | src = mputprintf(src, | |
1220 | " if (field_%s.ispresent()) {\n", | |
1221 | sdef->elements[sdef->elements[i].raw.pointerto].name); | |
1222 | } | |
1223 | src = mputprintf(src, | |
1224 | " bool in_between_modified_pointerto_%s = false;\n" | |
1225 | " for (int idx_map_idx = %d; idx_map_idx <= %d; ++idx_map_idx) {\n" | |
1226 | " if (idx_map[idx_map_idx] < 0) {\n" | |
1227 | " in_between_modified_pointerto_%s = true;\n" | |
1228 | " break;\n" | |
1229 | " }\n" | |
1230 | " }\n" | |
1231 | " if (idx_map[%lu] < 0 || idx_map[%lu] < 0 ||\n" | |
1232 | " %lu != idx_map[%lu] - idx_map[%lu] || in_between_modified_pointerto_%s) {\n" | |
1233 | " e_c.set_msg(\"Field '%s' and/or '%s': \");\n" | |
1234 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1235 | " \"Conflicting negative testing attributes, POINTERTO " | |
1236 | "attribute will be ignored\");\n" | |
1237 | " } else {\n" | |
1238 | " encoded_length += %d;\n" | |
1239 | " myleaf.body.node.nodes[idx_map[%lu]]->calc = CALC_POINTER;\n" | |
1240 | " myleaf.body.node.nodes[idx_map[%lu]]->coding_descr = &%s_descr_;\n" | |
1241 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.unit = %d;\n" | |
1242 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.ptr_offset = %d;\n" | |
1243 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.ptr_base = %d;\n" | |
1244 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.target.level = " | |
1245 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
1246 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.target.pos = " | |
1247 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n" | |
1248 | " myleaf.body.node.nodes[idx_map[%lu]]->length = %d;\n" | |
1249 | " }\n", | |
1250 | sdef->elements[i].name, | |
1251 | i, sdef->elements[i].raw.pointerto, | |
1252 | sdef->elements[i].name, (unsigned long)i, | |
1253 | (unsigned long)sdef->elements[i].raw.pointerto, | |
1254 | (unsigned long)sdef->elements[i].raw.pointerto - (unsigned long)i, | |
1255 | (unsigned long)sdef->elements[i].raw.pointerto, (unsigned long)i, | |
1256 | sdef->elements[i].name, sdef->elements[i].name, | |
1257 | sdef->elements[sdef->elements[i].raw.pointerto].name, | |
1258 | sdef->elements[i].raw.fieldlength, (unsigned long)i, | |
1259 | (unsigned long)i, sdef->elements[i].typedescrname, | |
1260 | (unsigned long)i, sdef->elements[i].raw.unit, | |
1261 | (unsigned long)i, sdef->elements[i].raw.ptroffset, | |
1262 | (unsigned long)i, sdef->elements[i].raw.pointerbase, | |
1263 | (unsigned long)i, sdef->elements[i].raw.pointerto, | |
1264 | (unsigned long)i, sdef->elements[i].raw.pointerto, | |
1265 | (unsigned long)i, sdef->elements[i].raw.fieldlength); | |
1266 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { | |
1267 | src = mputprintf(src, | |
1268 | " } else {\n" | |
1269 | " INTEGER atm;\n" | |
1270 | " atm = 0;\n" | |
1271 | " encoded_length += atm.RAW_encode(%s_descr_, " | |
1272 | "*myleaf.body.node.nodes[idx_map[%lu]]);\n" | |
1273 | " }\n", | |
1274 | sdef->elements[i].typedescrname, (unsigned long)i); | |
1275 | } | |
1276 | } else { | |
1277 | /* Encoding of normal fields with no negative testing. Needed for the | |
1278 | later phase. */ | |
1279 | src = mputprintf(src, | |
1280 | " if (idx_map[%lu] >= 0) " | |
1281 | "encoded_length += field_%s%s.RAW_encode(%s_descr_, " | |
1282 | "*myleaf.body.node.nodes[idx_map[%lu]]);\n", | |
1283 | (unsigned long)i, sdef->elements[i].name, | |
1284 | sdef->elements[i].isOptional ? "()" : "", | |
1285 | sdef->elements[i].typedescrname, (unsigned long)i); | |
1286 | } | |
1287 | if (sdef->elements[i].isOptional) { | |
1288 | src = mputstr(src, | |
1289 | " }\n"); | |
1290 | } | |
1291 | } | |
1292 | for (i = 0; i < sdef->nElements; i++) { | |
1293 | /* Fill presence, tag and crosstag. */ | |
1294 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex) { | |
1295 | /* Encoding of lenghto fields with lengthindex. */ | |
1296 | int a; | |
1297 | if (sdef->elements[i].isOptional) { | |
1298 | src = mputprintf(src, | |
1299 | " if (field_%s.ispresent()) {\n", | |
1300 | sdef->elements[i].name); | |
1301 | } | |
1302 | src = mputprintf(src, | |
1303 | " if (idx_map[%lu] < 0) {\n" | |
1304 | " e_c.set_msg(\"Field '%s': \");\n" | |
1305 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1306 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " | |
1307 | "attribute will be ignored\");\n" | |
1308 | " } else {\n" | |
1309 | " if (myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]) {\n" | |
1310 | " bool negtest_confl_lengthto = false;\n", | |
1311 | (unsigned long)i, sdef->elements[i].name, (unsigned long)i, | |
1312 | sdef->elements[i].raw.lengthindex->nthfield); | |
1313 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1314 | src = mputprintf(src, | |
1315 | " if (idx_map[%lu] < 0) {\n" | |
1316 | " negtest_confl_lengthto = true;\n" | |
1317 | " e_c.set_msg(\"Field '%s': \");\n" | |
1318 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1319 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " | |
1320 | "attribute will be ignored\");\n" | |
1321 | " }\n", | |
1322 | (unsigned long)sdef->elements[i].raw.lengthto[a], | |
1323 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1324 | } | |
1325 | src = mputprintf(src, | |
1326 | " if (!negtest_confl_lengthto) {\n" | |
1327 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1328 | "calc = CALC_LENGTH;\n" | |
1329 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1330 | "coding_descr = &%s_descr_;\n" | |
1331 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1332 | "calcof.lengthto.num_of_fields = %d;\n" | |
1333 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1334 | "calcof.lengthto.unit = %d;\n" | |
1335 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1336 | "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", | |
1337 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1338 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1339 | sdef->elements[i].raw.lengthindex->typedescr, | |
1340 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1341 | sdef->elements[i].raw.lengthto_num, | |
1342 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1343 | sdef->elements[i].raw.unit, | |
1344 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1345 | sdef->elements[i].raw.lengthto_num); | |
1346 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1347 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1348 | src = mputprintf(src, | |
1349 | " if (field_%s.ispresent()) {\n", | |
1350 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1351 | } | |
1352 | src = mputprintf(src, | |
1353 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]" | |
1354 | "->calcof.lengthto.fields[%d].level = " | |
1355 | "myleaf.body.node.nodes[idx_map[%d]]->curr_pos.level;\n" | |
1356 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]" | |
1357 | "->calcof.lengthto.fields[%d].pos = " | |
1358 | "myleaf.body.node.nodes[idx_map[%d]]->curr_pos.pos;\n", | |
1359 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a, | |
1360 | sdef->elements[i].raw.lengthto[a], (unsigned long)i, | |
1361 | sdef->elements[i].raw.lengthindex->nthfield, a, | |
1362 | sdef->elements[i].raw.lengthto[a]); | |
1363 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1364 | src = mputprintf(src, | |
1365 | " } else {\n" | |
1366 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1367 | "calcof.lengthto.fields[%d].level = 0;\n" | |
1368 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1369 | "calcof.lengthto.fields[%d].pos = 0;\n" | |
1370 | " }\n", | |
1371 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a, | |
1372 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a); | |
1373 | } | |
1374 | } | |
1375 | /* Closing index check. */ | |
1376 | src = mputstr(src, | |
1377 | " }\n"); | |
1378 | src = mputstr(src, " }\n }\n"); | |
1379 | if (sdef->elements[i].isOptional) { | |
1380 | src = mputstr(src, " }\n"); | |
1381 | } | |
1382 | } | |
1383 | if (raw_options[i].lengthto && sdef->elements[i].raw.union_member_num) { | |
1384 | /* Encoding of lenghto fields. */ | |
1385 | int a; | |
1386 | if (sdef->elements[i].isOptional) { | |
1387 | src = mputprintf(src, | |
1388 | " if (field_%s.ispresent()) ", sdef->elements[i].name); | |
1389 | } | |
1390 | src = mputprintf(src, | |
1391 | " {\n" | |
1392 | " if (idx_map[%lu] < 0) {\n" | |
1393 | " e_c.set_msg(\"Field '%s': \");\n" | |
1394 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1395 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " | |
1396 | "attribute will be ignored\");\n" | |
1397 | " } else {\n" | |
1398 | " bool negtest_confl_lengthto = false;\n", | |
1399 | (unsigned long)i, sdef->elements[i].name); | |
1400 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1401 | src = mputprintf(src, | |
1402 | " if (idx_map[%lu] < 0) {\n" | |
1403 | " negtest_confl_lengthto = true;\n" | |
1404 | " e_c.set_msg(\"Field '%s': \");\n" | |
1405 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1406 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " | |
1407 | "attribute will be ignored\");\n" | |
1408 | " }\n", | |
1409 | (unsigned long)sdef->elements[i].raw.lengthto[a], | |
1410 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1411 | } | |
1412 | src = mputprintf(src, | |
1413 | " if (!negtest_confl_lengthto) {\n" | |
1414 | " int sel_field = 0;\n" | |
1415 | " while (myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field] == NULL) " | |
1416 | "{ sel_field++; }\n" | |
1417 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" | |
1418 | "calc = CALC_LENGTH;\n" | |
1419 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" | |
1420 | "calcof.lengthto.num_of_fields = %d;\n" | |
1421 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" | |
1422 | "calcof.lengthto.unit = %d;\n" | |
1423 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" | |
1424 | "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", | |
1425 | (unsigned long)i, (unsigned long)i, | |
1426 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
1427 | (unsigned long)i, sdef->elements[i].raw.unit, | |
1428 | (unsigned long)i, sdef->elements[i].raw.lengthto_num); | |
1429 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1430 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1431 | src = mputprintf(src, | |
1432 | " if (field_%s.ispresent()) {\n", | |
1433 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1434 | } | |
1435 | src = mputprintf(src, | |
1436 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" | |
1437 | "->calcof.lengthto.fields[%d].level = " | |
1438 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
1439 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" | |
1440 | "->calcof.lengthto.fields[%d].pos = " | |
1441 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", | |
1442 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a], | |
1443 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]); | |
1444 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1445 | src = mputprintf(src, | |
1446 | " } else {\n" | |
1447 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" | |
1448 | "->calcof.lengthto.fields[%d].level = 0;\n" | |
1449 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" | |
1450 | "->calcof.lengthto.fields[%d].pos = 0;\n" | |
1451 | " }\n", | |
1452 | (unsigned long)i, a, | |
1453 | (unsigned long)i, a); | |
1454 | } | |
1455 | } | |
1456 | /* Closing inner index check. */ | |
1457 | src = mputstr(src, | |
1458 | " }\n"); | |
1459 | /* Closing outer index check. */ | |
1460 | src = mputstr(src, | |
1461 | " }\n"); | |
1462 | /* Closing ispresent or local block. */ | |
1463 | src = mputstr(src, | |
1464 | " }\n"); | |
1465 | } | |
1466 | if (raw_options[i].tag_type && | |
1467 | sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements) { | |
1468 | /* Plain, old tag. */ | |
1469 | rawAST_coding_taglist *cur_choice = | |
1470 | sdef->raw.taglist.list + raw_options[i].tag_type - 1; | |
1471 | src = mputprintf(src, | |
1472 | " bool negtest_confl_tag_%s = false;\n" | |
1473 | " if (idx_map[%lu] < 0) {\n" | |
1474 | " negtest_confl_tag_%s = true;\n" | |
1475 | " e_c.set_msg(\"Field '%s': \");\n" | |
1476 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1477 | " \"Conflicting negative testing attributes, TAG attribute will " | |
1478 | "be ignored\");\n" | |
1479 | " }\n", | |
1480 | sdef->elements[i].name, (unsigned long)i, sdef->elements[i].name, | |
1481 | sdef->elements[i].name); | |
1482 | src = mputprintf(src, " if (!negtest_confl_tag_%s && (", | |
1483 | sdef->elements[i].name); | |
1484 | if (sdef->elements[i].isOptional) { | |
1485 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); | |
1486 | } | |
1487 | src = genRawFieldChecker(src, cur_choice, FALSE); | |
1488 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); | |
1489 | src = mputstr(src,")) {\n"); | |
1490 | src = genRawTagChecker(src, cur_choice); | |
1491 | src = mputstr(src," }\n"); | |
1492 | } | |
1493 | if (sdef->elements[i].hasRaw && sdef->elements[i].raw.presence.nElements) { | |
1494 | /* Presence attribute for fields. */ | |
1495 | int taglist_idx, field_idx; | |
1496 | /* The optional field itself. */ | |
1497 | src = mputprintf(src, | |
1498 | " bool negtest_confl_presence_%s = false;\n" | |
1499 | " if (idx_map[%lu] < 0) {\n" | |
1500 | " negtest_confl_presence_%s = true;\n" | |
1501 | " e_c.set_msg(\"Field '%s': \");\n" | |
1502 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1503 | " \"Conflicting negative testing attributes, PRESENCE attribute " | |
1504 | "will be ignored\");\n" | |
1505 | " }\n", | |
1506 | sdef->elements[i].name, (unsigned long)i, sdef->elements[i].name, | |
1507 | sdef->elements[i].name); | |
1508 | /* Check the referenced fields. */ | |
1509 | for (taglist_idx = 0; | |
1510 | taglist_idx < sdef->elements[i].raw.presence.nElements; ++taglist_idx) { | |
1511 | rawAST_coding_field_list *fields = | |
1512 | sdef->elements[i].raw.presence.fields + taglist_idx; | |
1513 | for (field_idx = 0; field_idx < fields->nElements; ++field_idx) { | |
1514 | /* The top level field is enough. >0 index is for subrefs. */ | |
1515 | if (field_idx == 0) { | |
1516 | rawAST_coding_fields *field = fields->fields + field_idx; | |
1517 | src = mputprintf(src, | |
1518 | " if (idx_map[%d] < 0) {\n" | |
1519 | " negtest_confl_presence_%s = true;\n" | |
1520 | " e_c.set_msg(\"Field '%s': \");\n" | |
1521 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1522 | " \"Conflicting negative testing attributes, PRESENCE attribute " | |
1523 | "will be ignored\");\n" | |
1524 | " }\n", | |
1525 | field->nthfield, sdef->elements[i].name, field->nthfieldname); | |
1526 | } else { | |
1527 | /* Subrefs. */ | |
1528 | break; | |
1529 | } | |
1530 | } | |
1531 | } | |
1532 | src = mputprintf(src, " if (!negtest_confl_presence_%s && (", | |
1533 | sdef->elements[i].name); | |
1534 | if (sdef->elements[i].isOptional) { | |
1535 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); | |
1536 | } | |
1537 | src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, FALSE); | |
1538 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); | |
1539 | src = mputstr(src, ")) {\n"); | |
1540 | src = genRawTagChecker(src, &sdef->elements[i].raw.presence); | |
1541 | src = mputstr(src, " }\n"); | |
1542 | } | |
1543 | if (sdef->elements[i].hasRaw && | |
1544 | sdef->elements[i].raw.crosstaglist.nElements) { | |
1545 | /* crosstag */ | |
1546 | int a; | |
1547 | /* The union field itself. */ | |
1548 | src = mputprintf(src, | |
1549 | " if (idx_map[%lu] < 0) {\n" | |
1550 | " e_c.set_msg(\"Field '%s': \");\n" | |
1551 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1552 | " \"Conflicting negative testing attributes, CROSSTAG attribute " | |
1553 | "will be ignored\");\n" | |
1554 | " } else {\n", | |
1555 | (unsigned long)i, sdef->elements[i].name); | |
1556 | if (sdef->elements[i].isOptional) { | |
1557 | src = mputprintf(src, | |
1558 | " if (field_%s.ispresent()) {\n", | |
1559 | sdef->elements[i].name); | |
1560 | } | |
1561 | src = mputprintf(src, | |
1562 | " switch (field_%s%s.get_selection()) {\n", | |
1563 | sdef->elements[i].name,sdef->elements[i].isOptional ? "()" : ""); | |
1564 | for (a = 0; a < sdef->elements[i].raw.crosstaglist.nElements; a++) { | |
1565 | rawAST_coding_taglist *cur_choice = | |
1566 | sdef->elements[i].raw.crosstaglist.list + a; | |
1567 | if (cur_choice->nElements > 0) { | |
1568 | int taglist_idx, field_idx; | |
1569 | src = mputprintf(src, | |
1570 | " case %s%s%s: {\n" | |
1571 | " bool negtest_confl_crosstag = false;\n", | |
1572 | sdef->elements[i].type, "::ALT_", | |
1573 | cur_choice->fieldName); | |
1574 | for (taglist_idx = 0; | |
1575 | taglist_idx < cur_choice->nElements; ++taglist_idx) { | |
1576 | rawAST_coding_field_list *fields = cur_choice->fields + taglist_idx; | |
1577 | for (field_idx = 0; field_idx < fields->nElements; ++field_idx) { | |
1578 | rawAST_coding_fields *field = fields->fields + field_idx; | |
1579 | if (field_idx == 0) { | |
1580 | src = mputprintf(src, | |
1581 | " if (idx_map[%d] < 0) {\n" | |
1582 | " negtest_confl_crosstag = true;\n" | |
1583 | " e_c.set_msg(\"Field '%s': \");\n" | |
1584 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1585 | " \"Conflicting negative testing attributes, CROSSTAG attribute " | |
1586 | "will be ignored\");\n" | |
1587 | " }\n", | |
1588 | field->nthfield, field->nthfieldname); | |
1589 | } else { | |
1590 | break; | |
1591 | } | |
1592 | } | |
1593 | } | |
1594 | src = mputstr(src, " if (!negtest_confl_crosstag && ("); | |
1595 | src = genRawFieldChecker(src, cur_choice, FALSE); | |
1596 | src = mputstr(src, ")) {\n"); | |
1597 | if (!strcmp(cur_choice->fields[0].value, "OMIT_VALUE")) { | |
1598 | if (cur_choice->fields[0].nElements != 1) | |
1599 | NOTSUPP("omit value with multiple fields in CROSSTAG"); | |
1600 | /* eliminating the corresponding encoded leaf, which will have | |
1601 | the same effect as if the referred field had been omit */ | |
1602 | src = mputprintf(src, | |
1603 | " encoded_length -= myleaf.body.node.nodes[%d]->length;\n" | |
1604 | " delete myleaf.body.node.nodes[%d];\n" | |
1605 | " myleaf.body.node.nodes[%d] = NULL;\n", | |
1606 | cur_choice->fields[0].fields[0].nthfield, | |
1607 | cur_choice->fields[0].fields[0].nthfield, | |
1608 | cur_choice->fields[0].fields[0].nthfield); | |
1609 | } else { | |
1610 | int ll; | |
1611 | src = mputprintf(src, | |
1612 | " RAW_enc_tr_pos pr_pos;\n" | |
1613 | " pr_pos.level = myleaf.curr_pos.level + %d;\n" | |
1614 | " int new_pos[] = { ", | |
1615 | cur_choice->fields[0].nElements); | |
1616 | for (ll = 0; ll < cur_choice->fields[0].nElements; ll++) { | |
1617 | if (ll > 0) src = mputstr(src, ", "); | |
1618 | src = mputprintf(src, "%d", | |
1619 | cur_choice->fields[0].fields[ll].nthfield); | |
1620 | } | |
1621 | src = mputprintf(src, " };\n" | |
1622 | " pr_pos.pos = init_new_tree_pos(myleaf.curr_pos, %d, " | |
1623 | "new_pos);\n", | |
1624 | cur_choice->fields[0].nElements); | |
1625 | if (cur_choice->fields[0].value[0] == ' ') { | |
1626 | /* the value is a string literal (the encoder can be called | |
1627 | on that object directly */ | |
1628 | src = mputprintf(src, | |
1629 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" | |
1630 | " if (temp_leaf != NULL)\n" | |
1631 | " %s.RAW_encode(%s_descr_, *temp_leaf);\n" | |
1632 | " else\n" | |
1633 | " TTCN_EncDec_ErrorContext::error\n" | |
1634 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged, " | |
1635 | "but omitted value.\");\n", | |
1636 | cur_choice->fields[0].value, | |
1637 | cur_choice->fields[0].fields[ | |
1638 | cur_choice->fields[0].nElements - 1].typedescr); | |
1639 | } else { | |
1640 | /* a temporary object needs to be created for encoding */ | |
1641 | src = mputprintf(src, | |
1642 | " %s new_val(%s);\n" | |
1643 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" | |
1644 | " if (temp_leaf != NULL)\n" | |
1645 | " new_val.RAW_encode(%s_descr_, *temp_leaf);\n" | |
1646 | " else\n" | |
1647 | " TTCN_EncDec_ErrorContext::error\n" | |
1648 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged, " | |
1649 | "but omitted value.\");\n", | |
1650 | cur_choice->fields[0].fields[ | |
1651 | cur_choice->fields[0].nElements - 1].type, | |
1652 | cur_choice->fields[0].value, | |
1653 | cur_choice->fields[0].fields[ | |
1654 | cur_choice->fields[0].nElements - 1].typedescr); | |
1655 | } | |
1656 | src = mputstr(src, " free_tree_pos(pr_pos.pos);\n"); | |
1657 | } | |
1658 | src = mputstr(src, " }\n" | |
1659 | " break; }\n"); | |
1660 | } | |
1661 | } | |
1662 | src = mputstr(src, " default:;\n" | |
1663 | " }\n"); | |
1664 | if (sdef->elements[i].isOptional) src = mputstr(src, " }\n"); | |
1665 | src = mputstr(src, " }\n"); | |
1666 | } | |
1667 | } | |
1668 | src = mputprintf(src, | |
1669 | " node_pos = 0;\n" | |
1670 | " next_optional_idx = 0;\n" | |
1671 | " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n" | |
1672 | " boolean is_optional_field = my_optional_indexes &&\n" | |
1673 | " (my_optional_indexes[next_optional_idx] == field_idx);\n" | |
1674 | " if ((p_err_descr->omit_before != -1) &&\n" | |
1675 | " (field_idx < p_err_descr->omit_before)) {\n" | |
1676 | " if (is_optional_field) ++next_optional_idx;\n" | |
1677 | " continue;\n" | |
1678 | " }\n" | |
1679 | " const Erroneous_values_t *err_vals = p_err_descr->get_field_err_values(field_idx);\n" | |
1680 | " const Erroneous_descriptor_t *emb_descr = p_err_descr->get_field_emb_descr(field_idx);\n" | |
1681 | " if (err_vals && err_vals->before) {\n" | |
1682 | " if (err_vals->before->errval == NULL)\n" | |
1683 | " TTCN_error(\"internal error: erroneous before value missing\");\n" | |
1684 | " if (err_vals->before->raw) {\n" | |
1685 | " encoded_length += err_vals->before->errval->" | |
1686 | "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n" | |
1687 | " } else {\n" | |
1688 | " if (err_vals->before->type_descr == NULL)\n" | |
1689 | " TTCN_error(\"internal error: erroneous before typedescriptor missing\");\n" | |
1690 | " encoded_length += err_vals->before->errval->RAW_encode(*(err_vals->before->type_descr),\n" | |
1691 | " *myleaf.body.node.nodes[node_pos++]);\n" | |
1692 | " }\n" | |
1693 | " }\n" | |
1694 | " if (err_vals && err_vals->value) {\n" | |
1695 | " if (err_vals->value->errval) {\n" | |
1696 | " e_c.set_msg(\"'%%s'(erroneous value): \", fld_name(field_idx));\n" | |
1697 | " if (err_vals->value->raw) {\n" | |
1698 | " encoded_length += err_vals->value->errval->" | |
1699 | "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n" | |
1700 | " } else {\n" | |
1701 | " if (err_vals->value->type_descr == NULL)\n" | |
1702 | " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n" | |
1703 | " encoded_length += err_vals->value->errval->" | |
1704 | "RAW_encode(*(err_vals->value->type_descr), *myleaf.body.node.nodes[node_pos++]);\n" | |
1705 | " }\n" | |
1706 | " }\n" | |
1707 | " } else {\n" | |
1708 | " e_c.set_msg(\"'%%s': \", fld_name(field_idx));\n" | |
1709 | " if (!is_optional_field || get_at(field_idx)->ispresent()) {\n" | |
1710 | " const Base_Type *curr_field = is_optional_field " | |
1711 | "? get_at(field_idx)->get_opt_value() : get_at(field_idx);\n" | |
1712 | " if (emb_descr) {\n" | |
1713 | " encoded_length += curr_field\n" | |
1714 | " ->RAW_encode_negtest(emb_descr, *fld_descr(field_idx),\n" | |
1715 | " *myleaf.body.node.nodes[node_pos]);\n" | |
1716 | " }\n" | |
1717 | " } else {\n" | |
1718 | " // `omitted' field.\n" | |
1719 | " myleaf.body.node.nodes[node_pos] = NULL;\n" | |
1720 | " }\n" | |
1721 | " ++node_pos;\n" | |
1722 | " }\n" | |
1723 | " if (err_vals && err_vals->after) {\n" | |
1724 | " if (err_vals->after->errval == NULL)\n" | |
1725 | " TTCN_error(\"internal error: erroneous before value missing\");\n" | |
1726 | " if (err_vals->after->raw) {\n" | |
1727 | " encoded_length += err_vals->after->errval->" | |
1728 | "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n" | |
1729 | " } else {\n" | |
1730 | " if (err_vals->after->type_descr == NULL)\n" | |
1731 | " TTCN_error(\"internal error: erroneous after typedescriptor missing\");\n" | |
1732 | " encoded_length += err_vals->after->errval->" | |
1733 | "RAW_encode(*(err_vals->after->type_descr), *myleaf.body.node.nodes[node_pos++]);\n" | |
1734 | " }\n" | |
1735 | " }\n" | |
1736 | " if (is_optional_field) ++next_optional_idx;\n" | |
1737 | " if ((p_err_descr->omit_after != -1) &&\n" | |
1738 | " (field_idx >= p_err_descr->omit_after))\n" | |
1739 | " break;\n" | |
1740 | " }\n"); | |
1741 | /* Presence for the whole record. */ | |
1742 | if (sdef->hasRaw && sdef->raw.presence.nElements > 0) { | |
1743 | /* Check the referenced fields. */ | |
1744 | int taglist_idx, field_idx; | |
1745 | src = mputstr(src, " bool negtest_confl_presence = false;\n"); | |
1746 | for (taglist_idx = 0; taglist_idx < sdef->raw.presence.nElements; ++taglist_idx) { | |
1747 | rawAST_coding_field_list *fields = | |
1748 | sdef->raw.presence.fields + taglist_idx; | |
1749 | for (field_idx = 0; field_idx < fields->nElements; ++field_idx) { | |
1750 | if (field_idx == 0) { | |
1751 | rawAST_coding_fields *field = fields->fields + field_idx; | |
1752 | src = mputprintf(src, | |
1753 | " if (idx_map[%d] < 0) {\n" | |
1754 | " negtest_confl_presence = true;\n" | |
1755 | " e_c.set_msg(\"Field '%s': \");\n" | |
1756 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1757 | " \"Conflicting negative testing attributes, PRESENCE attribute " | |
1758 | "will be ignored\");\n" | |
1759 | " }\n", | |
1760 | field->nthfield, field->nthfieldname); | |
1761 | } else { | |
1762 | break; | |
1763 | } | |
1764 | } | |
1765 | } | |
1766 | src = mputstr(src, " if (!negtest_confl_presence && ("); | |
1767 | src = genRawFieldChecker(src, &sdef->raw.presence, FALSE); | |
1768 | src = mputstr(src,")) {\n"); | |
1769 | src = genRawTagChecker(src, &sdef->raw.presence); | |
1770 | src = mputstr(src," }\n"); | |
1771 | } | |
1772 | src = mputstr(src, | |
1773 | " return myleaf.length = encoded_length;\n" | |
1774 | "}\n\n"); | |
1775 | return src; | |
1776 | } | |
1777 | ||
1778 | void gen_xer(const struct_def *sdef, char **pdef, char **psrc) | |
1779 | { /* XERSTUFF codegen for record/SEQUENCE */ | |
1780 | size_t i; | |
1781 | char *def = *pdef, *src = *psrc; | |
1782 | const char * const name = sdef->name; | |
1783 | ||
1784 | /* | |
1785 | * NOTE! Decisions based on the coding instructions of the components | |
1786 | * (e.g. number of attributes) can be made at compile time. | |
1787 | * Decisions on coding instructions of the record itself (e.g. D-F-E, | |
1788 | * EMBED-VALUES, USE-NIL, USE-ORDER) __must__ be postponed to run-time, | |
1789 | * because these can be applied to type references, | |
1790 | * which will not be visible when the code is generated. | |
1791 | */ | |
1792 | ||
1793 | /* Number of fields with ATTRIBUTE, includes ANY-ATTRIBUTES */ | |
1794 | size_t num_attributes = 0; | |
1795 | ||
1796 | /* index of USE-ORDER member, which may be bumped into second place by EMBED-VALUES */ | |
1797 | size_t uo = (sdef->xerEmbedValuesPossible !=0); | |
1798 | ||
1799 | /* start_at is the index of the first "real" member of the record */ | |
1800 | size_t start_at = uo + (sdef->xerUseOrderPossible != 0); | |
1801 | ||
970ed795 EL |
1802 | /* Number of optional non-attributes */ |
1803 | size_t n_opt_elements = 0; | |
1804 | ||
1805 | const boolean want_namespaces = !sdef->isASN1 /* TODO remove this when ASN.1 gets EXER */; | |
1806 | ||
1807 | int aa_index = -1; | |
1808 | /* Find the number of attributes (compile time) */ | |
1809 | for (i = 0; i < sdef->nElements; ++i) { | |
1810 | if (sdef->elements[i].xerAttribute) { | |
1811 | ++num_attributes; | |
1812 | } | |
1813 | else if (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT) { | |
1814 | ++num_attributes; /* ANY-ATTRIBUTES also included with attributes */ | |
1815 | aa_index = i; | |
1816 | /* If the first member is ANY-ATTRIBUTES, then xerEmbedValuesPossible | |
1817 | * is merely an illusion and USE-ORDER is not possible. */ | |
1818 | if (i==0) { | |
1819 | start_at = uo = 0; | |
1820 | } | |
1821 | } | |
1822 | else /* not attribute */ if (sdef->elements[i].isOptional) { | |
1823 | ++n_opt_elements; | |
1824 | } | |
1825 | } | |
970ed795 EL |
1826 | |
1827 | /* Write some helper functions */ | |
1828 | def = mputstr(def, | |
1829 | "char **collect_ns(const XERdescriptor_t& p_td, size_t& num_ns, bool& def_ns) const;\n"); | |
1830 | ||
1831 | src = mputprintf(src, | |
1832 | "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num_ns, bool& def_ns) const {\n" | |
1833 | " size_t num_collected;\n" | |
1834 | " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n" | |
1835 | /* The above might throw but then nothing was allocated. */ | |
1836 | , name); | |
1837 | ||
1838 | /* Collect namespaces from the "non-special" members (incl. attributes) */ | |
1839 | if (start_at < sdef->nElements) src = mputstr(src, | |
1840 | " try {\n" | |
1841 | " char **new_ns;\n" | |
1842 | " size_t num_new;\n" | |
1843 | " bool def_ns_1 = false;\n"); | |
1844 | for (i = start_at; i < sdef->nElements; ++i) { | |
1845 | src = mputprintf(src, | |
1846 | " new_ns = field_%s.collect_ns(%s_xer_, num_new, def_ns);\n" | |
1847 | " merge_ns(collected_ns, num_collected, new_ns, num_new);\n" | |
1848 | " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */ | |
1849 | , sdef->elements[i].name, sdef->elements[i].typegen | |
1850 | ); | |
1851 | } | |
1852 | if (sdef->xerUseNilPossible) { | |
1853 | src = mputprintf(src, | |
1854 | " if((p_td.xer_bits & USE_NIL) && !field_%s.ispresent()) {\n" /* "nil" attribute to be written*/ | |
1855 | " collected_ns = (char**)Realloc(collected_ns, sizeof(char*) * ++num_collected);\n" | |
1856 | " const namespace_t *c_ns = p_td.my_module->get_controlns();\n" | |
1857 | " collected_ns[num_collected-1] = mprintf(\" xmlns:%%s='%%s'\", c_ns->px, c_ns->ns);\n" | |
1858 | " }\n" | |
1859 | , sdef->elements[sdef->nElements-1].name | |
1860 | ); | |
1861 | } | |
1862 | if (start_at < sdef->nElements) src = mputstr(src, | |
1863 | " }\n" | |
1864 | " catch (...) {\n" | |
1865 | /* Probably a TC_Error thrown from field_%s->collect_ns() if e.g. | |
1866 | * encoding an unbound value. */ | |
1867 | " while (num_collected > 0) Free(collected_ns[--num_collected]);\n" | |
1868 | " Free(collected_ns);\n" | |
1869 | " throw;\n" | |
1870 | " }\n" | |
1871 | ); | |
1872 | ||
1873 | src = mputstr(src, | |
1874 | " num_ns = num_collected;\n" | |
1875 | " return collected_ns;\n" | |
1876 | "}\n\n" | |
1877 | ); | |
1878 | ||
1879 | src = mputprintf(src, | |
1880 | "boolean %s::can_start(const char *name, const char *uri, const XERdescriptor_t& xd, unsigned int flavor) {\n" | |
1881 | " boolean e_xer = is_exer(flavor &= ~XER_RECOF);\n" | |
1882 | " if (!e_xer || !((xd.xer_bits & UNTAGGED) || (flavor & (USE_NIL|XER_RECOF)))) return check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n" | |
1883 | , name | |
1884 | ); | |
1885 | for (i = start_at; i < sdef->nElements; ++i) { | |
1886 | src = mputprintf(src, | |
1887 | " else if (%s::can_start(name, uri, %s_xer_, flavor)) return true;\n" | |
1888 | /* Here we know for sure it's exer */ | |
1889 | , sdef->elements[i].type | |
1890 | , sdef->elements[i].typegen | |
1891 | ); | |
1892 | if (!sdef->elements[i].isOptional) break; | |
1893 | /* The last component with which it can begin is the first non-optional. | |
1894 | * Does that sentence makes sense to you ? */ | |
1895 | } | |
1896 | src = mputstr(src, " return false;\n}\n\n"); | |
1897 | ||
1898 | /* * * * * * * * * * XER_encode * * * * * * * * * * * * * * */ | |
1899 | src = mputprintf(src, | |
1900 | "int %s::XER_encode(const XERdescriptor_t& p_td, " | |
af710487 | 1901 | "TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n" |
970ed795 EL |
1902 | "{\n" |
1903 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
1904 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
1905 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" | |
1906 | " TTCN_EncDec_ErrorContext ec_1;\n" | |
1907 | " int encoded_length=(int)p_buf.get_len();\n" | |
1908 | " int e_xer = is_exer(p_flavor);\n" | |
1909 | " const boolean omit_tag = e_xer && p_indent " | |
1910 | "&& ((p_td.xer_bits & (UNTAGGED|XER_ATTRIBUTE)) || (p_flavor & (USE_NIL|USE_TYPE_ATTR)));\n" | |
1911 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) p_flavor |= XER_CANONICAL;\n" | |
1912 | " int is_indented = !is_canonical(p_flavor);\n" | |
1913 | , name); | |
1914 | ||
1915 | if (want_namespaces && !(num_attributes|sdef->xerUseQName)) src = mputstr(src, | |
1916 | " const boolean need_control_ns = (p_td.xer_bits & (USE_NIL));\n"); | |
1917 | ||
1918 | if (start_at < sdef->nElements) { /* there _are_ non-special members */ | |
1919 | src = mputstr(src, | |
1920 | " size_t num_collected = 0;\n" | |
1921 | " char **collected_ns = NULL;\n" | |
1922 | " bool def_ns = false;\n" | |
1923 | " if (e_xer) {\n" | |
1924 | " if (p_indent == 0) {\n" /* top-level */ | |
1925 | " collected_ns = collect_ns(p_td, num_collected, def_ns);\n" /* our own ns */ | |
1926 | " }\n" | |
1927 | " else if ((p_flavor & DEF_NS_SQUASHED) && p_td.my_module && p_td.ns_index != -1){\n" | |
1928 | " const namespace_t * ns = p_td.my_module->get_ns(p_td.ns_index);\n" | |
1929 | " if (*ns->px == '\\0') {\n" | |
1930 | " collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n" | |
1931 | " }\n" | |
1932 | " }\n" | |
1933 | " }\n" | |
1934 | ); | |
1935 | } | |
1936 | ||
1937 | if (want_namespaces) { | |
1938 | src = mputstr(src, | |
1939 | " const boolean empty_ns_hack = e_xer && !omit_tag && (p_indent > 0)\n" | |
1940 | " && (p_td.xer_bits & FORM_UNQUALIFIED)\n" | |
1941 | " && p_td.my_module && p_td.ns_index != -1\n" | |
1942 | " && *p_td.my_module->get_ns(p_td.ns_index)->px == '\\0';\n" | |
1943 | ); | |
1944 | ||
1945 | src = mputstr(src, " const boolean delay_close = e_xer"); | |
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" | |
1976 | " }\n" | |
1977 | , (want_namespaces ? "-(delay_close || (e_xer && (p_td.xer_bits & HAS_1UNTAGGED)))" : "") | |
1978 | , (want_namespaces ? " || delay_close" : "")); | |
1979 | } | |
1980 | ||
1981 | src = mputprintf(src, | |
1982 | " int sub_len=0%s;\n" | |
1983 | " p_flavor &= XER_MASK;\n", | |
1984 | num_attributes ? ", tmp_len; (void)tmp_len" : ""); | |
1985 | ||
1986 | if (sdef->xerUseQName) { | |
1987 | src = mputprintf(src, | |
1988 | " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n" | |
1989 | " if (field_%s.is_value()) {\n" | |
1990 | " p_buf.put_s(11, (cbyte*)\" xmlns:b0='\");\n" | |
af710487 | 1991 | " field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1, 0);\n" |
970ed795 EL |
1992 | " p_buf.put_c('\\'');\n" |
1993 | " }\n" | |
1994 | " if (p_td.xer_bits & XER_ATTRIBUTE) begin_attribute(p_td, p_buf);\n" | |
1995 | " else p_buf.put_c('>');\n" | |
1996 | " if (field_%s.is_value()) {\n" | |
1997 | " p_buf.put_s(3, (cbyte*)\"b0:\");\n" | |
1998 | " sub_len += 3;\n" | |
1999 | " }\n" | |
af710487 | 2000 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1, 0);\n" |
970ed795 EL |
2001 | " if (p_td.xer_bits & XER_ATTRIBUTE) p_buf.put_c('\\'');\n" |
2002 | " } else" /* no newline */ | |
2003 | , sdef->elements[0].name | |
2004 | , sdef->elements[0].name, sdef->elements[0].typegen | |
2005 | , sdef->elements[0].name | |
2006 | , sdef->elements[1].name, sdef->elements[1].typegen | |
2007 | ); | |
2008 | } | |
2009 | src = mputstr(src, " { // !QN\n"); | |
2010 | ||
2011 | /* First, the EMBED-VALUES member as an ordinary member if not doing EXER */ | |
2012 | if (sdef->xerEmbedValuesPossible) { | |
2013 | src = mputprintf(src, | |
970ed795 EL |
2014 | " if (!e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" |
2015 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2016 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
970ed795 | 2017 | " }\n" |
970ed795 EL |
2018 | , sdef->elements[0].dispname |
2019 | , sdef->elements[0].name, sdef->elements[0].typegen | |
2020 | ); | |
2021 | } | |
2022 | /* Then, the USE-ORDER member as an ordinary member when !EXER */ | |
2023 | if (sdef->xerUseOrderPossible) { | |
2024 | src = mputprintf(src, | |
2025 | " if (!e_xer && (p_td.xer_bits & USE_ORDER)) {\n" | |
af710487 | 2026 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
970ed795 EL |
2027 | " }\n" |
2028 | , sdef->elements[uo].name, sdef->elements[uo].typegen | |
2029 | ); | |
2030 | } | |
2031 | ||
2032 | if (start_at+num_attributes > sdef->nElements) FATAL_ERROR("defRecordClass1"); | |
2033 | ||
2034 | if (want_namespaces && (start_at < sdef->nElements)) { | |
2035 | src = mputstr(src, | |
2036 | " if (e_xer && num_collected) {\n" | |
2037 | " size_t num_ns;\n" | |
2038 | " for (num_ns = 0; num_ns < num_collected; ++num_ns) {\n" | |
2039 | " p_buf.put_s(strlen(collected_ns[num_ns]), (cbyte*)collected_ns[num_ns]);\n" | |
2040 | " Free(collected_ns[num_ns]);\n" | |
2041 | " }\n" | |
2042 | " Free(collected_ns);\n" | |
2043 | " }\n\n" | |
2044 | " if (def_ns) {\n" | |
2045 | " p_flavor &= ~DEF_NS_SQUASHED;\n" | |
2046 | " p_flavor |= DEF_NS_PRESENT;\n" | |
2047 | " }\n" | |
2048 | " else if (empty_ns_hack) {\n" | |
2049 | " p_buf.put_s(9, (cbyte*)\" xmlns=''\");\n" | |
2050 | " p_flavor &= ~DEF_NS_PRESENT;\n" | |
2051 | " p_flavor |= DEF_NS_SQUASHED;\n" | |
2052 | " }\n"); | |
2053 | } | |
2054 | ||
2055 | /* Then, all the attributes (not added to sub_len) */ | |
2056 | for ( i = start_at; i < start_at + num_attributes; ++i ) { | |
2057 | /* If the first component is a record-of with ANY-ATTRIBUTES, | |
2058 | * it has been taken care of because it looked like an EMBED-VALUES */ | |
2059 | if (i==0 && sdef->xerEmbedValuesPossible && (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) continue ; | |
2060 | src = mputprintf(src, | |
2061 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2062 | " tmp_len = field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
970ed795 EL |
2063 | " %ssub_len += tmp_len;\n" /* do not add if attribute and EXER */ |
2064 | , sdef->elements[i].dispname | |
2065 | , sdef->elements[i].name, sdef->elements[i].typegen | |
2066 | , sdef->elements[i].xerAttribute ? "if (!e_xer) " : "" | |
2067 | ); | |
2068 | } | |
2069 | ||
2070 | if (sdef->xerUseNilPossible) { | |
2071 | src = mputprintf(src, | |
2072 | " bool nil_attribute = e_xer && (p_td.xer_bits & USE_NIL) && !field_%s.ispresent();\n" | |
2073 | " if (nil_attribute) {\n" | |
2074 | " const namespace_t *control_ns = p_td.my_module->get_controlns();\n" | |
2075 | " p_buf.put_c(' ');\n" | |
2076 | " p_buf.put_s(strlen(control_ns->px), (cbyte*)control_ns->px);\n" | |
2077 | " p_buf.put_c(':');\n" | |
2078 | " p_buf.put_s(10, (cbyte*)\"nil='true'\");\n" | |
2079 | " }\n" | |
2080 | , sdef->elements[sdef->nElements-1].name | |
2081 | ); | |
2082 | } | |
2083 | ||
2084 | if (want_namespaces) { | |
2085 | /* there were some attributes. close the start tag left open */ | |
2086 | src = mputprintf(src, | |
2087 | " if (delay_close && (!omit_tag || chopped_chars)) p_buf.put_s(1%s, (cbyte*)\">\\n\");\n", /* close the start tag */ | |
2088 | (sdef->xerUntaggedOne /*|| sdef->xerUseNil*/) ? "" : "+is_indented" | |
2089 | ); | |
2090 | } | |
2091 | ||
2092 | if (sdef->xerEmbedValuesPossible) { | |
970ed795 EL |
2093 | src = mputprintf(src, |
2094 | " ec_1.set_msg(\"%s': \");\n" | |
2095 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" | |
970ed795 | 2096 | /* write the first string (must come AFTER the attributes) */ |
af710487 | 2097 | " if (field_%s.size_of() > 0) {\n" |
2098 | " sub_len += field_%s[0].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" | |
2099 | " }\n" | |
970ed795 | 2100 | " }\n" |
af710487 | 2101 | , sdef->elements[0].dispname, sdef->elements[0].name, sdef->elements[0].name); |
970ed795 EL |
2102 | if (want_namespaces) { /* here's another chance */ |
2103 | src = mputprintf(src, | |
2104 | " else if ( !(p_td.xer_bits & EMBED_VALUES)) {\n" | |
af710487 | 2105 | " %sfield_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
970ed795 EL |
2106 | " }\n" |
2107 | , ((sdef->elements[0].xerAnyKind & ANY_ATTRIB_BIT) ? "" : "sub_len += " ) | |
2108 | , sdef->elements[0].name, sdef->elements[0].typegen | |
2109 | ); | |
2110 | } | |
2111 | } | |
2112 | ||
2113 | /* Then, all the non-attributes. Structuring the code like this depends on | |
2114 | * all attributes appearing before all non-attributes (excluding | |
2115 | * special members for EMBED-VALUES, USE-ORDER, etc.) */ | |
af710487 | 2116 | if (sdef->xerEmbedValuesPossible) { |
2117 | src = mputprintf(src, | |
2118 | " embed_values_enc_struct_t* emb_val = 0;\n" | |
2119 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && field_%s.size_of() > 1) {\n" | |
2120 | " emb_val = new embed_values_enc_struct_t;\n" | |
a38c6d4c | 2121 | /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated |
2122 | * record of universal charstring, so it needs a cast to avoid a compilation error */ | |
2123 | " emb_val->embval_array%s = (const PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s;\n" | |
2124 | " emb_val->embval_array%s = NULL;\n" | |
af710487 | 2125 | " emb_val->embval_index = 1;\n" |
a38c6d4c | 2126 | " }\n" |
2127 | , sdef->elements[0].name | |
2128 | , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg" | |
2129 | , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : "" | |
2130 | , sdef->elements[0].name | |
2131 | , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt"); | |
af710487 | 2132 | } |
2133 | ||
970ed795 EL |
2134 | if (sdef->xerUseOrderPossible) { |
2135 | int max_ordered = sdef->nElements - start_at - num_attributes; | |
2136 | int min_ordered = max_ordered - n_opt_elements; | |
2137 | size_t offset = 0; | |
2138 | size_t base = i; | |
2139 | size_t limit = sdef->nElements; | |
2140 | /* base and limit are indexes into sdef->elements[] */ | |
2141 | src = mputprintf(src, | |
2142 | " int dis_order = e_xer && (p_td.xer_bits & USE_ORDER);\n" | |
2143 | " int to_send = field_%s.lengthof();\n" | |
2144 | " int uo_limit = dis_order ? to_send : %lu;\n" | |
2145 | , sdef->elements[start_at-1].name | |
2146 | , (unsigned long)(limit - base) | |
2147 | ); | |
2148 | if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */ | |
2149 | base = sdef->nElements; | |
2150 | limit = sdef->totalElements; | |
2151 | min_ordered = max_ordered = limit - base; | |
2152 | src = mputprintf(src, | |
2153 | " if (!nil_attribute) {\n" | |
2154 | "%s" | |
af710487 | 2155 | " if (!e_xer) sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, 0);\n" |
970ed795 EL |
2156 | " else" /* no newline */ |
2157 | , (sdef->xerUseNilPossible ? " if (!(p_td.xer_bits & USE_ORDER)) p_flavor |= (p_td.xer_bits & USE_NIL);\n" : "") | |
2158 | /* If USE-ORDER is on, the tag-removing effect of USE-NIL has been | |
2159 | * performed by calling the sub-fields directly. */ | |
2160 | , sdef->elements[sdef->nElements-1].name | |
2161 | , sdef->elements[sdef->nElements-1].typegen | |
2162 | ); | |
2163 | } | |
2164 | ||
2165 | /* check incorrect data */ | |
2166 | src = mputprintf(src, | |
2167 | " {\n" | |
2168 | " if (to_send < %d || to_send > %d) {\n" | |
2169 | " ec_1.set_msg(\"%s': \");\n" | |
2170 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, " | |
2171 | "\"Wrong number of USE-ORDER, %%d instead of %d..%d\", to_send);\n" | |
2172 | " uo_limit = -1;\n" /* squash the loop */ | |
2173 | " }\n" | |
2174 | " else {\n" /* check duplicates */ | |
2175 | " int *seen = new int [to_send];\n" | |
2176 | " int num_seen = 0;\n" | |
2177 | " for (int ei = 0; ei < to_send; ++ei) {\n" | |
2178 | " int val = field_%s[ei];\n" | |
2179 | " for (int x = 0; x < num_seen; ++x) {\n" | |
2180 | " if (val == seen[x]) { // complain\n" | |
2181 | " ec_1.set_msg(\"%s': \");\n" | |
2182 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n" | |
2183 | " \"Duplicate value for USE-ORDER\");\n" | |
2184 | " uo_limit = -1; // don't bother sending anything\n" | |
2185 | " goto trouble;\n" | |
2186 | " }\n" | |
2187 | " }\n" | |
2188 | " seen[num_seen++] = val;\n" | |
2189 | " }\n" | |
2190 | "trouble:\n" | |
2191 | " delete [] seen;" | |
2192 | " }\n" | |
2193 | " " | |
2194 | , min_ordered, max_ordered | |
2195 | , sdef->elements[start_at-1].dispname | |
2196 | , min_ordered, max_ordered | |
2197 | , sdef->elements[start_at-1].name | |
2198 | , sdef->elements[start_at-1].dispname | |
2199 | ); | |
2200 | ||
2201 | src = mputprintf(src, | |
2202 | " for (int i = 0; i < uo_limit; ++i) {\n" | |
2203 | " switch (dis_order ? (int)field_%s[i] : i) {\n" | |
2204 | , sdef->elements[start_at-1].name | |
2205 | ); | |
2206 | for ( i = base; i < limit; ++i ) { | |
2207 | src = mputprintf(src, | |
2208 | " case %lu:\n" | |
2209 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2210 | " sub_len += field_%s%s%s%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, %s);\n" |
970ed795 EL |
2211 | |
2212 | , (unsigned long)offset++ | |
2213 | , sdef->elements[i].dispname | |
2214 | , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name : sdef->elements[i].name) | |
2215 | , (sdef->xerUseNilPossible ? "()." : "") | |
2216 | , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") | |
2217 | , (sdef->xerUseNilPossible ? "()" : "") | |
2218 | , sdef->elements[i].typegen | |
af710487 | 2219 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0" |
970ed795 EL |
2220 | ); |
2221 | ||
2222 | src = mputstr(src, " break;\n"); | |
2223 | } /* next element */ | |
2224 | src = mputstr(src, | |
2225 | " default:\n" | |
2226 | " TTCN_error(\"Runaway value while encoding USE-ORDER\");\n" | |
2227 | " break;\n" /* cannot happen, complain */ | |
2228 | " }\n"); | |
2229 | ||
2230 | if (sdef->xerEmbedValuesPossible) { | |
2231 | src = mputprintf(src, | |
af710487 | 2232 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n" |
a38c6d4c | 2233 | " emb_val->embval_index < field_%s.size_of()) { // embed-val\n" |
af710487 | 2234 | " field_%s[emb_val->embval_index].XER_encode(\n" |
2235 | " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" | |
2236 | " ++emb_val->embval_index;\n" | |
970ed795 | 2237 | " }\n" |
a38c6d4c | 2238 | , sdef->elements[0].name, sdef->elements[0].name); |
970ed795 EL |
2239 | } |
2240 | ||
2241 | ||
2242 | src = mputstr(src, | |
2243 | " }\n" /* end of loop */ | |
2244 | " } // exer\n"); | |
2245 | if (sdef->xerUseNilPossible) { | |
2246 | src = mputstr(src, " } // nil_attr\n"); | |
2247 | } | |
2248 | } | |
2249 | else /* not USE-ORDER */ | |
2250 | for ( /* continue with i */; i < sdef->nElements; ++i ) { | |
2251 | src = mputprintf(src, | |
2252 | " ec_1.set_msg(\"%s': \");\n" | |
2253 | , sdef->elements[i].dispname | |
2254 | ); | |
2255 | src = mputprintf(src, | |
af710487 | 2256 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor%s, p_indent+!omit_tag, %s);\n" |
970ed795 EL |
2257 | , sdef->elements[i].name, sdef->elements[i].typegen |
2258 | , sdef->xerUseNilPossible ? "| (p_td.xer_bits & USE_NIL)" : "" | |
af710487 | 2259 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0" |
970ed795 EL |
2260 | ); |
2261 | ||
2262 | if (sdef->xerEmbedValuesPossible) { | |
970ed795 | 2263 | src = mputprintf(src, |
af710487 | 2264 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n" |
a38c6d4c | 2265 | " emb_val->embval_index < field_%s.size_of()) {\n" |
af710487 | 2266 | " field_%s[emb_val->embval_index].XER_encode(\n" |
2267 | " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" | |
2268 | " ++emb_val->embval_index;\n" | |
970ed795 | 2269 | " }\n" |
a38c6d4c | 2270 | , sdef->elements[0].name, sdef->elements[0].name); |
970ed795 EL |
2271 | } |
2272 | } /* next field when not USE-ORDER */ | |
2273 | ||
af710487 | 2274 | if (sdef->xerEmbedValuesPossible) { |
2275 | src = mputprintf(src, | |
2276 | " if (0 != emb_val) {\n" | |
a38c6d4c | 2277 | " if (emb_val->embval_index < field_%s.size_of()) {\n" |
af710487 | 2278 | " ec_1.set_msg(\"%s': \");\n" |
2279 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n" | |
2280 | " \"Too many EMBED-VALUEs specified: %%d (expected %%d or less)\",\n" | |
a38c6d4c | 2281 | " field_%s.size_of(), emb_val->embval_index);\n" |
af710487 | 2282 | " }\n" |
2283 | " delete emb_val;\n" | |
2284 | " }\n" | |
a38c6d4c | 2285 | , sdef->elements[0].name, sdef->elements[0].name, sdef->elements[0].name); |
af710487 | 2286 | } |
2287 | ||
970ed795 EL |
2288 | src = mputstr(src, " } // QN?\n"); |
2289 | ||
2290 | { | |
2291 | src = mputprintf(src, | |
2292 | " if (!omit_tag) {\n" | |
2293 | " if (sub_len) {\n" /* something was written, now an end tag */ | |
2294 | " if (is_indented && !(e_xer && (p_td.xer_bits & (HAS_1UNTAGGED | USE_QNAME)))) {\n" | |
2295 | " switch ((int)(e_xer && (p_td.xer_bits & USE_NIL))) {\n" | |
2296 | " case 1: {\n" | |
2297 | " const unsigned char *buf_end = p_buf.get_data() + (p_buf.get_len()-1);\n" | |
2298 | " if (buf_end[-1] != '>' || *buf_end != '\\n') break;\n" | |
2299 | /* else fall through */ | |
2300 | " }\n" | |
2301 | " case 0:\n" | |
2302 | " do_indent(p_buf, p_indent);\n" | |
2303 | " break;\n" | |
2304 | " }\n" | |
2305 | " }\n" | |
2306 | " p_buf.put_c('<');\n" | |
2307 | " p_buf.put_c('/');\n" | |
2308 | " if (e_xer) write_ns_prefix(p_td, p_buf);\n" | |
2309 | " p_buf.put_s((size_t)p_td.namelens[e_xer]-!is_indented, (cbyte*)p_td.names[e_xer]);\n" | |
2310 | " } else {\n" /* need to generate an empty element tag */ | |
2311 | " p_buf.increase_length(%s-1);\n" /* decrease length */ | |
2312 | " p_buf.put_s((size_t)2+is_indented, (cbyte*)\"/>\\n\");\n" | |
2313 | " }}\n" | |
2314 | , (sdef->xerUntaggedOne /*|| sdef->xerUseNil*/) ? "" : "-is_indented" | |
2315 | ); | |
2316 | } | |
2317 | src = mputstr(src, | |
2318 | " return (int)p_buf.get_len() - encoded_length;\n" | |
2319 | "}\n\n"); | |
2320 | ||
2321 | #ifndef NDEBUG | |
2322 | src = mputprintf(src, "// %s has%s%s%s%s%s%s%s%s%s\n" | |
2323 | "// written by %s in " __FILE__ " at %d\n" | |
2324 | , name | |
2325 | , (sdef->xerUntagged ? " UNTAGGED" : "") | |
2326 | , (sdef->xerUntaggedOne ? "1" : "") | |
2327 | , (sdef->xerUseNilPossible ? " USE_NIL?" : "") | |
2328 | , (sdef->xerUseOrderPossible ? " USE_ORDER?" : "") | |
2329 | , (sdef->xerUseQName ? " USE_QNAME" : "") | |
2330 | , (sdef->xerUseTypeAttr ? " USE_TYPE_ATTR" : "") | |
2331 | , (sdef->xerUseUnion ? " USE-UNION" : "") | |
2332 | , (sdef->xerHasNamespaces ? " namespace" : "") | |
2333 | , (sdef->xerEmbedValuesPossible ? " EMBED?" : "") | |
2334 | , __FUNCTION__, __LINE__ | |
2335 | ); | |
2336 | #endif | |
2337 | ||
2338 | src = mputprintf(src, /* XERSTUFF decodegen for record/SEQUENCE*/ | |
2339 | "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader," | |
af710487 | 2340 | " unsigned int p_flavor, embed_values_dec_struct_t*)\n" |
970ed795 EL |
2341 | "{\n" |
2342 | " bound_flag = TRUE;\n" | |
2343 | /* Remove XER_LIST, XER_RECOF from p_flavor. This is not required | |
2344 | * for is_exer (which tests another bit), but for subsequent code. */ | |
2345 | " int e_xer = is_exer(p_flavor);\n" | |
2346 | " int xerbits = p_td.xer_bits;\n" | |
2347 | " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n" | |
2348 | " const boolean omit_tag = e_xer && ((xerbits & (UNTAGGED|XER_ATTRIBUTE)) " | |
2349 | "|| (p_flavor & (USE_NIL|USE_TYPE_ATTR)));\n" | |
2350 | "%s" | |
2351 | " const boolean parent_tag = e_xer && (p_flavor & (USE_TYPE_ATTR));\n" | |
2352 | " (void)parent_tag;\n" | |
2353 | " p_flavor &= XER_MASK;\n" /* also removes "toplevel" bit */ | |
2354 | " int rd_ok, xml_depth=-1, type;\n" | |
2355 | " {\n" /* scope for the error contexts */ | |
2356 | , name | |
2357 | , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0) | |
2358 | ? " boolean tag_closed = (p_flavor & PARENT_CLOSED) != 0;\n" : "") | |
2359 | /* tag_closed needed for non-attribute normal members only, | |
2360 | * or if EMBED-VALUES is possible, but isn't. */ | |
2361 | ); | |
2362 | ||
2363 | if (sdef->xerUseNilPossible) src = mputstr(src, | |
2364 | " boolean nil_attribute = FALSE;\n"); | |
2365 | ||
2366 | src = mputprintf(src, | |
2367 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" | |
2368 | " TTCN_EncDec_ErrorContext ec_1;\n" | |
2369 | " if (!omit_tag) for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" | |
2370 | " type = p_reader.NodeType();\n" | |
2371 | " if (type==XML_READER_TYPE_ELEMENT) {\n" | |
2372 | " verify_name(p_reader, p_td, e_xer);\n" | |
2373 | " xml_depth = p_reader.Depth();\n" | |
2374 | "%s" | |
2375 | " break;\n" | |
2376 | " }\n" | |
2377 | " }\n" | |
2378 | , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0) | |
2379 | ? " tag_closed = p_reader.IsEmptyElement();\n": "") | |
2380 | ); | |
2381 | ||
2382 | ||
2383 | if (sdef->xerUseQName) { | |
2384 | src = mputprintf(src, | |
2385 | " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n" | |
2386 | " if (p_td.xer_bits & XER_ATTRIBUTE) rd_ok = 1;\n" | |
2387 | " else for (rd_ok = p_reader.Read(); rd_ok == 1; rd_ok = p_reader.Read()) {\n" | |
2388 | " type = p_reader.NodeType();\n" | |
2389 | " if (type == XML_READER_TYPE_TEXT) break;\n" | |
2390 | " }\n" | |
2391 | " if (rd_ok==1) {\n" | |
2392 | " xmlChar *new_val = p_reader.NewValue();\n" | |
2393 | " xmlChar *v_npfx = (xmlChar*)strchr((char*)new_val, ':');\n" | |
2394 | " xmlChar *v_pfx;\n" | |
2395 | " if (v_npfx != NULL) {\n" | |
2396 | " *v_npfx++ = '\\0';\n" | |
2397 | " v_pfx = new_val;\n" | |
2398 | " }\n" | |
2399 | " else {\n" | |
2400 | " v_npfx = new_val;\n" | |
2401 | " v_pfx = NULL;\n" | |
2402 | " }\n" | |
2403 | " xmlChar *q_ns = p_reader.LookupNamespace(v_pfx);\n" | |
2404 | " if (q_ns) field_%s = (const char*)q_ns;\n" | |
2405 | " else field_%s = OMIT_VALUE;\n" | |
2406 | " field_%s = (const char*)v_npfx;\n" | |
2407 | " xmlFree(q_ns);\n" | |
2408 | " xmlFree(new_val);\n" | |
2409 | " }\n" | |
2410 | " } else {\n" | |
2411 | , sdef->elements[0].name | |
2412 | , sdef->elements[0].name | |
2413 | , sdef->elements[1].name | |
2414 | ); | |
2415 | } /* QName */ | |
2416 | ||
2417 | if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { | |
2418 | src = mputstr(src, "if (e_xer) {\n"); | |
2419 | } | |
2420 | ||
2421 | /* ******************************************************************** | |
2422 | * ATTRIBUTES | |
2423 | ***************************/ | |
2424 | if (num_attributes || sdef->xerUseNilPossible /* maybe QNAME too ? */) { | |
2425 | size_t aaa; | |
2426 | src = mputstr(src, " if (!omit_tag || parent_tag) {\n"); | |
2427 | ||
2428 | /* Prepare for attributes not present in the XML. | |
2429 | * Set all attributes with defaultForEmpty to the D-F-E value. | |
2430 | * Set all optional components with ATTRIBUTE to omit. | |
2431 | * | |
2432 | * If EMBED-VALUES is possible, the first component can't be optional. | |
2433 | * The same is true for the USE-ORDER component. Hence start_at. */ | |
2434 | for (aaa = start_at; aaa < start_at + num_attributes; ++aaa) { | |
2435 | if (sdef->elements[aaa].xerAttribute) { /* "proper" ATTRIBUTE */ | |
2436 | src = mputprintf(src, | |
2437 | " if (%s_xer_.dfeValue) field_%s = " | |
2438 | "*static_cast<const %s*>(%s_xer_.dfeValue);\n" | |
2439 | , sdef->elements[aaa].typegen, sdef->elements[aaa].name | |
2440 | , sdef->elements[aaa].type , sdef->elements[aaa].typegen); | |
2441 | if (sdef->elements[aaa].isOptional) src = mputprintf(src, | |
2442 | " else field_%s = OMIT_VALUE;\n", sdef->elements[aaa].name); | |
2443 | } | |
2444 | else { /* must be the ANY-ATTRIBUTES */ | |
2445 | src = mputprintf(src, | |
af710487 | 2446 | " field_%s%s;\n" |
2447 | , sdef->elements[aaa].name | |
2448 | , sdef->elements[aaa].isOptional ? " = OMIT_VALUE" : ".set_size(0)"); | |
970ed795 EL |
2449 | } |
2450 | } | |
2451 | ||
2452 | if (num_attributes==0 /* therefore sdef->xerUseNilPossible is true */ ) { | |
2453 | /* Only the "nil" attribute may be present. If there is no USE-NIL, | |
2454 | * then there can be no attributes at all. */ | |
2455 | src = mputstr(src, | |
2456 | " if (e_xer && (p_td.xer_bits & (USE_NIL|USE_TYPE_ATTR))) {\n"); | |
2457 | } | |
2458 | ||
2459 | if (aa_index > -1) src = mputstr(src, " size_t num_aa = 0;\n"); | |
2460 | if (sdef->xerUseNilPossible) { | |
2461 | src = mputstr(src, | |
2462 | " static const namespace_t *control_ns = p_td.my_module->get_controlns();\n"); | |
2463 | } | |
2464 | ||
2465 | src = mputstr(src, | |
2466 | " for (rd_ok = p_reader.MoveToFirstAttribute(); rd_ok==1 && " | |
2467 | "p_reader.NodeType()==XML_READER_TYPE_ATTRIBUTE; " | |
2468 | "rd_ok = p_reader.AdvanceAttribute()) {\n" | |
2469 | " if (p_reader.IsNamespaceDecl()) continue;\n"); | |
2470 | /* if the only attribute is ANY-ATTRIBUTE, it doesn't need attr_name */ | |
2471 | if (num_attributes==1 && aa_index!=-1 /*&& !sdef->xerUseNilPossible*/) {} | |
2472 | else { | |
2473 | src = mputstr(src, | |
2474 | " const char *attr_name = (const char*)p_reader.LocalName();\n" | |
2475 | " const char *ns_uri = (const char*)p_reader.NamespaceUri();\n"); | |
2476 | } | |
2477 | ||
2478 | if (sdef->xerUseNilPossible) { | |
2479 | src = mputprintf(src, | |
2480 | " const char *prefix = (const char*)p_reader.Prefix();\n" | |
2481 | /* prefix may be NULL, control_ns->px is never NULL or empty */ | |
2482 | " if (prefix && !strcmp(prefix, control_ns->px)\n" | |
2483 | " && !strcmp((const char*)p_reader.LocalName(), \"nil\")){\n" | |
2484 | " const char *value = (const char*)p_reader.Value();\n" | |
2485 | " if (!strcmp(value, \"1\") || !strcmp(value, \"true\")) {\n" | |
2486 | " field_%s = OMIT_VALUE;\n" | |
2487 | " nil_attribute = TRUE;\n" | |
2488 | /* found the "nil" attribute */ | |
2489 | " }\n" | |
2490 | " } else" | |
2491 | , sdef->elements[sdef->nElements-1].name); | |
2492 | } | |
2493 | ||
2494 | for (i = start_at; i < start_at + num_attributes; ++i) { | |
2495 | if (i == aa_index) continue; /* ANY_ATTR. is handled below */ | |
2496 | src = mputprintf(src, | |
2497 | " if (check_name(attr_name, %s_xer_, 1) && check_namespace(ns_uri, %s_xer_)) {\n" | |
2498 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2499 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), 0);\n" |
970ed795 EL |
2500 | " } else" |
2501 | , sdef->elements[i].typegen, sdef->elements[i].typegen | |
2502 | , sdef->elements[i].dispname /* set_msg */ | |
2503 | , sdef->elements[i].name, sdef->elements[i].typegen | |
2504 | ); | |
2505 | } | |
2506 | ||
2507 | if (sdef->control_ns_prefix && !(num_attributes==1 && aa_index!=-1)) { | |
2508 | src = mputprintf(src, | |
2509 | " if (parent_tag && !strcmp(attr_name, \"type\") " | |
2510 | "&& !strcmp((const char*)p_reader.Prefix(), \"%s\")) {} else\n" | |
2511 | , sdef->control_ns_prefix); | |
2512 | /* xsi:type; already processed by parent with USE-UNION or USE-TYPE */ | |
2513 | } | |
2514 | ||
2515 | ||
2516 | if (aa_index >= 0) { | |
2517 | /* we are at a dangling else */ | |
2518 | src = mputprintf(src, | |
2519 | " {\n" | |
af710487 | 2520 | " TTCN_EncDec_ErrorContext ec_0(\"Attribute %%d: \", (int)num_aa);\n" |
2521 | " UNIVERSAL_CHARSTRING& new_elem = field_%s%s[num_aa++];\n" | |
970ed795 EL |
2522 | /* Construct the AnyAttributeFormat (X.693amd1, 18.2.6) */ |
2523 | " TTCN_Buffer aabuf;\n" | |
2524 | " const xmlChar *x_name = p_reader.LocalName();\n" | |
2525 | " const xmlChar *x_val = p_reader.Value();\n" | |
2526 | " const xmlChar *x_uri = p_reader.NamespaceUri();\n" | |
2527 | " if (%s_xer_.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n" | |
2528 | " check_namespace_restrictions(%s_xer_, (const char*)x_uri);\n" | |
2529 | " }\n" | |
2530 | /* We don't care about p_reader.Prefix() */ | |
2531 | /* Using strlen to count bytes */ | |
2532 | " aabuf.put_s(x_uri ? strlen((const char*)x_uri) : 0, x_uri);\n" | |
2533 | " if (x_uri && *x_uri) aabuf.put_c(' ');\n" | |
2534 | " aabuf.put_s(x_name ? strlen((const char*)x_name) : 0, x_name);\n" | |
2535 | " aabuf.put_c('=');\n" | |
2536 | " aabuf.put_c('\"');\n" | |
2537 | " aabuf.put_s(x_val ? strlen((const char*)x_val) : 0, x_val);\n" | |
2538 | " aabuf.put_c('\"');\n" | |
2539 | " new_elem.decode_utf8(aabuf.get_len(), aabuf.get_data());\n" | |
2540 | " } \n" | |
2541 | , sdef->elements[aa_index].name | |
af710487 | 2542 | , sdef->elements[aa_index].isOptional ? "()" : "" |
970ed795 EL |
2543 | , sdef->elements[aa_index].typegen, sdef->elements[aa_index].typegen |
2544 | ); | |
2545 | } | |
2546 | else { | |
2547 | /* we are at a dangling else */ | |
2548 | src = mputstr(src, " {\n"); | |
2549 | if (sdef->control_ns_prefix) { | |
2550 | src = mputprintf(src, | |
2551 | // Lastly check for the xsi:schemaLocation attribute, this does not | |
2552 | // affect TTCN-3, but it shouldn't cause a DTE | |
2553 | " if (!p_reader.LocalName() || strcmp((const char*)p_reader.LocalName(), \"schemaLocation\") ||\n" | |
2554 | " !p_reader.Prefix() || strcmp((const char*)p_reader.Prefix(), \"%s\"))\n" | |
2555 | , sdef->control_ns_prefix); | |
2556 | } | |
2557 | src = mputstr(src, | |
2558 | " {\n" | |
2559 | " ec_0.set_msg(\" \"); ec_1.set_msg(\" \");\n" /* we have no component */ | |
2560 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, " | |
2561 | "\"Unexpected attribute '%s', ns '%s'\", attr_name, ns_uri ? ns_uri : \"\");\n" | |
2562 | " }\n" | |
2563 | " }\n"); | |
2564 | } | |
2565 | src = mputstr(src, " }\n"); /* for */ | |
2566 | ||
2567 | for (i = start_at; i < start_at + num_attributes; ++i) { | |
2568 | if (sdef->elements[i].isOptional) continue; /* allowed to be missing */ | |
2569 | src = mputprintf(src, " if (!field_%s.is_bound()) " | |
2570 | "TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, " | |
2571 | "\"Missing attribute '%s'\");\n" | |
2572 | , sdef->elements[i].name, sdef->elements[i].dispname); | |
2573 | } | |
2574 | ||
2575 | if (num_attributes==0) src = mputstr(src, " }\n"); /* if USE_NIL or USE_TYPE_ATTR */ | |
2576 | src = mputstr(src, " }\n"); /* process (attributes) in (own or parent) tag */ | |
2577 | } /* * * * * * * * * end if(attributes...) * * * * * * * * * * * * */ | |
2578 | ||
2579 | src = mputstr(src, | |
2580 | " if ((!omit_tag || parent_tag) && !p_reader.IsEmptyElement()) " | |
2581 | "rd_ok = p_reader.Read();\n"); | |
2582 | ||
2583 | if (sdef->xerEmbedValuesPossible && num_attributes==0) { | |
2584 | /* EMBED-VALUES possible, but isn't: the first component is a non-special | |
2585 | * record of strings. This means there are no attributes, unless | |
2586 | * the first component is an ATTRIBUTE or ANY-ATTRIBUTES. */ | |
2587 | src = mputprintf(src, | |
2588 | " if (!(p_td.xer_bits & EMBED_VALUES)) {\n" | |
2589 | " ec_1.set_msg(\"%s': \");\n" | |
2590 | " field_%s.XER_decode(%s_xer_, p_reader, " | |
af710487 | 2591 | "p_flavor | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0), 0);\n" |
970ed795 EL |
2592 | " }\n" |
2593 | , sdef->elements[0].dispname | |
2594 | , sdef->elements[0].name, sdef->elements[0].typegen | |
2595 | ); | |
2596 | } | |
2597 | ||
2598 | if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { | |
2599 | src = mputstr(src, | |
2600 | "} else {\n" /* now the non-EXER processing of (would-be) attributes */ | |
2601 | " if (!p_reader.IsEmptyElement()) p_reader.Read();\n" | |
2602 | ); | |
2603 | } | |
2604 | ||
2605 | if (sdef->xerUseOrderPossible) { | |
2606 | src = mputstr(src, | |
2607 | " if (e_xer && p_td.xer_bits & USE_ORDER) ; else {"); | |
2608 | } | |
2609 | ||
2610 | if (start_at + num_attributes > 0) | |
2611 | { | |
2612 | /* No attributes nor USE-NIL: | |
2613 | * Just decode the specials and would-be attributes. */ | |
2614 | ||
2615 | // FIXME: WTF is this? | |
2616 | //if (sdef->xerEmbedValuesPossible) { | |
2617 | // /* Only decode the first member if it really is EMBED-VALUES */ | |
2618 | // src = mputprintf(src, "if (p_td.xer_bits & EMBED_VALUES) "); | |
2619 | //} | |
2620 | for (i = 0; i < start_at + num_attributes; ++i) { | |
2621 | /* Decode the field */ | |
2622 | src = mputprintf(src, | |
2623 | " {\n" | |
2624 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2625 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), 0);\n" |
970ed795 EL |
2626 | " }\n" |
2627 | , sdef->elements[i].dispname | |
2628 | , sdef->elements[i].name, sdef->elements[i].typegen | |
2629 | ); | |
2630 | } /* next field */ | |
2631 | ||
2632 | if (sdef->xerUseOrderPossible) { | |
2633 | src = mputstr(src, " }\n"); | |
2634 | } | |
2635 | } | |
2636 | ||
2637 | if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { | |
2638 | src = mputstr(src, "}\n"); | |
2639 | } | |
af710487 | 2640 | |
2641 | if (sdef->xerEmbedValuesPossible) { | |
2642 | src = mputprintf(src, | |
2643 | " embed_values_dec_struct_t* emb_val = 0;\n" | |
2644 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" | |
2645 | " emb_val = new embed_values_dec_struct_t;\n" | |
a38c6d4c | 2646 | /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated |
2647 | * record of universal charstring, so it needs a cast to avoid a compilation error */ | |
2648 | " emb_val->embval_array%s = (PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s;\n" | |
2649 | " emb_val->embval_array%s = NULL;\n" | |
af710487 | 2650 | " emb_val->embval_index = 0;\n" |
2651 | " field_%s.set_size(0);\n" | |
a38c6d4c | 2652 | " }\n" |
2653 | , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg" | |
2654 | , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : "" | |
2655 | , sdef->elements[0].name | |
2656 | , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt" | |
2657 | , sdef->elements[0].name); | |
af710487 | 2658 | } |
970ed795 EL |
2659 | |
2660 | if (sdef->xerUseOrderPossible) { | |
2661 | size_t begin = start_at + num_attributes; /* first non-attribute */ | |
2662 | size_t end = sdef->nElements; | |
2663 | size_t n_optionals = 0, n_embed; | |
2664 | int max_ordered = sdef->nElements - start_at - num_attributes; | |
2665 | int min_ordered = max_ordered - n_opt_elements; | |
2666 | if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */ | |
2667 | begin = sdef->nElements; | |
2668 | end = sdef->totalElements; | |
2669 | } | |
2670 | n_embed = end - begin; | |
2671 | ||
2672 | src = mputstr(src, | |
2673 | " if (e_xer && (p_td.xer_bits & USE_ORDER)) {\n" | |
2674 | ); | |
2675 | for (i = begin; i < end; ++i) { | |
2676 | if (sdef->elements[i].isOptional) { | |
2677 | src = mputprintf(src, " field_%s = OMIT_VALUE;\n", | |
2678 | sdef->elements[i].name); | |
2679 | ++n_optionals; | |
2680 | } | |
2681 | } | |
2682 | ||
970ed795 EL |
2683 | if (sdef->xerUseNilPossible) { /* USE-NIL and USE-ORDER */ |
2684 | src = mputprintf(src, | |
2685 | " if (nil_attribute) field_%s.set_size(0);\n else" | |
2686 | , sdef->elements[uo].name); | |
2687 | } | |
2688 | ||
2689 | src = mputprintf(src, | |
2690 | " {\n" | |
2691 | " field_%s.set_size(0);\n" | |
2692 | " int e_val, num_seen = 0, *seen_f = new int[%lu];\n" | |
970ed795 EL |
2693 | , sdef->elements[uo].name |
2694 | , (unsigned long)(n_embed) | |
af710487 | 2695 | ); |
2696 | if (sdef->xerEmbedValuesPossible) { | |
2697 | // The index of the latest embedded value can change outside of this function | |
2698 | // (if the field is a untagged record of), in this case the next value should | |
2699 | // be ignored, as it's already been handled by the record of | |
2700 | src = mputstr(src, " int last_embval_index = 0;\n"); | |
2701 | } | |
2702 | src = mputprintf(src, | |
2703 | " for (int i=0; i < %lu; ++i) {\n" | |
2704 | " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" | |
970ed795 EL |
2705 | , (unsigned long)(n_embed)); |
2706 | ||
2707 | if (sdef->xerEmbedValuesPossible) { | |
2708 | /* read and store embedValues text if present */ | |
2709 | src = mputprintf(src, | |
af710487 | 2710 | " if (0 != emb_val && p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" |
970ed795 | 2711 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" |
af710487 | 2712 | " field_%s[emb_val->embval_index] = emb_ustr;\n" |
970ed795 EL |
2713 | " }\n" |
2714 | , sdef->elements[0].name); | |
2715 | } | |
2716 | ||
2717 | src = mputstr(src, | |
2718 | " type = p_reader.NodeType();\n" | |
2719 | " if (type==XML_READER_TYPE_ELEMENT) break;\n" | |
2720 | " }\n" | |
2721 | " if (rd_ok != 1) break;\n" | |
2722 | " const char * x_name = (const char*)p_reader.LocalName();\n" /* Name or LocalName ? */); | |
af710487 | 2723 | |
2724 | if (sdef->xerEmbedValuesPossible) { | |
2725 | src = mputstr(src, | |
2726 | " if (0 != emb_val) {\n" | |
2727 | " if (last_embval_index == emb_val->embval_index) {\n" | |
2728 | " ++emb_val->embval_index;\n" | |
2729 | " }\n" | |
2730 | " last_embval_index = emb_val->embval_index;\n" | |
2731 | " }\n"); | |
2732 | } | |
970ed795 EL |
2733 | |
2734 | /* * * * * code for USE-ORDER * * * * */ | |
2735 | ||
2736 | for (i = begin; i < end; ++i) { | |
2737 | // Check non-anyElement fields first | |
2738 | if (!(sdef->elements[i].xerAnyKind & ANY_ELEM_BIT)) { | |
2739 | src = mputprintf(src, | |
2740 | " if (check_name(x_name, %s_xer_, 1)) {\n" | |
2741 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2742 | " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, %s);\n" |
970ed795 EL |
2743 | , sdef->elements[i].typegen |
2744 | , sdef->elements[i].dispname | |
970ed795 EL |
2745 | , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name) |
2746 | , (sdef->xerUseNilPossible ? "()." : "") | |
2747 | , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") | |
2748 | , (sdef->xerUseNilPossible ? "()" : "") | |
2749 | , sdef->elements[i].typegen | |
af710487 | 2750 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0" |
970ed795 EL |
2751 | ); |
2752 | src = mputprintf(src, | |
af710487 | 2753 | " field_%s[i] = e_val = %s::of_type::%s;\n" |
2754 | , sdef->elements[uo].name | |
2755 | , sdef->elements[uo].typegen, sdef->elements[i].name); | |
970ed795 EL |
2756 | src = mputstr(src, " }\n else"); |
2757 | } | |
2758 | } | |
2759 | src = mputstr(src, | |
2760 | " {\n" | |
2761 | " boolean any_found = false;\n" | |
2762 | " if (!any_found)"); | |
2763 | for (i = begin; i < end; ++i) { | |
2764 | // Check anyElement fields after all other fields | |
2765 | if (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT) { | |
2766 | src = mputstr(src, " {\n"); | |
2767 | src = mputprintf(src, | |
2768 | " e_val = %s::of_type::%s;\n" | |
2769 | , sdef->elements[uo].typegen, sdef->elements[i].name); | |
2770 | src = mputprintf(src, | |
2771 | " boolean next_any = false;\n" | |
2772 | " for (int d_f = 0; d_f < num_seen; ++d_f) {\n" | |
2773 | " if (e_val == seen_f[d_f]) {\n" | |
2774 | " next_any = true;\n" | |
2775 | " }\n" | |
2776 | " }\n" | |
2777 | " if (!next_any) {\n" | |
2778 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2779 | " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, 0);\n" |
970ed795 EL |
2780 | " field_%s[i] = e_val;\n" |
2781 | " any_found = true;\n" | |
2782 | " }\n" | |
2783 | " }\n" | |
2784 | " if (!any_found)" | |
2785 | , sdef->elements[i].dispname | |
2786 | , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name) | |
2787 | , (sdef->xerUseNilPossible ? "()." : "") | |
2788 | , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") | |
2789 | , (sdef->xerUseNilPossible ? "()" : "") | |
2790 | , sdef->elements[i].typegen, sdef->elements[uo].name | |
2791 | ); | |
2792 | } | |
2793 | } | |
2794 | ||
2795 | src = mputstr(src, | |
2796 | " continue; \n" /* take care of the dangling else */ | |
2797 | " }\n" | |
2798 | " for (int d_f = 0; d_f < num_seen; ++d_f)\n" | |
2799 | " if (e_val == seen_f[d_f])\n" | |
2800 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Duplicate field\");\n" | |
2801 | " seen_f[num_seen++] = e_val;\n" | |
2802 | " } // next i\n"); | |
2803 | ||
2804 | if (sdef->xerEmbedValuesPossible) { | |
2805 | /* read and store embedValues text if present */ | |
2806 | src = mputprintf(src, | |
af710487 | 2807 | " if (0 != emb_val) {\n" |
2808 | " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" | |
2809 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" | |
2810 | " field_%s[emb_val->embval_index] = emb_ustr;\n" | |
2811 | " }\n" | |
2812 | " if (last_embval_index == emb_val->embval_index) {\n" | |
2813 | " ++emb_val->embval_index;\n" | |
2814 | " }\n" | |
970ed795 | 2815 | " }\n" |
af710487 | 2816 | , sdef->elements[0].name); |
970ed795 EL |
2817 | } |
2818 | ||
2819 | src = mputprintf(src, | |
2820 | " delete [] seen_f;\n" | |
2821 | " }\n" | |
2822 | " int n_collected = field_%s.size_of();\n" | |
2823 | " if (p_td.xer_bits & USE_NIL) {\n" | |
2824 | " ;\n" | |
2825 | " } else {\n" | |
2826 | " if (n_collected < %d || n_collected > %d) {\n" | |
2827 | " ec_0.set_msg(\" \");\n" | |
2828 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Wrong number of elements\");\n" | |
2829 | " }\n" | |
2830 | " }\n" | |
2831 | " } else { // !uo\n" | |
2832 | , sdef->elements[uo].dispname | |
2833 | , min_ordered, max_ordered | |
2834 | ); | |
2835 | } /* end if(UseOrder possible) */ | |
2836 | ||
2837 | /* * * * * non-UseOrder code always written, executed when * * * * | |
2838 | * * * * * UseOrder not possible or in the "else" clause * * * * */ | |
2839 | ||
2840 | if (sdef->xerUseNilPossible) { | |
2841 | /* value absent, nothing more to do */ | |
2842 | src = mputstr(src, | |
2843 | " if (nil_attribute) {\n" | |
2844 | " p_reader.MoveToElement();\n" | |
2845 | " } else {\n"); | |
2846 | } | |
af710487 | 2847 | if (sdef->xerEmbedValuesPossible) { |
2848 | // The index of the latest embedded value can change outside of this function | |
2849 | // (if the field is a untagged record of), in this case the next value should | |
2850 | // be ignored, as it's already been handled by the record of | |
2851 | // Omitted fields can also reset this value | |
2852 | src = mputstr(src, " int last_embval_index = 0;\n"); | |
2853 | } | |
970ed795 EL |
2854 | /* for all the non-attribute fields... */ |
2855 | for (i = start_at + num_attributes; i < sdef->nElements; ++i) { | |
2856 | if (sdef->xerEmbedValuesPossible) { | |
2857 | /* read and store embedValues text if present */ | |
2858 | src = mputprintf(src, | |
af710487 | 2859 | " if (0 != emb_val) {\n" |
2860 | " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" | |
2861 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" | |
2862 | " field_%s[emb_val->embval_index] = emb_ustr;\n" | |
2863 | " }\n" | |
2864 | " if (last_embval_index == emb_val->embval_index) {\n" | |
2865 | " ++emb_val->embval_index;\n" | |
2866 | " }\n" | |
2867 | " last_embval_index = emb_val->embval_index;\n" | |
970ed795 | 2868 | " }\n" |
af710487 | 2869 | , sdef->elements[0].name); |
970ed795 EL |
2870 | } |
2871 | /* The DEFAULT-FOR-EMPTY member can not be involved with EMBED-VALUES, | |
2872 | * so we can use the same pattern: optional "if(...) else" before {} | |
2873 | * XXX check with single-element record where nElements-1 == 0 !! */ | |
2874 | if (sdef->kind == RECORD && i == sdef->nElements-1) { | |
2875 | src = mputprintf(src, | |
2876 | " if (e_xer && p_td.dfeValue && p_reader.IsEmptyElement()) {\n" | |
2877 | " field_%s = *static_cast<const %s*>(p_td.dfeValue);\n" | |
2878 | " }\n" | |
2879 | " else" | |
2880 | , sdef->elements[i].name, sdef->elements[i].type); | |
2881 | } | |
2882 | /* Decode the field */ | |
2883 | src = mputprintf(src, | |
2884 | " {\n" | |
2885 | " ec_1.set_msg(\"%s': \");\n" | |
2886 | , sdef->elements[i].dispname); | |
2887 | ||
2888 | if ( (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT) | |
2889 | && !strcmp(sdef->elements[i].type,"UNIVERSAL_CHARSTRING") ) { | |
2890 | // In case the field is an optional anyElement -> check if it should be omitted | |
2891 | if (sdef->elements[i].isOptional) { | |
2892 | src = mputprintf(src, | |
2893 | " if (field_%s.XER_check_any_elem(p_reader, \"%s\", tag_closed))\n " | |
2894 | , sdef->elements[i].name | |
2895 | , (i == sdef->nElements - 1) ? "NULL" : sdef->elements[i + 1].name); | |
2896 | } else { | |
2897 | // If the record is emptyElement, there's no way it will have an anyElement field | |
2898 | src = mputstr(src, " if (tag_closed) p_reader.Read(); \n"); | |
2899 | } | |
2900 | } | |
2901 | ||
2902 | src = mputprintf(src, | |
2903 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor" | |
af710487 | 2904 | " | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0), %s);\n" |
970ed795 | 2905 | " }\n" |
af710487 | 2906 | , sdef->elements[i].name, sdef->elements[i].typegen |
2907 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0"); | |
2908 | if (sdef->xerEmbedValuesPossible) { | |
2909 | src = mputprintf(src, | |
2910 | " if (!field_%s.is_present()) {\n" | |
2911 | // there was no new element, the last embedded value is for the next field | |
2912 | // (or the end of the record if this is the last field) | |
2913 | " last_embval_index = -1;\n" | |
2914 | " }\n" | |
2915 | , sdef->elements[i].name); | |
2916 | } | |
970ed795 EL |
2917 | } /* next field */ |
2918 | ||
970ed795 EL |
2919 | if (sdef->xerEmbedValuesPossible) { |
2920 | /* read and store embedValues text if present */ | |
2921 | src = mputprintf(src, | |
af710487 | 2922 | " if (0 != emb_val) {\n" |
2923 | " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" | |
2924 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" | |
2925 | " field_%s[emb_val->embval_index] = emb_ustr;\n" | |
2926 | " }\n" | |
2927 | " if (last_embval_index == emb_val->embval_index) {\n" | |
2928 | " ++emb_val->embval_index;\n" | |
2929 | " }\n" | |
970ed795 | 2930 | " }\n" |
af710487 | 2931 | , sdef->elements[0].name); |
2932 | } | |
2933 | ||
2934 | if (sdef->xerUseNilPossible) { | |
2935 | src = mputstr(src, " } // use_nil\n"); | |
970ed795 EL |
2936 | } |
2937 | ||
af710487 | 2938 | if (sdef->xerUseOrderPossible) { |
2939 | src = mputstr(src, " } // uo\n"); | |
2940 | } | |
2941 | ||
970ed795 | 2942 | if (sdef->xerEmbedValuesPossible) { |
970ed795 | 2943 | src = mputprintf(src, |
af710487 | 2944 | " if (0 != emb_val) {\n" |
970ed795 | 2945 | " %s::of_type empty_string(\"\");\n" |
af710487 | 2946 | " for (int j_j = 0; j_j < emb_val->embval_index; ++j_j) {\n" |
970ed795 EL |
2947 | " if (!field_%s[j_j].is_bound()) field_%s[j_j] = empty_string;\n" |
2948 | " }\n" | |
af710487 | 2949 | " delete emb_val;\n" |
2950 | " }\n" | |
970ed795 EL |
2951 | , sdef->elements[0].type |
2952 | , sdef->elements[0].name | |
2953 | , sdef->elements[0].name | |
2954 | ); | |
2955 | } | |
2956 | ||
970ed795 EL |
2957 | if (sdef->xerUseQName) { |
2958 | src = mputstr(src, " } // qn\n"); | |
2959 | } | |
2960 | ||
2961 | src = mputstr(src, | |
2962 | " } // errorcontext\n" /* End scope for error context objects */ | |
2963 | " if (!omit_tag) {\n" | |
2964 | " int current_depth;\n" | |
2965 | " for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n" | |
2966 | " type = p_reader.NodeType();\n" | |
2967 | " if ((current_depth = p_reader.Depth()) > xml_depth) {\n" | |
2968 | " if (XML_READER_TYPE_ELEMENT == type) {\n" | |
2969 | /* An element deeper than our start tag has not been processed */ | |
2970 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG,\n" | |
2971 | " \"Unprocessed XML tag `%s'\", (const char *)p_reader.Name());\n" | |
2972 | " }\n" | |
2973 | " continue;\n" | |
2974 | " }\n" | |
2975 | " else if (current_depth == xml_depth) {\n" | |
2976 | " if (XML_READER_TYPE_ELEMENT == type) {\n" | |
2977 | " verify_name(p_reader, p_td, e_xer);\n" | |
2978 | " if (p_reader.IsEmptyElement()) {\n" | |
2979 | " p_reader.Read();\n" /* advance one more time */ | |
2980 | " break;\n" | |
2981 | " }\n" | |
2982 | " }\n" | |
2983 | " else if (XML_READER_TYPE_END_ELEMENT == type) {\n" | |
2984 | " verify_end(p_reader, p_td, xml_depth, e_xer);\n" | |
2985 | " rd_ok = p_reader.Read();\n" | |
2986 | " break;\n" | |
2987 | " }\n" | |
2988 | " }\n" | |
2989 | " else break;" /* depth is less, we are in trouble... */ | |
2990 | " }\n" | |
2991 | " }\n" | |
2992 | " return 1;\n}\n\n"); | |
2993 | ||
2994 | *pdef = def; | |
2995 | *psrc = src; | |
2996 | } | |
2997 | ||
2998 | void defRecordClass1(const struct_def *sdef, output_struct *output) | |
2999 | { | |
3000 | size_t i; | |
3001 | size_t mandatory_fields_count; | |
3002 | const char *name = sdef->name, *dispname = sdef->dispname; | |
3003 | const char* kind_str = sdef->kind == SET ? "set" : "record"; | |
3004 | char *def = NULL, *src = NULL; | |
3005 | boolean ber_needed = sdef->isASN1 && enable_ber(); | |
3006 | boolean raw_needed = sdef->hasRaw && enable_raw(); | |
3007 | boolean text_needed = sdef->hasText && enable_text(); | |
3008 | boolean xer_needed = sdef->hasXer && enable_xer(); | |
3009 | boolean json_needed = sdef->hasJson && enable_json(); | |
3010 | ||
3011 | /* class declaration code */ | |
3012 | output->header.class_decls = mputprintf(output->header.class_decls, | |
3013 | "class %s;\n", name); | |
3014 | ||
3015 | if (sdef->nElements <= 0) { | |
3016 | defEmptyRecordClass(sdef, output); | |
3017 | return; | |
3018 | } | |
3019 | ||
3020 | /* class definition and source code */ | |
3021 | if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) { | |
3022 | def=mputprintf | |
3023 | (def, | |
3024 | #ifndef NDEBUG | |
3025 | "// written by %s in " __FILE__ " at line %d\n" | |
3026 | #endif | |
3027 | "class %s : public Base_Type {\n" | |
3028 | #ifndef NDEBUG | |
3029 | , __FUNCTION__, __LINE__ | |
3030 | #endif | |
3031 | , name); | |
3032 | } else { | |
3033 | def=mputprintf(def, "class %s {\n", name); | |
3034 | } | |
3035 | ||
3036 | /* fields */ | |
3037 | for (i = 0; i < sdef->nElements; i++) { | |
3038 | if(sdef->elements[i].isOptional) | |
3039 | def = mputprintf(def, " OPTIONAL<%s> field_%s;\n", | |
3040 | sdef->elements[i].type, | |
3041 | sdef->elements[i].name); | |
3042 | else | |
3043 | def = mputprintf(def, " %s field_%s;\n", | |
3044 | sdef->elements[i].type, sdef->elements[i].name); | |
3045 | } | |
3046 | ||
3047 | /* bound flag */ | |
3048 | def = mputstr(def, " boolean bound_flag;\n"); | |
3049 | ||
3050 | /* default constructor */ | |
3051 | def = mputprintf(def, "public:\n" | |
3052 | " %s();\n", name); | |
3053 | src = mputprintf(src, "%s::%s()\n" | |
3054 | "{\n" | |
3055 | " bound_flag = FALSE;\n" | |
3056 | "}\n\n", name, name); | |
3057 | ||
3058 | /* constructor by fields */ | |
3059 | def = mputprintf(def, " %s(", name); | |
3060 | src = mputprintf(src, "%s::%s(", name, name); | |
3061 | ||
3062 | for (i = 0; i < sdef->nElements; i++) { | |
3063 | char *tmp = NULL; | |
3064 | if (i > 0) tmp = mputstr(tmp, ",\n "); | |
3065 | if (sdef->elements[i].isOptional) | |
3066 | tmp = mputprintf | |
3067 | (tmp, | |
3068 | "const OPTIONAL<%s>& par_%s", | |
3069 | sdef->elements[i].type, sdef->elements[i].name); | |
3070 | else | |
3071 | tmp = mputprintf | |
3072 | (tmp, | |
3073 | "const %s& par_%s", | |
3074 | sdef->elements[i].type, sdef->elements[i].name); | |
3075 | def = mputstr(def, tmp); | |
3076 | src = mputstr(src, tmp); | |
3077 | Free(tmp); | |
3078 | } | |
3079 | def = mputstr(def, ");\n"); | |
3080 | src = mputstr(src, ")\n" | |
3081 | " : "); | |
3082 | for (i = 0; i < sdef->nElements; i++) { | |
3083 | if (i > 0) src = mputstr(src, ",\n"); | |
3084 | src = mputprintf(src, " field_%s(par_%s)", sdef->elements[i].name, | |
3085 | sdef->elements[i].name); | |
3086 | } | |
3087 | src = mputstr(src, "\n" | |
3088 | "{\n" | |
3089 | " bound_flag = TRUE;\n" | |
3090 | "}\n\n"); | |
3091 | ||
3092 | /* copy constructor */ | |
3093 | def = mputprintf(def, " %s(const %s& other_value);\n", name, name); | |
3094 | src = mputprintf(src, "%s::%s(const %s& other_value)\n" | |
3095 | "{\n" | |
3096 | "if(!other_value.is_bound()) " | |
3097 | "TTCN_error(\"Copying an unbound value of type %s.\");\n" | |
3098 | "bound_flag = TRUE;\n", | |
3099 | name, name, name, dispname); | |
3100 | for (i = 0; i < sdef->nElements; i++) { | |
3101 | src = mputprintf(src, | |
3102 | "if (other_value.%s().is_bound()) field_%s = other_value.%s();\n" | |
3103 | "else field_%s.clean_up();\n", | |
3104 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name, | |
3105 | sdef->elements[i].name); | |
3106 | } | |
3107 | src = mputstr(src, "}\n\n"); | |
3108 | ||
3109 | /* not a component */ | |
3110 | def = mputstr(def, " inline boolean is_component() { return FALSE; }\n"); | |
3111 | ||
3112 | /* clean_up */ | |
3113 | def = mputstr(def, " void clean_up();\n"); | |
3114 | src = mputprintf(src, "void %s::clean_up()\n" | |
3115 | "{\n", name); | |
3116 | for (i = 0; i < sdef->nElements; i++) { | |
3117 | src = mputprintf(src, | |
3118 | "field_%s.clean_up();\n", sdef->elements[i].name); | |
3119 | } | |
3120 | src = mputstr(src, | |
3121 | "bound_flag = FALSE;\n" | |
3122 | "}\n\n"); | |
3123 | ||
3124 | /* = operator */ | |
3125 | def = mputprintf(def, " %s& operator=(const %s& other_value);\n", name, name); | |
3126 | src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n" | |
3127 | "{\n" | |
3128 | "if (this != &other_value) {\n" | |
3129 | " if(!other_value.is_bound()) " | |
3130 | "TTCN_error(\"Assignment of an unbound value of type %s.\");\n" | |
3131 | " bound_flag = TRUE;\n", | |
3132 | name, name, name, dispname); | |
3133 | for (i = 0; i < sdef->nElements; i++) { | |
3134 | src = mputprintf(src, | |
3135 | " if (other_value.%s().is_bound()) field_%s = other_value.%s();\n" | |
3136 | " else field_%s.clean_up();\n", | |
3137 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name, | |
3138 | sdef->elements[i].name); | |
3139 | } | |
3140 | src = mputstr(src, | |
3141 | "}\n" | |
3142 | "return *this;\n" | |
3143 | "}\n\n"); | |
3144 | ||
3145 | /* == operator */ | |
3146 | def = mputprintf(def, " boolean operator==(const %s& other_value) " | |
3147 | "const;\n", name); | |
3148 | src = mputprintf(src, | |
3149 | "boolean %s::operator==(const %s& other_value) const\n" | |
3150 | "{\n" | |
3151 | "if (!is_bound() && !other_value.is_bound()) return TRUE;\n" | |
3152 | "return ", name, name); | |
3153 | for (i = 0; i < sdef->nElements; i++) { | |
3154 | if (i > 0) src = mputstr(src, "\n && "); | |
3155 | src = mputprintf(src, "field_%s==other_value.field_%s", | |
3156 | sdef->elements[i].name, sdef->elements[i].name); | |
3157 | } | |
3158 | src = mputstr(src, ";\n}\n\n"); | |
3159 | ||
3160 | /* != and () operator */ | |
3161 | def = mputprintf(def, | |
3162 | " inline boolean operator!=(const %s& other_value) const\n" | |
3163 | " { return !(*this == other_value); }\n\n", name); | |
3164 | ||
3165 | /* is_bound */ | |
3166 | def = mputprintf(def, | |
3167 | " boolean is_bound() const;\n\n"); | |
3168 | src = mputprintf(src, | |
3169 | "boolean %s::is_bound() const\n" | |
3170 | "{\n" | |
3171 | "if (bound_flag) return TRUE;\n", name); | |
3172 | for(i=0; i < sdef->nElements; i++) { | |
3173 | if(sdef->elements[i].isOptional) { | |
3174 | src = mputprintf(src, | |
3175 | "if(OPTIONAL_OMIT == field_%s.get_selection() || field_%s.is_bound()) return TRUE;\n", | |
3176 | sdef->elements[i].name, sdef->elements[i].name); | |
3177 | } else { | |
3178 | src = mputprintf(src, | |
3179 | "if(field_%s.is_bound()) return TRUE;\n", | |
3180 | sdef->elements[i].name); | |
3181 | } | |
3182 | } | |
3183 | src = mputprintf(src, | |
3184 | "return FALSE;\n" | |
3185 | "}\n"); | |
3186 | ||
3187 | /* is_present */ | |
3188 | def = mputstr(def, | |
3189 | "inline boolean is_present() const { return is_bound(); }\n"); | |
3190 | ||
3191 | /* is_value */ | |
3192 | def = mputprintf(def, | |
3193 | " boolean is_value() const;\n\n"); | |
3194 | src = mputprintf(src, | |
3195 | "boolean %s::is_value() const\n" | |
3196 | "{\n" | |
3197 | "if (!is_bound()) return FALSE;\n", name); | |
3198 | for(i=0; i < sdef->nElements; i++) { | |
3199 | if(sdef->elements[i].isOptional) { | |
3200 | src = mputprintf(src, | |
3201 | "if(OPTIONAL_OMIT != field_%s.get_selection() && !field_%s.is_value()) return FALSE;\n", | |
3202 | sdef->elements[i].name, sdef->elements[i].name); | |
3203 | } else { | |
3204 | src = mputprintf(src, | |
3205 | "if(!field_%s.is_value()) return FALSE;\n", | |
3206 | sdef->elements[i].name); | |
3207 | } | |
3208 | } | |
3209 | src = mputprintf(src, | |
3210 | "return TRUE;\n}\n"); | |
3211 | ||
3212 | /* field accessor methods */ | |
3213 | for (i = 0; i < sdef->nElements; i++) { | |
3214 | if(sdef->elements[i].isOptional) | |
3215 | def = mputprintf | |
3216 | (def, | |
3217 | " inline OPTIONAL<%s>& %s()\n" | |
3218 | " {return field_%s;}\n" | |
3219 | " inline const OPTIONAL<%s>& %s() const\n" | |
3220 | " {return field_%s;}\n", | |
3221 | sdef->elements[i].type, sdef->elements[i].name, | |
3222 | sdef->elements[i].name, | |
3223 | sdef->elements[i].type, sdef->elements[i].name, | |
3224 | sdef->elements[i].name); | |
3225 | else def = mputprintf | |
3226 | (def, | |
3227 | " inline %s& %s()\n" | |
3228 | " {return field_%s;}\n" | |
3229 | " inline const %s& %s() const\n" | |
3230 | " {return field_%s;}\n", | |
3231 | sdef->elements[i].type, sdef->elements[i].name, | |
3232 | sdef->elements[i].name, sdef->elements[i].type, | |
3233 | sdef->elements[i].name, sdef->elements[i].name); | |
3234 | ||
3235 | } | |
3236 | ||
3237 | /* sizeof operation */ | |
3238 | mandatory_fields_count = 0; | |
3239 | for (i = 0; i < sdef->nElements; i++) | |
3240 | if (!sdef->elements[i].isOptional) mandatory_fields_count++; | |
3241 | ||
3242 | def = mputstr(def, " int size_of() const;\n"); | |
3243 | src = mputprintf(src, | |
3244 | "int %s::size_of() const\n" | |
3245 | "{\n" | |
3246 | " if (!is_bound()) " | |
3247 | "TTCN_error(\"Calculating the size of an unbound record/set value of type %s\");\n" | |
3248 | , name, dispname); | |
3249 | if (sdef->nElements == mandatory_fields_count) { | |
3250 | src = mputprintf(src, " return %lu;\n", (unsigned long) mandatory_fields_count); | |
3251 | } | |
3252 | else { | |
3253 | src = mputprintf(src, " int ret_val = %lu;\n", | |
3254 | (unsigned long) mandatory_fields_count); | |
3255 | for (i = 0; i < sdef->nElements; i++) | |
3256 | if (sdef->elements[i].isOptional) | |
3257 | src = mputprintf(src, | |
3258 | " if (field_%s.ispresent()) ret_val++;\n", | |
3259 | sdef->elements[i].name); | |
3260 | src = mputstr(src, " return ret_val;\n"); | |
3261 | } | |
3262 | src = mputstr(src, "}\n\n"); | |
3263 | ||
3264 | /* log function */ | |
3265 | def = mputstr(def, " void log() const;\n"); | |
3266 | src = mputprintf(src, | |
3267 | "void %s::log() const\n{\n" | |
3268 | "if (!is_bound()) {\n" | |
3269 | "TTCN_Logger::log_event_unbound();\n" | |
3270 | "return;\n" | |
3271 | "}\n", name); | |
3272 | for (i = 0; i < sdef->nElements; i++) { | |
3273 | src = mputstr(src, "TTCN_Logger::log_event_str(\""); | |
3274 | if (i == 0) src = mputc(src, '{'); | |
3275 | else src = mputc(src, ','); | |
3276 | src = mputprintf(src, " %s := \");\n" | |
3277 | "field_%s.log();\n", | |
3278 | sdef->elements[i].dispname, sdef->elements[i].name); | |
3279 | } | |
3280 | src = mputstr(src, "TTCN_Logger::log_event_str(\" }\");\n}\n\n"); | |
3281 | ||
3282 | /* set param function */ | |
3283 | def = mputstr(def, " void set_param(Module_Param& param);\n"); | |
3284 | src = mputprintf | |
3285 | (src, | |
3286 | "void %s::set_param(Module_Param& param)\n{\n" | |
3287 | " bound_flag = TRUE;\n" | |
3288 | " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n" | |
3289 | " param.get_id()->next_name()) {\n" | |
3290 | // Haven't reached the end of the module parameter name | |
3291 | // => the name refers to one of the fields, not to the whole record | |
3292 | " char* param_field = param.get_id()->get_current_name();\n" | |
3293 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" | |
3294 | " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n" | |
3295 | " \" name for %s type `%s'\");\n" | |
3296 | " }\n" | |
3297 | " ", name, kind_str, dispname); | |
3298 | for (i = 0; i < sdef->nElements; i++) { | |
3299 | src = mputprintf(src, | |
3300 | "if (strcmp(\"%s\", param_field) == 0) {\n" | |
3301 | " %s().set_param(param);\n" | |
3302 | " return;\n" | |
3303 | " } else ", | |
3304 | sdef->elements[i].dispname, sdef->elements[i].name); | |
3305 | } | |
3306 | src = mputprintf(src, | |
3307 | "param.error(\"Field `%%s' not found in %s type `%s'\", param_field);\n" | |
3308 | " }\n" | |
3309 | " param.basic_check(Module_Param::BC_VALUE, \"%s value\");\n" | |
3310 | " switch (param.get_type()) {\n" | |
3311 | " case Module_Param::MP_Value_List:\n" | |
3312 | " if (%lu<param.get_size()) {\n" | |
3313 | " param.error(\"%s value of type %s has %lu fields but list value has %%d fields\", (int)param.get_size());\n" | |
3314 | " }\n", | |
3315 | kind_str, dispname, kind_str, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements); | |
3316 | ||
3317 | for (i = 0; i < sdef->nElements; ++i) { | |
3318 | src = mputprintf(src, | |
3319 | " if (param.get_size()>%lu && param.get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*param.get_elem(%lu));\n", | |
3320 | (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i); | |
3321 | } | |
3322 | src = mputstr(src, | |
3323 | " break;\n" | |
3324 | " case Module_Param::MP_Assignment_List: {\n" | |
3325 | " Vector<bool> value_used(param.get_size());\n" | |
3326 | " value_used.resize(param.get_size(), false);\n"); | |
3327 | for (i = 0; i < sdef->nElements; ++i) { | |
3328 | src = mputprintf(src, | |
3329 | " for (size_t val_idx=0; val_idx<param.get_size(); val_idx++) {\n" | |
3330 | " Module_Param* const curr_param = param.get_elem(val_idx);\n" | |
3331 | " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n" | |
3332 | " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n" | |
3333 | " %s().set_param(*curr_param);\n" | |
3334 | " }\n" | |
3335 | " value_used[val_idx]=true;\n" | |
3336 | " }\n" | |
3337 | " }\n" | |
3338 | , sdef->elements[i].dispname, sdef->elements[i].name); | |
3339 | } | |
3340 | src = mputprintf(src, | |
3341 | " for (size_t val_idx=0; val_idx<param.get_size(); val_idx++) if (!value_used[val_idx]) {\n" | |
3342 | " param.get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", param.get_elem(val_idx)->get_id()->get_name());\n" | |
3343 | " break;\n" | |
3344 | " }\n" | |
3345 | " } break;\n" | |
3346 | " default:\n" | |
3347 | " param.type_error(\"%s value\", \"%s\");\n" | |
3348 | " }\n" | |
3349 | "}\n\n", dispname, kind_str, dispname); | |
3350 | ||
3351 | /* set implicit omit function, recursive */ | |
3352 | def = mputstr(def, " void set_implicit_omit();\n"); | |
3353 | src = mputprintf(src, "void %s::set_implicit_omit()\n{\n", name); | |
3354 | for (i = 0; i < sdef->nElements; i++) { | |
3355 | if (sdef->elements[i].isOptional) { | |
3356 | src = mputprintf(src, | |
3357 | "if (!%s().is_bound()) %s() = OMIT_VALUE;\n" | |
3358 | "else %s().set_implicit_omit();\n", | |
3359 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); | |
3360 | } else { | |
3361 | src = mputprintf(src, | |
3362 | "if (%s().is_bound()) %s().set_implicit_omit();\n", | |
3363 | sdef->elements[i].name, sdef->elements[i].name); | |
3364 | } | |
3365 | } | |
3366 | src = mputstr(src, "}\n\n"); | |
3367 | ||
3368 | /* text encoder function */ | |
3369 | def = mputstr(def, " void encode_text(Text_Buf& text_buf) const;\n"); | |
3370 | src = mputprintf(src, | |
3371 | "void %s::encode_text(Text_Buf& text_buf) const\n{\n" | |
3372 | "if (!is_bound()) " | |
3373 | "TTCN_error(\"Text encoder: Encoding an unbound record/set value of type %s.\");\n" | |
3374 | , name, dispname); | |
3375 | for (i = 0; i < sdef->nElements; i++) { | |
3376 | src = mputprintf(src, "field_%s.encode_text(text_buf);\n", | |
3377 | sdef->elements[i].name); | |
3378 | } | |
3379 | src = mputstr(src, "}\n\n"); | |
3380 | ||
3381 | /* text decoder function */ | |
3382 | def = mputstr(def, " void decode_text(Text_Buf& text_buf);\n"); | |
3383 | src = mputprintf(src, | |
3384 | "void %s::decode_text(Text_Buf& text_buf)\n{\n" | |
3385 | "bound_flag = TRUE;\n", name); | |
3386 | for (i = 0; i < sdef->nElements; i++) { | |
3387 | src = mputprintf(src, "field_%s.decode_text(text_buf);\n", | |
3388 | sdef->elements[i].name); | |
3389 | } | |
3390 | src = mputstr(src, "}\n\n"); | |
3391 | ||
3392 | /* The common "classname::encode()" and "classname::decode()" functions */ | |
3393 | if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) | |
3394 | def_encdec(name, &def, &src, ber_needed, raw_needed, | |
3395 | text_needed, xer_needed, json_needed, FALSE); | |
3396 | ||
3397 | /* BER functions */ | |
3398 | if(ber_needed) { | |
3399 | /* BER_encode_TLV() */ | |
3400 | src=mputprintf | |
3401 | (src, | |
3402 | "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td," | |
3403 | " unsigned p_coding) const\n" | |
3404 | "{\n" | |
3405 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
3406 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
3407 | " BER_chk_descr(p_td);\n" | |
3408 | " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n" | |
3409 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" | |
3410 | " TTCN_EncDec_ErrorContext ec_1;\n" | |
3411 | , name | |
3412 | ); | |
3413 | for(i=0; i<sdef->nElements; i++) { | |
3414 | if(!default_as_optional && sdef->elements[i].isDefault) { /* is DEFAULT */ | |
3415 | src=mputprintf | |
3416 | (src, | |
3417 | " if(field_%s!=%s) {\n" | |
3418 | " ec_1.set_msg(\"%s': \");\n" | |
3419 | " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_," | |
3420 | " p_coding));\n" | |
3421 | " }\n" | |
3422 | , sdef->elements[i].name, sdef->elements[i].defvalname | |
3423 | , sdef->elements[i].dispname | |
3424 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3425 | ); | |
3426 | } | |
3427 | else { /* is not DEFAULT */ | |
3428 | src=mputprintf | |
3429 | (src, | |
3430 | " ec_1.set_msg(\"%s': \");\n" | |
3431 | " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_," | |
3432 | " p_coding));\n" | |
3433 | , sdef->elements[i].dispname | |
3434 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3435 | ); | |
3436 | } /* !isDefault */ | |
3437 | } /* for i */ | |
3438 | if(sdef->kind==SET) { | |
3439 | src=mputstr | |
3440 | (src, | |
3441 | " if(p_coding==BER_ENCODE_DER)\n" | |
3442 | " new_tlv->sort_tlvs_tag();\n" | |
3443 | ); | |
3444 | } | |
3445 | src=mputstr | |
3446 | (src, | |
3447 | " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n" | |
3448 | " return new_tlv;\n" | |
3449 | "}\n" | |
3450 | "\n" | |
3451 | ); | |
3452 | ||
3453 | /* BER_decode_TLV() */ | |
3454 | src=mputprintf | |
3455 | (src, | |
3456 | "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td," | |
3457 | " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n" | |
3458 | "{\n" | |
3459 | " bound_flag = TRUE;\n" | |
3460 | " BER_chk_descr(p_td);\n" | |
3461 | " ASN_BER_TLV_t stripped_tlv;\n" | |
3462 | " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n" | |
3463 | " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n" | |
3464 | " stripped_tlv.chk_constructed_flag(TRUE);\n" | |
3465 | " size_t V_pos=0;\n" | |
3466 | " ASN_BER_TLV_t tmp_tlv;\n" | |
3467 | , name, sdef->dispname | |
3468 | ); | |
3469 | ||
3470 | if(sdef->kind==RECORD) | |
3471 | { /* SEQUENCE decoding */ | |
3472 | src=mputstr | |
3473 | (src, | |
3474 | " boolean tlv_present=FALSE;\n" | |
3475 | " {\n" | |
3476 | " TTCN_EncDec_ErrorContext ec_1(\"Component '\");\n" | |
3477 | " TTCN_EncDec_ErrorContext ec_2;\n" | |
3478 | ); | |
3479 | for(i=0; i<sdef->nElements; i++) { | |
3480 | src=mputprintf | |
3481 | (src, | |
3482 | " ec_2.set_msg(\"%s': \");\n" | |
3483 | " if(!tlv_present) tlv_present=BER_decode_constdTLV_next" | |
3484 | "(stripped_tlv, V_pos, L_form, tmp_tlv);\n" | |
3485 | , sdef->elements[i].dispname | |
3486 | ); | |
3487 | if(sdef->elements[i].isDefault) { /* is DEFAULT */ | |
3488 | src=mputprintf | |
3489 | (src, | |
3490 | " if(!tlv_present || !field_%s.BER_decode_isMyMsg(%s_descr_," | |
3491 | " tmp_tlv))\n" | |
3492 | " field_%s=%s;\n" | |
3493 | " else {\n" | |
3494 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv," | |
3495 | " L_form);\n" | |
3496 | " tlv_present=FALSE;\n" | |
3497 | " }\n" | |
3498 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3499 | , sdef->elements[i].name, sdef->elements[i].defvalname | |
3500 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3501 | ); | |
3502 | } | |
3503 | else if(sdef->elements[i].isOptional) { /* is OPTIONAL */ | |
3504 | src=mputprintf | |
3505 | (src, | |
3506 | " if(!tlv_present) field_%s=OMIT_VALUE;\n" | |
3507 | " else {\n" | |
3508 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n" | |
3509 | " if(field_%s.ispresent()) tlv_present=FALSE;\n" | |
3510 | " }\n" | |
3511 | , sdef->elements[i].name | |
3512 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3513 | , sdef->elements[i].name | |
3514 | ); | |
3515 | } | |
3516 | else { /* is not DEFAULT OPTIONAL */ | |
3517 | src=mputprintf | |
3518 | (src, | |
3519 | " if(!tlv_present){\n" | |
3520 | " ec_2.error(TTCN_EncDec::ET_INCOMPL_MSG,\"Invalid or incomplete message was received.\");\n" | |
3521 | " return FALSE;\n" | |
3522 | " }\n" | |
3523 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n" | |
3524 | " tlv_present=FALSE;\n" | |
3525 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3526 | ); | |
3527 | } /* !isDefault */ | |
3528 | } /* for i */ | |
3529 | src=mputstr | |
3530 | (src, | |
3531 | " }\n" | |
3532 | " BER_decode_constdTLV_end(stripped_tlv, V_pos, L_form, tmp_tlv," | |
3533 | " tlv_present);\n" | |
3534 | ); | |
3535 | } /* SEQUENCE decoding */ | |
3536 | else { /* SET decoding */ | |
3537 | src=mputprintf | |
3538 | (src, | |
3539 | " const char *fld_name[%lu]={" | |
3540 | , (unsigned long) sdef->nElements | |
3541 | ); | |
3542 | for(i=0; i<sdef->nElements; i++) | |
3543 | src=mputprintf | |
3544 | (src, | |
3545 | "%s\"%s\"" | |
3546 | , i?", ":"" | |
3547 | , sdef->elements[i].dispname | |
3548 | ); | |
3549 | /* field indicator: | |
3550 | * 0x01: value arrived | |
3551 | * 0x02: is optional / not used :) | |
3552 | * 0x04: has default / not used :) | |
3553 | */ | |
3554 | src=mputprintf | |
3555 | (src, | |
3556 | "};\n" | |
3557 | " unsigned char fld_indctr[%lu]={" | |
3558 | , (unsigned long) sdef->nElements | |
3559 | ); | |
3560 | for(i=0; i<sdef->nElements; i++) | |
3561 | src=mputprintf | |
3562 | (src, | |
3563 | "%s0" | |
3564 | , i?", ":"" | |
3565 | ); | |
3566 | src=mputstr | |
3567 | (src, | |
3568 | "};\n" | |
3569 | " size_t fld_curr;\n" | |
3570 | " while(BER_decode_constdTLV_next(stripped_tlv, V_pos," | |
3571 | " L_form, tmp_tlv)) {\n" | |
3572 | ); | |
3573 | for(i=0; i<sdef->nElements; i++) | |
3574 | src=mputprintf | |
3575 | (src, | |
3576 | " %sif(field_%s.BER_decode_isMyMsg(%s_descr_, tmp_tlv)) {\n" | |
3577 | " fld_curr=%lu;\n" | |
3578 | " TTCN_EncDec_ErrorContext ec_1(\"Component '%%s': \"," | |
3579 | " fld_name[%lu]);\n" | |
3580 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n" | |
3581 | " }\n" | |
3582 | , i?"else ":"" | |
3583 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3584 | , (unsigned long) i, (unsigned long) i | |
3585 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3586 | ); | |
3587 | src=mputprintf | |
3588 | (src, | |
3589 | " else {\n" | |
3590 | " /* ellipsis or error... */\n" | |
3591 | " fld_curr=static_cast<size_t>(-1);\n" | |
3592 | " }\n" | |
3593 | " if(fld_curr!=static_cast<size_t>(-1)) {\n" | |
3594 | " if(fld_indctr[fld_curr])\n" | |
3595 | " ec_0.error(TTCN_EncDec::ET_DEC_DUPFLD, \"Duplicated" | |
3596 | " value for component '%%s'.\", fld_name[fld_curr]);\n" | |
3597 | " fld_indctr[fld_curr]=1;\n" | |
3598 | " }\n" /* if != -1 */ | |
3599 | " }\n" /* while */ | |
3600 | " for(fld_curr=0; fld_curr<%lu; fld_curr++) {\n" | |
3601 | " if(fld_indctr[fld_curr]) continue;\n" | |
3602 | " switch(fld_curr) {\n" | |
3603 | , (unsigned long) sdef->nElements | |
3604 | ); | |
3605 | for(i=0; i<sdef->nElements; i++) { | |
3606 | if(sdef->elements[i].isDefault) | |
3607 | src=mputprintf | |
3608 | (src, | |
3609 | " case %lu:\n" | |
3610 | " field_%s=%s;\n" | |
3611 | " break;\n" | |
3612 | , (unsigned long) i | |
3613 | , sdef->elements[i].name, sdef->elements[i].defvalname | |
3614 | ); | |
3615 | else if(sdef->elements[i].isOptional) | |
3616 | src=mputprintf | |
3617 | (src, | |
3618 | " case %lu:\n" | |
3619 | " field_%s=OMIT_VALUE;\n" | |
3620 | " break;\n" | |
3621 | , (unsigned long) i | |
3622 | , sdef->elements[i].name | |
3623 | ); | |
3624 | } /* for i */ | |
3625 | src=mputstr | |
3626 | (src, | |
3627 | " default:\n" | |
3628 | " ec_0.error(TTCN_EncDec::ET_DEC_MISSFLD, \"Missing" | |
3629 | " value for component '%s'.\", fld_name[fld_curr]);\n" | |
3630 | " }\n" /* switch */ | |
3631 | " }\n" /* for fld_curr */ | |
3632 | ); | |
3633 | } /* SET decoding */ | |
3634 | ||
3635 | if(sdef->opentype_outermost) { | |
3636 | src=mputstr | |
3637 | (src, | |
3638 | " TTCN_EncDec_ErrorContext ec_1(\"While decoding opentypes: \");\n" | |
3639 | " TTCN_Type_list p_typelist;\n" | |
3640 | " BER_decode_opentypes(p_typelist, L_form);\n" | |
3641 | ); | |
3642 | } /* if sdef->opentype_outermost */ | |
3643 | src=mputstr | |
3644 | (src, | |
3645 | " return TRUE;\n" | |
3646 | "}\n" | |
3647 | "\n" | |
3648 | ); | |
3649 | ||
3650 | if(sdef->has_opentypes) { | |
3651 | /* BER_decode_opentypes() */ | |
3652 | def=mputstr | |
3653 | (def, | |
3654 | "void BER_decode_opentypes(TTCN_Type_list& p_typelist," | |
3655 | " unsigned L_form);\n"); | |
3656 | src=mputprintf | |
3657 | (src, | |
3658 | "void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist," | |
3659 | " unsigned L_form)\n" | |
3660 | "{\n" | |
3661 | " bound_flag = TRUE;\n" | |
3662 | " p_typelist.push(this);\n" | |
3663 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" | |
3664 | " TTCN_EncDec_ErrorContext ec_1;\n" | |
3665 | , name | |
3666 | ); | |
3667 | for(i=0; i<sdef->nElements; i++) { | |
3668 | src=mputprintf | |
3669 | (src, | |
3670 | " ec_1.set_msg(\"%s': \");\n" | |
3671 | " field_%s.BER_decode_opentypes(p_typelist, L_form);\n" | |
3672 | , sdef->elements[i].dispname | |
3673 | , sdef->elements[i].name | |
3674 | ); | |
3675 | } /* for i */ | |
3676 | src=mputstr | |
3677 | (src, | |
3678 | " p_typelist.pop();\n" | |
3679 | "}\n" | |
3680 | "\n" | |
3681 | ); | |
3682 | } /* if sdef->has_opentypes */ | |
3683 | ||
3684 | } /* if ber_needed */ | |
3685 | ||
3686 | if(text_needed){ | |
3687 | int man_num=0; | |
3688 | int opt_number=0; | |
3689 | int seof=0; | |
3690 | size_t last_man_index=0; | |
3691 | for(i=0;i<sdef->nElements;i++){ | |
3692 | if(sdef->elements[i].isOptional) opt_number++; | |
3693 | else {man_num++;last_man_index=i+1;} | |
3694 | if(sdef->elements[i].of_type) seof++; | |
3695 | } | |
3696 | ||
3697 | src=mputprintf(src, | |
3698 | "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td," | |
3699 | " TTCN_Buffer& p_buf) const{\n" | |
3700 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
3701 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
3702 | " bool need_separator=false;\n" | |
3703 | " int encoded_length=0;\n" | |
3704 | " if(p_td.text->begin_encode){\n" | |
3705 | " p_buf.put_cs(*p_td.text->begin_encode);\n" | |
3706 | " encoded_length+=p_td.text->begin_encode->lengthof();\n" | |
3707 | " }\n" | |
3708 | ,name | |
3709 | ); | |
3710 | ||
3711 | for(i=0;i<sdef->nElements;i++){ | |
3712 | if(sdef->elements[i].isOptional){ | |
3713 | src=mputprintf(src, | |
3714 | " if(field_%s.ispresent()){\n" | |
3715 | ,sdef->elements[i].name | |
3716 | ); | |
3717 | } | |
3718 | src=mputprintf(src, | |
3719 | " if(need_separator && p_td.text->separator_encode){\n" | |
3720 | " p_buf.put_cs(*p_td.text->separator_encode);\n" | |
3721 | " encoded_length+=p_td.text->separator_encode->lengthof();\n" | |
3722 | " }\n" | |
3723 | " encoded_length+=field_%s%s.TEXT_encode(%s_descr_,p_buf);\n" | |
3724 | " need_separator=true;\n" | |
3725 | ,sdef->elements[i].name | |
3726 | ,sdef->elements[i].isOptional?"()":"",sdef->elements[i].typedescrname | |
3727 | ); | |
3728 | if(sdef->elements[i].isOptional){ | |
3729 | src=mputstr(src, | |
3730 | " }\n" | |
3731 | ); | |
3732 | } | |
3733 | } | |
3734 | ||
3735 | src=mputstr(src, | |
3736 | " if(p_td.text->end_encode){\n" | |
3737 | " p_buf.put_cs(*p_td.text->end_encode);\n" | |
3738 | " encoded_length+=p_td.text->end_encode->lengthof();\n" | |
3739 | " }\n" | |
3740 | " return encoded_length;\n" | |
3741 | "}\n" | |
3742 | ); | |
3743 | ||
3744 | if(sdef->kind==SET){ /* set decoder start*/ | |
3745 | src = mputprintf(src, | |
3746 | "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td," | |
3747 | " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n" | |
3748 | " bound_flag = TRUE;\n" | |
3749 | " int decoded_length=0;\n" | |
3750 | " int decoded_field_length=0;\n" | |
3751 | " size_t pos=p_buf.get_pos();\n" | |
3752 | " boolean sep_found=FALSE;\n" | |
3753 | " int ml=0;\n" | |
3754 | " int sep_length=0;\n" | |
3755 | " int mand_field_num=%d;\n" | |
3756 | " int opt_field_num=%d;\n" | |
3757 | " int loop_detector=1;\n" | |
3758 | " int last_field_num=-1;\n" | |
3759 | " int field_map[%lu];\n" | |
3760 | " memset(field_map, 0, sizeof(field_map));\n" | |
3761 | " if(p_td.text->begin_decode){\n" | |
3762 | " int tl;\n" | |
3763 | " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n" | |
3764 | " if(no_err)return -1;\n" | |
3765 | " TTCN_EncDec_ErrorContext::error\n" | |
3766 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
3767 | " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)" | |
3768 | ", p_td.name);\n" | |
3769 | " return 0;\n" | |
3770 | " }\n" | |
3771 | " decoded_length+=tl;\n" | |
3772 | " p_buf.increase_pos(tl);\n" | |
3773 | " }\n" | |
3774 | " if(p_td.text->end_decode){\n" | |
3775 | " limit.add_token(p_td.text->end_decode);\n" | |
3776 | " ml++;\n" | |
3777 | " }\n" | |
3778 | " if(p_td.text->separator_decode){\n" | |
3779 | " limit.add_token(p_td.text->separator_decode);\n" | |
3780 | " ml++;\n" | |
3781 | " }\n" | |
3782 | ,name,man_num,opt_number,(unsigned long) sdef->nElements | |
3783 | ); | |
3784 | ||
3785 | if(seof){ | |
3786 | int first=0; | |
3787 | src=mputstr(src, | |
3788 | " int has_repeatable=0;\n" | |
3789 | " if(" | |
3790 | ); | |
3791 | for(i=0;i<sdef->nElements;i++){ | |
3792 | if(sdef->elements[i].of_type){ | |
3793 | src=mputprintf(src, | |
3794 | "%s%s_descr_.text->val.parameters->decoding_params.repeatable" | |
3795 | ,first?" && ":"" | |
3796 | ,sdef->elements[i].typedescrname | |
3797 | ); | |
3798 | first=1; | |
3799 | } | |
3800 | } | |
3801 | src=mputstr(src, | |
3802 | ") has_repeatable=1;\n" | |
3803 | ); | |
3804 | ||
3805 | } | |
3806 | for(i=0;i<sdef->nElements;i++){ | |
3807 | if(sdef->elements[i].isOptional){ | |
3808 | src=mputprintf(src, | |
3809 | " field_%s=OMIT_VALUE;\n" | |
3810 | ,sdef->elements[i].name | |
3811 | ); | |
3812 | } | |
3813 | } | |
3814 | src = mputprintf(src, | |
3815 | " while(mand_field_num+opt_field_num%s){\n" | |
3816 | " loop_detector=1;\n" | |
3817 | " while(TRUE){\n" | |
3818 | ,seof?"+has_repeatable":"" | |
3819 | ); | |
3820 | ||
3821 | for(i=0;i<sdef->nElements;i++){ | |
3822 | if(sdef->elements[i].of_type){ | |
3823 | src=mputprintf(src, | |
3824 | " if( (%s_descr_.text->val.parameters->decoding_params.repeatable" | |
3825 | " && field_map[%lu]<3) || !field_map[%lu]){\n" | |
3826 | " pos=p_buf.get_pos();\n" | |
3827 | " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf," | |
3828 | "limit,true,!field_map[%lu]);\n" | |
3829 | " if(decoded_field_length<0){\n" | |
3830 | " p_buf.set_pos(pos);\n" | |
3831 | ,sdef->elements[i].typedescrname,(unsigned long) i,(unsigned long) i | |
3832 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
3833 | ,sdef->elements[i].typedescrname | |
3834 | ,(unsigned long) i | |
3835 | ); | |
3836 | ||
3837 | if(sdef->elements[i].isOptional){ | |
3838 | src=mputprintf(src, | |
3839 | " if(!field_map[%lu]) field_%s=OMIT_VALUE;\n" | |
3840 | ,(unsigned long) i | |
3841 | ,sdef->elements[i].name | |
3842 | ); | |
3843 | } | |
3844 | src=mputprintf(src, | |
3845 | " }else{\n" | |
3846 | " loop_detector=0;\n" | |
3847 | " if(!field_map[%lu]) {%s--;field_map[%lu]=1;}\n" | |
3848 | " else field_map[%lu]=2;\n" | |
3849 | " last_field_num=%lu;\n" | |
3850 | " break;\n" | |
3851 | " }\n" | |
3852 | " }\n" | |
3853 | ,(unsigned long) i | |
3854 | ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num" | |
3855 | ,(unsigned long) i,(unsigned long) i,(unsigned long) i | |
3856 | ); | |
3857 | } else { | |
3858 | src=mputprintf(src, | |
3859 | " if(!field_map[%lu]){\n" | |
3860 | " pos=p_buf.get_pos();\n" | |
3861 | " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf," | |
3862 | "limit,true);\n" | |
3863 | " if(decoded_field_length<0){\n" | |
3864 | " p_buf.set_pos(pos);\n" | |
3865 | "%s%s%s" | |
3866 | " }else{\n" | |
3867 | " loop_detector=0;\n" | |
3868 | " field_map[%lu]=1;\n" | |
3869 | " %s--;\n" | |
3870 | " last_field_num=%lu;\n" | |
3871 | " break;\n" | |
3872 | " }\n" | |
3873 | " }\n" | |
3874 | ,(unsigned long) i | |
3875 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
3876 | ,sdef->elements[i].typedescrname | |
3877 | ,sdef->elements[i].isOptional?" field_":"" | |
3878 | ,sdef->elements[i].isOptional?sdef->elements[i].name:"" | |
3879 | ,sdef->elements[i].isOptional?"=OMIT_VALUE;\n":"",(unsigned long) i | |
3880 | ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num" | |
3881 | ,(unsigned long) i | |
3882 | ); | |
3883 | } | |
3884 | } | |
3885 | ||
3886 | src = mputstr(src, | |
3887 | " break;\n" | |
3888 | " }\n" | |
3889 | " if(loop_detector) break;\n" | |
3890 | " if(p_td.text->separator_decode){\n" | |
3891 | " int tl;\n" | |
3892 | " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n" | |
3893 | " if(p_td.text->end_decode){\n" | |
3894 | " int tl;\n" | |
3895 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" | |
3896 | " sep_found=FALSE;\n" | |
3897 | " break;\n" | |
3898 | " }\n" | |
3899 | " } else if(limit.has_token(ml)){\n" | |
3900 | " int tl;\n" | |
3901 | " if((tl=limit.match(p_buf,ml))==0){\n" | |
3902 | " sep_found=FALSE;\n" | |
3903 | " break;\n" | |
3904 | " }\n" | |
3905 | " } else break;\n" | |
3906 | " p_buf.set_pos(pos);\n" | |
3907 | " decoded_length-=decoded_field_length;\n" | |
3908 | " field_map[last_field_num]+=2;\n" | |
3909 | ); | |
3910 | ||
3911 | if(opt_number){ | |
3912 | src=mputstr(src, | |
3913 | "switch(last_field_num){\n" | |
3914 | ); | |
3915 | for(i=0;i<sdef->nElements;i++){ | |
3916 | if(sdef->elements[i].of_type){ | |
3917 | if(sdef->elements[i].isOptional){ | |
3918 | src=mputprintf(src, | |
3919 | " case %lu:\n" | |
3920 | " if(field_map[%lu]==3){\n" | |
3921 | " field_%s=OMIT_VALUE;\n" | |
3922 | " opt_field_num++;\n" | |
3923 | " }\n" | |
3924 | " break;\n" | |
3925 | ,(unsigned long) i,(unsigned long) i,sdef->elements[i].name | |
3926 | ); | |
3927 | } else { | |
3928 | src=mputprintf(src, | |
3929 | " case %lu:\n" | |
3930 | " if(field_map[%lu]==3){\n" | |
3931 | " mand_field_num++;\n" | |
3932 | " }\n" | |
3933 | " break;\n" | |
3934 | ,(unsigned long) i,(unsigned long) i | |
3935 | ); | |
3936 | } | |
3937 | } else if(sdef->elements[i].isOptional){ | |
3938 | src=mputprintf(src, | |
3939 | " case %lu:\n" | |
3940 | " field_%s=OMIT_VALUE;\n" | |
3941 | " opt_field_num++;\n" | |
3942 | " break;\n" | |
3943 | ,(unsigned long) i,sdef->elements[i].name | |
3944 | ); | |
3945 | } | |
3946 | } | |
3947 | src=mputstr(src, | |
3948 | " default:\n" | |
3949 | " mand_field_num++;\n" | |
3950 | " break;\n" | |
3951 | "}\n" | |
3952 | ); | |
3953 | } | |
3954 | ||
3955 | src = mputprintf(src, | |
3956 | " } else {\n" | |
3957 | " sep_length=tl;\n" | |
3958 | " decoded_length+=tl;\n" | |
3959 | " p_buf.increase_pos(tl);\n" | |
3960 | " for(int a=0;a<%lu;a++) if(field_map[a]>2) field_map[a]-=3;\n" | |
3961 | " sep_found=TRUE;}\n" | |
3962 | " } else if(p_td.text->end_decode){\n" | |
3963 | " int tl;\n" | |
3964 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" | |
3965 | " decoded_length+=tl;\n" | |
3966 | " p_buf.increase_pos(tl);\n" | |
3967 | " limit.remove_tokens(ml);\n" | |
3968 | " if(mand_field_num) return -1;\n" | |
3969 | " return decoded_length;\n" | |
3970 | " }\n" | |
3971 | " } else if(limit.has_token(ml)){\n" | |
3972 | " int tl;\n" | |
3973 | " if((tl=limit.match(p_buf,ml))==0){\n" | |
3974 | " sep_found=FALSE;\n" | |
3975 | " break;\n" | |
3976 | " }\n" | |
3977 | " }\n" | |
3978 | " }\n" | |
3979 | " limit.remove_tokens(ml);\n" | |
3980 | " if(sep_found){\n" | |
3981 | " if(mand_field_num){\n" | |
3982 | " if(no_err)return -1;\n" | |
3983 | " TTCN_EncDec_ErrorContext::error" | |
3984 | "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding '%%s': \"," | |
3985 | "p_td.name);\n" | |
3986 | " return decoded_length;\n" | |
3987 | " } else {\n" | |
3988 | " decoded_length-=sep_length;\n" | |
3989 | " p_buf.set_pos(p_buf.get_pos()-sep_length);\n" | |
3990 | " }\n" | |
3991 | " }\n" | |
3992 | " if(p_td.text->end_decode){\n" | |
3993 | " int tl;\n" | |
3994 | " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" | |
3995 | " if(no_err)return -1;\n" | |
3996 | " TTCN_EncDec_ErrorContext::error" | |
3997 | "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
3998 | " not found for '%%s': \",(const char*)*(p_td.text->end_decode)" | |
3999 | ",p_td.name);\n" | |
4000 | " return decoded_length;\n" | |
4001 | " }\n" | |
4002 | " decoded_length+=tl;\n" | |
4003 | " p_buf.increase_pos(tl);\n" | |
4004 | " }\n" | |
4005 | " if(mand_field_num) return -1;\n" | |
4006 | " return decoded_length;\n" | |
4007 | "}\n" | |
4008 | ,(unsigned long) sdef->nElements | |
4009 | ); | |
4010 | } else { /* record decoder start */ | |
4011 | src = mputprintf(src, | |
4012 | "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td," | |
4013 | " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n" | |
509718e0 | 4014 | " bound_flag = TRUE;\n" |
970ed795 EL |
4015 | " int decoded_length=0;\n" |
4016 | " int decoded_field_length=0;\n" | |
4017 | "%s" | |
4018 | " boolean sep_found=FALSE;\n" | |
4019 | " int sep_length=0;\n" | |
4020 | " int ml=0;\n" | |
4021 | " if(p_td.text->begin_decode){\n" | |
4022 | " int tl;\n" | |
4023 | " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n" | |
4024 | " if(no_err)return -1;\n" | |
4025 | " TTCN_EncDec_ErrorContext::error\n" | |
4026 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
4027 | " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)" | |
4028 | ", p_td.name);\n" | |
4029 | " return 0;\n" | |
4030 | " }\n" | |
4031 | " decoded_length+=tl;\n" | |
4032 | " p_buf.increase_pos(tl);\n" | |
4033 | " }\n" | |
4034 | " if(p_td.text->end_decode){\n" | |
4035 | " limit.add_token(p_td.text->end_decode);\n" | |
4036 | " ml++;\n" | |
4037 | " }\n" | |
4038 | " if(p_td.text->separator_decode){\n" | |
4039 | " limit.add_token(p_td.text->separator_decode);\n" | |
4040 | " ml++;\n" | |
4041 | " }\n" | |
4042 | ,name,opt_number?" size_t pos=p_buf.get_pos();\n":"" | |
4043 | ); | |
4044 | for(i=0;i<sdef->nElements;i++){ | |
4045 | if(sdef->elements[i].isOptional){ | |
4046 | src=mputprintf(src, | |
4047 | " field_%s=OMIT_VALUE;\n" | |
4048 | ,sdef->elements[i].name | |
4049 | ); | |
4050 | } } | |
4051 | src=mputstr(src, | |
4052 | " while(TRUE){\n" | |
4053 | ); | |
4054 | for(i=0;i<sdef->nElements;i++){ | |
4055 | if(sdef->elements[i].isOptional){ | |
4056 | src=mputstr(src, | |
4057 | " pos=p_buf.get_pos();\n" | |
4058 | ); | |
4059 | } | |
4060 | src=mputprintf(src, | |
4061 | " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf" | |
4062 | ",limit,TRUE);\n" | |
4063 | " if(decoded_field_length<0){\n" | |
4064 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4065 | ,sdef->elements[i].typedescrname | |
4066 | ); | |
4067 | if(sdef->elements[i].isOptional){ | |
4068 | src=mputprintf(src, | |
4069 | " field_%s=OMIT_VALUE;\n" | |
4070 | " p_buf.set_pos(pos);\n" | |
4071 | " } else {\n" | |
4072 | ,sdef->elements[i].name | |
4073 | ); | |
4074 | } else { | |
4075 | src=mputprintf(src, | |
4076 | " limit.remove_tokens(ml);\n" | |
4077 | " if(no_err)return -1;\n" | |
4078 | " TTCN_EncDec_ErrorContext::error" | |
4079 | "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding " | |
4080 | "field '%s' for '%%s': \", p_td.name);\n" | |
4081 | " return decoded_length;\n" | |
4082 | " } else {\n" | |
4083 | ,sdef->elements[i].name | |
4084 | ); | |
4085 | } | |
4086 | src=mputstr(src, | |
4087 | " decoded_length+=decoded_field_length;\n" | |
4088 | ); | |
4089 | if(last_man_index>(i+1)){ | |
4090 | src=mputstr(src, | |
4091 | " if(p_td.text->separator_decode){\n" | |
4092 | " int tl;\n" | |
4093 | " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n" | |
4094 | ); | |
4095 | ||
4096 | if(sdef->elements[i].isOptional){ | |
4097 | src=mputprintf(src, | |
4098 | " field_%s=OMIT_VALUE;\n" | |
4099 | " p_buf.set_pos(pos);\n" | |
4100 | " decoded_length-=decoded_field_length;\n" | |
4101 | ,sdef->elements[i].name | |
4102 | ); | |
4103 | } else { | |
4104 | src=mputstr(src, | |
4105 | " limit.remove_tokens(ml);\n" | |
4106 | " if(no_err)return -1;\n" | |
4107 | " TTCN_EncDec_ErrorContext::error" | |
4108 | "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'" | |
4109 | " not found for '%s': \",(const char*)*(p_td.text->" | |
4110 | "separator_decode),p_td.name);\n" | |
4111 | " return decoded_length;\n" | |
4112 | ); | |
4113 | } | |
4114 | ||
4115 | src=mputstr(src, | |
4116 | " } else {\n" | |
4117 | " decoded_length+=tl;\n" | |
4118 | " p_buf.increase_pos(tl);\n" | |
4119 | " sep_length=tl;\n" | |
4120 | " sep_found=TRUE;}\n" | |
4121 | " } else sep_found=FALSE;\n" | |
4122 | ); | |
4123 | } else if(i==(sdef->nElements-1)){ | |
4124 | src=mputstr(src, | |
4125 | " sep_found=FALSE;\n" | |
4126 | ); | |
4127 | } else { | |
4128 | src=mputstr(src, | |
4129 | " if(p_td.text->separator_decode){\n" | |
4130 | " int tl;\n" | |
4131 | " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n" | |
4132 | ); | |
4133 | if(sdef->elements[i].isOptional){ | |
4134 | src=mputprintf(src, | |
4135 | " if(p_td.text->end_decode){\n" | |
4136 | " int tl;\n" | |
4137 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" | |
4138 | " decoded_length+=tl;\n" | |
4139 | " p_buf.increase_pos(tl);\n" | |
4140 | " limit.remove_tokens(ml);\n" | |
4141 | " return decoded_length;\n" | |
4142 | " }\n" | |
4143 | " } else if(limit.has_token(ml)){\n" | |
4144 | " if((tl=limit.match(p_buf,ml))==0){\n" | |
4145 | " sep_found=FALSE;\n" | |
4146 | " break;\n" | |
4147 | " }\n" | |
4148 | " } else break;\n" | |
4149 | " field_%s=OMIT_VALUE;\n" | |
4150 | " p_buf.set_pos(pos);\n" | |
4151 | " decoded_length-=decoded_field_length;\n" | |
4152 | ,sdef->elements[i].name | |
4153 | ); | |
4154 | } else { | |
4155 | src=mputstr(src, | |
4156 | " sep_found=FALSE;\n" | |
4157 | " break;\n" | |
4158 | ); | |
4159 | } | |
4160 | src=mputstr(src, | |
4161 | " } else {\n" | |
4162 | " decoded_length+=tl;\n" | |
4163 | " p_buf.increase_pos(tl);\n" | |
4164 | " sep_length=tl;\n" | |
4165 | " sep_found=TRUE;}\n" | |
4166 | " } else {\n" | |
4167 | " sep_found=FALSE;\n" | |
4168 | " if(p_td.text->end_decode){\n" | |
4169 | " int tl;\n" | |
4170 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" | |
4171 | " decoded_length+=tl;\n" | |
4172 | " p_buf.increase_pos(tl);\n" | |
4173 | " limit.remove_tokens(ml);\n" | |
4174 | " return decoded_length;\n" | |
4175 | " }\n" | |
4176 | " } else if(limit.has_token(ml)){\n" | |
4177 | " int tl;\n" | |
4178 | " if((tl=limit.match(p_buf,ml))==0){\n" | |
4179 | " sep_found=FALSE;\n" | |
4180 | " break;\n" | |
4181 | " }\n" | |
4182 | " }\n" | |
4183 | " }\n" | |
4184 | ); | |
4185 | } | |
4186 | src=mputstr(src, | |
4187 | " }\n" | |
4188 | ); | |
4189 | } | |
4190 | ||
4191 | src = mputstr(src, | |
4192 | " break;\n" | |
4193 | " }\n" | |
4194 | " limit.remove_tokens(ml);\n" | |
4195 | " if(sep_found){\n" | |
4196 | " p_buf.set_pos(p_buf.get_pos()-sep_length);\n" | |
4197 | " decoded_length-=sep_length;\n" | |
4198 | " }\n" | |
4199 | " if(p_td.text->end_decode){\n" | |
4200 | " int tl;\n" | |
4201 | " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" | |
4202 | " if(no_err)return -1;\n" | |
4203 | " TTCN_EncDec_ErrorContext::error" | |
4204 | "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'" | |
4205 | " not found for '%s': \",(const char*)*(p_td.text->end_decode)" | |
4206 | ",p_td.name);\n" | |
4207 | " return decoded_length;\n" | |
4208 | " }\n" | |
4209 | " decoded_length+=tl;\n" | |
4210 | " p_buf.increase_pos(tl);\n" | |
4211 | " }\n" | |
4212 | " return decoded_length;\n" | |
4213 | "}\n" | |
4214 | ); | |
4215 | } | |
4216 | } /* text_needed */ | |
4217 | ||
4218 | /* RAW functions */ | |
4219 | if(raw_needed){ | |
4220 | struct raw_option_struct *raw_options; | |
4221 | boolean haslengthto, haspointer, hascrosstag, has_ext_bit; | |
4222 | raw_options = (struct raw_option_struct*) | |
4223 | Malloc(sdef->nElements * sizeof(*raw_options)); | |
4224 | ||
4225 | set_raw_options(sdef, raw_options, &haslengthto, | |
4226 | &haspointer, &hascrosstag, &has_ext_bit); | |
4227 | ||
4228 | src = generate_raw_coding(src, sdef, raw_options, haspointer, hascrosstag, | |
4229 | has_ext_bit); | |
4230 | ||
4231 | for (i = 0; i < sdef->nElements; i++) { | |
4232 | Free(raw_options[i].lengthoffield); | |
4233 | Free(raw_options[i].dependent_fields); | |
4234 | } | |
4235 | Free(raw_options); | |
4236 | } /* if raw_needed */ | |
4237 | ||
4238 | if (xer_needed) gen_xer(sdef, &def, &src); | |
4239 | ||
4240 | if (json_needed) { | |
4241 | // JSON encode, RT1 | |
4242 | src = mputprintf(src, | |
4243 | "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n" | |
4244 | "{\n" | |
4245 | " if (!is_bound()) {\n" | |
4246 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" | |
4247 | " \"Encoding an unbound value of type %s.\");\n" | |
4248 | " return -1;\n" | |
4249 | " }\n\n" | |
4250 | " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n" | |
4251 | , name, dispname); | |
4252 | for (i = 0; i < sdef->nElements; ++i) { | |
4253 | if (sdef->elements[i].isOptional && !sdef->elements[i].jsonOmitAsNull) { | |
4254 | src = mputprintf(src, | |
4255 | " if (field_%s.is_present())\n" | |
4256 | , sdef->elements[i].name); | |
4257 | } | |
4258 | src=mputprintf(src, | |
4259 | " {\n" | |
4260 | " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n" | |
4261 | " enc_len += field_%s.JSON_encode(%s_descr_, p_tok);\n" | |
4262 | " }\n\n" | |
4263 | , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname | |
4264 | , sdef->elements[i].name, sdef->elements[i].typedescrname); | |
4265 | } | |
4266 | src = mputstr(src, | |
4267 | " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n" | |
4268 | " return enc_len;\n" | |
4269 | "}\n\n"); | |
4270 | ||
4271 | // JSON decode, RT1 | |
4272 | src = mputprintf(src, | |
4273 | "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n" | |
4274 | "{\n" | |
509718e0 | 4275 | " json_token_t j_token = JSON_TOKEN_NONE;\n" |
4276 | " int dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n" | |
4277 | " if (JSON_TOKEN_ERROR == j_token) {\n" | |
970ed795 EL |
4278 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n" |
4279 | " return JSON_ERROR_FATAL;\n" | |
4280 | " }\n" | |
509718e0 | 4281 | " else if (JSON_TOKEN_OBJECT_START != j_token) {\n" |
970ed795 EL |
4282 | " return JSON_ERROR_INVALID_TOKEN;\n" |
4283 | " }\n" | |
4284 | " bound_flag = TRUE;\n\n" | |
4285 | // Read name - value token pairs until we reach some other token | |
4286 | " while (true) {\n" | |
509718e0 | 4287 | " char* fld_name = 0;\n" |
970ed795 EL |
4288 | " size_t name_len = 0;\n" |
4289 | " size_t buf_pos = p_tok.get_buf_pos();\n" | |
509718e0 | 4290 | " dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n" |
4291 | " if (JSON_TOKEN_ERROR == j_token) {\n" | |
970ed795 EL |
4292 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n" |
4293 | " return JSON_ERROR_FATAL;\n" | |
4294 | " }\n" | |
4295 | // undo the last action on the buffer | |
509718e0 | 4296 | " else if (JSON_TOKEN_NAME != j_token) {\n" |
970ed795 EL |
4297 | " p_tok.set_buf_pos(buf_pos);\n" |
4298 | " break;\n" | |
4299 | " }\n" | |
4300 | " else {\n " | |
4301 | , name); | |
4302 | for (i = 0; i < sdef->nElements; ++i) { | |
4303 | src = mputprintf(src, | |
4304 | // check field name | |
509718e0 | 4305 | "if (%d == name_len && 0 == strncmp(fld_name, \"%s\", name_len)) {\n" |
970ed795 EL |
4306 | " int ret_val = field_%s.JSON_decode(%s_descr_, p_tok, p_silent);\n" |
4307 | " if (0 > ret_val) {\n" | |
4308 | " if (JSON_ERROR_INVALID_TOKEN) {\n" | |
4309 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n" | |
4310 | " }\n" | |
4311 | " return JSON_ERROR_FATAL;\n" | |
4312 | " }\n" | |
4313 | " dec_len += ret_val;\n" | |
4314 | " } else " | |
4315 | , (int)strlen(sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname) | |
4316 | , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname | |
4317 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
4318 | , sdef->elements[i].dispname); | |
4319 | } | |
4320 | src = mputstr(src, | |
4321 | "{\n" | |
4322 | // invalid field name | |
509718e0 | 4323 | " char* fld_name2 = mcopystrn(fld_name, name_len);\n" |
4324 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, fld_name2);\n" | |
970ed795 | 4325 | // if this is set to a warning, skip the value of the field |
509718e0 | 4326 | " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n" |
4327 | " if (JSON_TOKEN_NUMBER != j_token && JSON_TOKEN_STRING != j_token &&\n" | |
4328 | " JSON_TOKEN_LITERAL_TRUE != j_token && JSON_TOKEN_LITERAL_FALSE != j_token &&\n" | |
4329 | " JSON_TOKEN_LITERAL_NULL != j_token) {\n" | |
4330 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name2);\n" | |
4331 | " Free(fld_name2);\n" | |
970ed795 EL |
4332 | " return JSON_ERROR_FATAL;\n" |
4333 | " }\n" | |
509718e0 | 4334 | " Free(fld_name2);\n" |
970ed795 EL |
4335 | " }\n" |
4336 | " }\n" | |
4337 | " }\n\n" | |
509718e0 | 4338 | " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n" |
4339 | " if (JSON_TOKEN_OBJECT_END != j_token) {\n" | |
970ed795 EL |
4340 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_OBJECT_END_TOKEN_ERROR, \"\");\n" |
4341 | " return JSON_ERROR_FATAL;\n" | |
4342 | " }\n\n"); | |
4343 | // Check if every field has been set | |
4344 | for (i = 0; i < sdef->nElements; ++i) { | |
4345 | src = mputprintf(src, | |
4346 | " if (!field_%s.is_bound()) {\n" | |
4347 | , sdef->elements[i].name); | |
4348 | if (sdef->elements[i].jsonDefaultValue) { | |
4349 | src = mputprintf(src, | |
4350 | " field_%s.JSON_decode(%s_descr_, DUMMY_BUFFER, p_silent);\n" | |
4351 | , sdef->elements[i].name, sdef->elements[i].typedescrname); | |
4352 | } | |
4353 | else if (sdef->elements[i].isOptional) { | |
4354 | src = mputprintf(src, | |
4355 | " field_%s = OMIT_VALUE;\n" | |
4356 | , sdef->elements[i].name); | |
4357 | } else { | |
4358 | src = mputprintf(src, | |
4359 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_MISSING_FIELD_ERROR, \"%s\");\n" | |
4360 | " return JSON_ERROR_FATAL;\n" | |
4361 | , sdef->elements[i].dispname); | |
4362 | } | |
4363 | src = mputstr(src, | |
4364 | " }\n"); | |
4365 | } | |
4366 | src = mputstr(src, | |
509718e0 | 4367 | "\n return dec_len;\n" |
970ed795 EL |
4368 | "}\n\n"); |
4369 | } | |
4370 | ||
4371 | /* end of class definition */ | |
4372 | def = mputstr(def, "};\n\n"); | |
4373 | ||
4374 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
4375 | Free(def); | |
4376 | ||
4377 | output->source.methods = mputstr(output->source.methods, src); | |
4378 | Free(src); | |
4379 | } | |
4380 | ||
4381 | ||
4382 | static char *genRawFieldDecodeLimit(char *src, const struct_def *sdef, | |
4383 | int i, const struct raw_option_struct *raw_options) | |
4384 | { | |
4385 | /* number of arguments passed to min_of_ints() */ | |
4386 | int nof_args = 1; | |
4387 | int j; | |
4388 | for (j = 0; j < raw_options[i].lengthof; j++) { | |
4389 | int field_index = raw_options[i].lengthoffield[j]; | |
4390 | if (i > field_index && sdef->elements[field_index].raw.unit!=-1) | |
4391 | nof_args++; | |
4392 | } | |
4393 | if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[ | |
4394 | raw_options[i].extbitgroup-1].ext_bit != XDEFNO) nof_args++; | |
4395 | if (nof_args > 1) { | |
4396 | src = mputprintf(src, "min_of_ints(%d, limit", nof_args); | |
4397 | for (j = 0; j < raw_options[i].lengthof; j++) { | |
4398 | int field_index = raw_options[i].lengthoffield[j]; | |
4399 | if (i > field_index && sdef->elements[field_index].raw.unit != -1) | |
4400 | src = mputprintf(src, ", value_of_length_field%d", field_index); | |
4401 | } | |
4402 | if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[ | |
4403 | raw_options[i].extbitgroup-1].ext_bit != XDEFNO) | |
4404 | src = mputstr(src, ", group_limit"); | |
4405 | src = mputc(src, ')'); | |
4406 | } else { | |
4407 | src = mputstr(src, "limit"); | |
4408 | } | |
4409 | return src; | |
4410 | } | |
4411 | ||
4412 | static char *genRawDecodeRecordField(char *src, const struct_def *sdef, | |
4413 | int i, const struct raw_option_struct *raw_options, boolean delayed_decode, | |
4414 | int *prev_ext_group) | |
4415 | { | |
4416 | int a; | |
4417 | if(raw_options[i].ptrbase) | |
4418 | src=mputprintf(src, | |
4419 | " start_pos_of_field%d=p_buf.get_pos_bit();\n" | |
4420 | ,i | |
4421 | ); | |
4422 | if (*prev_ext_group != raw_options[i].extbitgroup) { | |
4423 | *prev_ext_group = raw_options[i].extbitgroup; | |
4424 | if(prev_ext_group && | |
4425 | sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){ | |
4426 | if(raw_options[i].pointerof) /* pointed field */ | |
4427 | src=mputprintf(src, | |
4428 | " {size_t old_pos=p_buf.get_pos_bit();\n" | |
4429 | " if(start_of_field%d!=-1 && start_pos_of_field%d!=-1){\n" | |
4430 | " start_of_field%d=start_pos_of_field%d" | |
4431 | "+(int)field_%s%s*%d+%d;\n" | |
4432 | " p_buf.set_pos_bit(start_of_field%d);\n" | |
4433 | " limit=end_of_available_data-start_of_field%d;\n" | |
4434 | ,i | |
4435 | ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase | |
4436 | ,i | |
4437 | ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase | |
4438 | ,sdef->elements[raw_options[i].pointerof-1].name | |
4439 | ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":"" | |
4440 | ,sdef->elements[raw_options[i].pointerof-1].raw.unit | |
4441 | ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset | |
4442 | ,i,i | |
4443 | ); | |
4444 | src=mputprintf(src, | |
4445 | " {\n" | |
4446 | " cbyte* data=p_buf.get_read_data();\n" | |
4447 | " int count=1;\n" | |
4448 | " int rot=local_top_order==ORDER_LSB?0:7;\n" | |
4449 | " while(((data[count-1]>>rot)&0x01)==%d && count*8<" | |
4450 | "(int)limit) count++;\n" | |
4451 | " if(limit) group_limit=count*8;\n" | |
4452 | " }\n" | |
4453 | ,sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit== | |
4454 | XDEFYES?0:1 | |
4455 | ); | |
4456 | if(raw_options[i].pointerof) /* pointed field */ | |
4457 | src=mputstr(src, | |
4458 | " } else group_limit=0;\n" | |
4459 | " p_buf.set_pos_bit(old_pos);\n" | |
4460 | " limit=end_of_available_data-old_pos;}\n" | |
4461 | ); | |
4462 | } | |
4463 | } | |
4464 | if(sdef->elements[i].hasRaw && /* check the crosstag */ | |
4465 | sdef->elements[i].raw.crosstaglist.nElements){ | |
4466 | /* field index of the otherwise rule */ | |
4467 | int other = -1; | |
4468 | boolean first_value = TRUE; | |
4469 | int j; | |
4470 | for (j = 0; j < sdef->elements[i].raw.crosstaglist.nElements; j++) { | |
4471 | rawAST_coding_taglist* cur_choice = | |
4472 | sdef->elements[i].raw.crosstaglist.list + j; | |
4473 | if (cur_choice->nElements > 0) { | |
4474 | /* this is a normal rule */ | |
4475 | if (first_value) { | |
4476 | src = mputstr(src, " if ("); | |
4477 | first_value = FALSE; | |
4478 | } else src = mputstr(src, " else if ("); | |
4479 | src = genRawFieldChecker(src, cur_choice, TRUE); | |
4480 | /* set selected_field in the if's body */ | |
4481 | src = mputprintf(src, ") selected_field = %d;\n", | |
4482 | cur_choice->fieldnum); | |
4483 | } else { | |
4484 | /* this is an otherwise rule */ | |
4485 | other = cur_choice->fieldnum; | |
4486 | } | |
4487 | } | |
4488 | /* set selected_field to the field index of the otherwise rule or -1 */ | |
4489 | src = mputprintf(src, " else selected_field = %d;\n", other); | |
4490 | } | |
4491 | /* check the presence of optional field*/ | |
4492 | if(sdef->elements[i].isOptional){ | |
4493 | /* check if enough bits to decode the field*/ | |
4494 | src = mputstr(src, " if (limit > 0"); | |
4495 | for (a = 0; a < raw_options[i].lengthof; a++){ | |
4496 | int field_index = raw_options[i].lengthoffield[a]; | |
4497 | if (i > field_index) src = mputprintf(src, | |
4498 | " && value_of_length_field%d > 0", field_index); | |
4499 | } | |
4500 | if (raw_options[i].extbitgroup && | |
4501 | sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){ | |
4502 | src = mputstr(src, " && group_limit > 0"); | |
4503 | } | |
4504 | if(raw_options[i].pointerof){ /* valid pointer?*/ | |
4505 | src=mputprintf(src, | |
4506 | " && start_of_field%d!=-1 && start_pos_of_field%d!=-1" | |
4507 | ,i,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase | |
4508 | ); | |
4509 | } | |
4510 | if(sdef->elements[i].hasRaw && | |
4511 | sdef->elements[i].raw.presence.nElements) | |
4512 | { | |
4513 | src = mputstr(src, " && "); | |
4514 | if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, '('); | |
4515 | src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, TRUE); | |
4516 | if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, ')'); | |
4517 | } | |
4518 | if(sdef->elements[i].hasRaw && | |
4519 | sdef->elements[i].raw.crosstaglist.nElements) | |
4520 | { | |
4521 | src=mputstr(src, | |
4522 | "&& selected_field!=-1" | |
4523 | ); | |
4524 | } | |
4525 | src=mputstr(src, | |
4526 | "){\n" | |
4527 | ); | |
4528 | } | |
4529 | if(raw_options[i].pointerof){ /* pointed field */ | |
4530 | src=mputprintf(src, | |
4531 | " start_of_field%d=start_pos_of_field%d" | |
4532 | "+(int)field_%s%s*%d+%d;\n" | |
4533 | ,i | |
4534 | ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase | |
4535 | ,sdef->elements[raw_options[i].pointerof-1].name | |
4536 | ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":"" | |
4537 | ,sdef->elements[raw_options[i].pointerof-1].raw.unit | |
4538 | ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset | |
4539 | ); | |
4540 | src=mputprintf(src, | |
4541 | " p_buf.set_pos_bit(start_of_field%d);\n" | |
4542 | " limit=end_of_available_data-start_of_field%d;\n" | |
4543 | ,i,i | |
4544 | ); | |
4545 | } | |
4546 | /* decoding of normal field */ | |
4547 | if (sdef->elements[i].isOptional) src = mputstr(src, | |
4548 | " size_t fl_start_pos = p_buf.get_pos_bit();\n"); | |
4549 | src = mputprintf(src, | |
4550 | " decoded_field_length = field_%s%s.RAW_decode(%s_descr_, p_buf, ", | |
4551 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
4552 | sdef->elements[i].typedescrname); | |
4553 | if (delayed_decode) { | |
4554 | /* the fixed field length is used as limit in case of delayed decoding */ | |
4555 | src = mputprintf(src, "%d", sdef->elements[i].raw.length); | |
4556 | } else { | |
4557 | src = genRawFieldDecodeLimit(src, sdef, i, raw_options); | |
4558 | } | |
4559 | src = mputprintf(src, ", local_top_order, %s", | |
4560 | sdef->elements[i].isOptional ? "TRUE" : "no_err"); | |
4561 | if (sdef->elements[i].hasRaw && | |
4562 | sdef->elements[i].raw.crosstaglist.nElements > 0) | |
4563 | src = mputstr(src, ", selected_field"); | |
4564 | for (a = 0; a < raw_options[i].lengthof; a++) { | |
4565 | int field_index = raw_options[i].lengthoffield[a]; | |
4566 | /* number of elements in 'record of' or 'set of' */ | |
4567 | if (sdef->elements[field_index].raw.unit == -1) { | |
4568 | src = mputprintf(src, ", value_of_length_field%d", field_index); | |
4569 | break; | |
4570 | } | |
4571 | } | |
4572 | src = mputstr(src, ");\n"); | |
4573 | if (delayed_decode) { | |
4574 | src = mputprintf(src, " if (decoded_field_length != %d) return -1;\n", | |
4575 | sdef->elements[i].raw.length); | |
4576 | } else if (sdef->elements[i].isOptional) { | |
4577 | src = mputprintf(src, " if (decoded_field_length < 1) {\n" | |
4578 | " field_%s = OMIT_VALUE;\n" /* transform errors into omit */ | |
4579 | " p_buf.set_pos_bit(fl_start_pos);\n" | |
4580 | " } else {\n", sdef->elements[i].name); | |
4581 | } else { | |
4582 | src = mputstr(src, " if (decoded_field_length < 0) return decoded_field_length;\n"); | |
4583 | } | |
4584 | if(raw_options[i].tag_type && sdef->raw.taglist.list[raw_options[i].tag_type-1].nElements){ | |
4585 | rawAST_coding_taglist* cur_choice= | |
4586 | sdef->raw.taglist.list+raw_options[i].tag_type-1; | |
4587 | src=mputstr(src, | |
4588 | " if("); | |
4589 | src=genRawFieldChecker(src,cur_choice,FALSE); | |
4590 | src=mputstr(src, | |
4591 | ")"); | |
4592 | if(sdef->elements[i].isOptional){ | |
4593 | src=mputprintf(src, | |
4594 | "{\n field_%s=OMIT_VALUE;\n" | |
4595 | " p_buf.set_pos_bit(fl_start_pos);\n }\n" | |
4596 | " else {\n" | |
4597 | ,sdef->elements[i].name | |
4598 | ); | |
4599 | }else src=mputstr(src, " return -1;\n"); | |
4600 | } | |
4601 | if (!delayed_decode) { | |
4602 | src=mputstr(src, | |
4603 | " decoded_length+=decoded_field_length;\n" | |
4604 | " limit-=decoded_field_length;\n" | |
4605 | " last_decoded_pos=bigger(last_decoded_pos, p_buf.get_pos_bit());\n" | |
4606 | ); | |
4607 | } | |
4608 | if(raw_options[i].extbitgroup && | |
4609 | sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){ | |
4610 | src=mputstr(src, | |
4611 | "group_limit-=decoded_field_length;\n" | |
4612 | ); | |
4613 | } | |
4614 | if(raw_options[i].lengthto){ /* if the field is lengthto store the value*/ | |
4615 | if(sdef->elements[i].raw.lengthindex){ | |
4616 | if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){ | |
4617 | src=mputprintf(src, | |
4618 | " if(field_%s%s.%s().ispresent()){\n" | |
4619 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4620 | ,sdef->elements[i].raw.lengthindex->nthfieldname | |
4621 | ); | |
4622 | } | |
4623 | src=mputprintf(src, | |
4624 | " value_of_length_field%d+=(int)field_%s%s.%s%s()*%d;\n" | |
4625 | ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4626 | ,sdef->elements[i].raw.lengthindex->nthfieldname | |
4627 | ,sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD?"()":"" | |
4628 | ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit | |
4629 | ); | |
4630 | if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){ | |
4631 | src=mputstr(src, | |
4632 | " }\n" | |
4633 | ); | |
4634 | } | |
4635 | } | |
4636 | else if(sdef->elements[i].raw.union_member_num){ | |
4637 | int m; | |
4638 | src = mputprintf(src, " switch (field_%s%s.get_selection()) {\n", | |
4639 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : ""); | |
4640 | for (m = 1; m < sdef->elements[i].raw.union_member_num + 1; m++) { | |
4641 | src = mputprintf(src, " case %s%s%s:\n" | |
4642 | " value_of_length_field%d += (int)field_%s%s.%s() * %d;\n" | |
4643 | " break;\n", sdef->elements[i].raw.member_name[0], | |
4644 | "::ALT_", | |
4645 | sdef->elements[i].raw.member_name[m], i, sdef->elements[i].name, | |
4646 | sdef->elements[i].isOptional ? "()" : "", | |
4647 | sdef->elements[i].raw.member_name[m], | |
4648 | sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit); | |
4649 | } | |
4650 | src = mputprintf(src, " default:\n" | |
4651 | " value_of_length_field%d = 0;\n" | |
4652 | " }\n", i); | |
4653 | } | |
4654 | else{ | |
4655 | src=mputprintf(src, | |
4656 | " value_of_length_field%d+=(int)field_%s%s*%d;\n" | |
4657 | ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4658 | ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit | |
4659 | ); | |
4660 | } | |
4661 | } | |
4662 | if(raw_options[i].pointerto){ /* store the start of pointed field*/ | |
4663 | src=mputprintf(src, | |
4664 | " start_of_field%d=(int)field_%s%s+%d?1:-1;\n" | |
4665 | ,sdef->elements[i].raw.pointerto | |
4666 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4667 | ,sdef->elements[i].raw.ptroffset | |
4668 | ); | |
4669 | } | |
4670 | if (!delayed_decode) { | |
4671 | /* mark the used bits in length area*/ | |
4672 | for (a = 0; a < raw_options[i].lengthof; a++) { | |
4673 | int field_index = raw_options[i].lengthoffield[a]; | |
4674 | src = mputprintf(src, | |
4675 | " value_of_length_field%d -= decoded_field_length;\n", field_index); | |
4676 | if (i == field_index) src = mputprintf(src, | |
4677 | " if (value_of_length_field%d < 0) return -1;\n", field_index); | |
4678 | } | |
4679 | } | |
4680 | if(sdef->elements[i].isOptional){ | |
4681 | src=mputprintf(src, | |
4682 | " }\n }\n%s" | |
4683 | " else field_%s=OMIT_VALUE;\n" | |
4684 | ,raw_options[i].tag_type?" }\n":"",sdef->elements[i].name | |
4685 | ); | |
4686 | } | |
4687 | return src; | |
4688 | } | |
4689 | ||
4690 | #ifdef __SUNPRO_C | |
4691 | #define SUNPRO_PUBLIC "public:\n" | |
4692 | #define SUNPRO_PRIVATE "private:\n" | |
4693 | #else | |
4694 | #define SUNPRO_PUBLIC | |
4695 | #define SUNPRO_PRIVATE | |
4696 | #endif | |
4697 | ||
4698 | void defRecordTemplate1(const struct_def *sdef, output_struct *output) | |
4699 | { | |
4700 | int i; | |
4701 | const char *name = sdef->name, *dispname = sdef->dispname; | |
4702 | const char* kind_str = sdef->kind == SET ? "set" : "record"; | |
4703 | char *def = NULL, *src = NULL; | |
4704 | ||
4705 | size_t mandatory_fields_count; | |
4706 | ||
4707 | /* class declaration */ | |
4708 | output->header.class_decls = mputprintf(output->header.class_decls, | |
4709 | "class %s_template;\n", name); | |
4710 | ||
4711 | if(sdef->nElements <= 0) { | |
4712 | defEmptyRecordTemplate(name, dispname, output); | |
4713 | return; | |
4714 | } | |
4715 | ||
4716 | /* template class definition */ | |
4717 | def = mputprintf(def, "class %s_template : public Base_Template {\n", name); | |
4718 | ||
4719 | /* data members */ | |
4720 | def = mputprintf(def, | |
4721 | SUNPRO_PUBLIC | |
4722 | "struct single_value_struct;\n" | |
4723 | SUNPRO_PRIVATE | |
4724 | "union {\n" | |
4725 | "single_value_struct *single_value;\n" | |
4726 | "struct {\n" | |
4727 | "unsigned int n_values;\n" | |
4728 | "%s_template *list_value;\n" | |
4729 | "} value_list;\n" | |
4730 | "};\n\n", name); | |
4731 | /* the definition of single_value_struct must be put into the source file | |
4732 | * because the types of optional fields may be incomplete in this position | |
4733 | * of header file (e.g. due to type recursion) */ | |
4734 | src = mputprintf(src, "struct %s_template::single_value_struct {\n", name); | |
4735 | for (i = 0; i < sdef->nElements; i++) { | |
4736 | src = mputprintf(src, "%s_template field_%s;\n", | |
4737 | sdef->elements[i].type, sdef->elements[i].name); | |
4738 | } | |
4739 | src = mputstr(src, "};\n\n"); | |
4740 | ||
4741 | /* set_specific function (used in field access members) */ | |
4742 | def = mputstr(def, "void set_specific();\n"); | |
4743 | src = mputprintf(src, "void %s_template::set_specific()\n" | |
4744 | "{\n" | |
4745 | "if (template_selection != SPECIFIC_VALUE) {\n" | |
4746 | "template_sel old_selection = template_selection;\n" | |
4747 | "clean_up();\n" | |
4748 | "single_value = new single_value_struct;\n" | |
4749 | "set_selection(SPECIFIC_VALUE);\n" | |
4750 | "if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {\n", | |
4751 | name); | |
4752 | for (i = 0; i < sdef->nElements; i++) { | |
4753 | src = mputprintf(src, "single_value->field_%s = %s;\n", | |
4754 | sdef->elements[i].name, | |
4755 | sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE"); | |
4756 | } | |
4757 | src = mputstr(src, "}\n" | |
4758 | "}\n" | |
4759 | "}\n\n"); | |
4760 | ||
4761 | /* copy_value function */ | |
4762 | def = mputprintf(def, "void copy_value(const %s& other_value);\n", name); | |
4763 | src = mputprintf(src, | |
4764 | "void %s_template::copy_value(const %s& other_value)\n" | |
4765 | "{\n" | |
4766 | "single_value = new single_value_struct;\n", name, name); | |
4767 | for (i = 0; i < sdef->nElements; i++) { | |
4768 | src = mputprintf(src, | |
4769 | "if (other_value.%s().is_bound()) {\n", sdef->elements[i].name); | |
4770 | if (sdef->elements[i].isOptional) { | |
4771 | /* If the value is present, "reach into" the OPTIONAL with operator() | |
4772 | * and pass the contained object to the template's constructor. | |
4773 | * Else set the template to omit. */ | |
4774 | src = mputprintf(src, | |
4775 | " if (other_value.%s().ispresent()) single_value->field_%s = " | |
4776 | "other_value.%s()();\n" | |
4777 | " else single_value->field_%s = OMIT_VALUE;\n", | |
4778 | sdef->elements[i].name, sdef->elements[i].name, | |
4779 | sdef->elements[i].name, sdef->elements[i].name); | |
4780 | } else { | |
4781 | src = mputprintf(src, | |
4782 | " single_value->field_%s = other_value.%s();\n", | |
4783 | sdef->elements[i].name, sdef->elements[i].name); | |
4784 | } | |
4785 | src = mputprintf(src, "} else {\n" | |
4786 | " single_value->field_%s.clean_up();\n" | |
4787 | "}\n", sdef->elements[i].name); | |
4788 | } | |
4789 | src = mputstr(src, "set_selection(SPECIFIC_VALUE);\n" | |
4790 | "}\n\n"); | |
4791 | ||
4792 | /* copy_template function */ | |
4793 | def = mputprintf(def, "void copy_template(const %s_template& " | |
4794 | "other_value);\n\n", name); | |
4795 | src = mputprintf(src, | |
4796 | "void %s_template::copy_template(const %s_template& other_value)\n" | |
4797 | "{\n" | |
4798 | "switch (other_value.template_selection) {\n" | |
4799 | "case SPECIFIC_VALUE:\n", name, name); | |
4800 | src = mputstr(src, | |
4801 | "single_value = new single_value_struct;\n"); | |
4802 | for (i = 0; i < sdef->nElements; i++) { | |
4803 | src = mputprintf(src, | |
4804 | "if (UNINITIALIZED_TEMPLATE != other_value.%s().get_selection()) {\n", | |
4805 | sdef->elements[i].name); | |
4806 | src = mputprintf(src, | |
4807 | "single_value->field_%s = other_value.%s();\n", | |
4808 | sdef->elements[i].name, sdef->elements[i].name); | |
4809 | src = mputprintf(src, "} else {\n" | |
4810 | "single_value->field_%s.clean_up();\n" | |
4811 | "}\n", sdef->elements[i].name); | |
4812 | } | |
4813 | src = mputprintf(src, | |
4814 | "case OMIT_VALUE:\n" | |
4815 | "case ANY_VALUE:\n" | |
4816 | "case ANY_OR_OMIT:\n" | |
4817 | "break;\n" | |
4818 | "case VALUE_LIST:\n" | |
4819 | "case COMPLEMENTED_LIST:\n" | |
4820 | "value_list.n_values = other_value.value_list.n_values;\n" | |
4821 | "value_list.list_value = new %s_template[value_list.n_values];\n" | |
4822 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
4823 | "list_count++)\n" | |
4824 | "value_list.list_value[list_count].copy_template(" | |
4825 | "other_value.value_list.list_value[list_count]);\n" | |
4826 | "break;\n" | |
4827 | "default:\n" | |
4828 | "TTCN_error(\"Copying an uninitialized/unsupported template of type " | |
4829 | "%s.\");\n" | |
4830 | "break;\n" | |
4831 | "}\n" | |
4832 | "set_selection(other_value);\n" | |
4833 | "}\n\n", name, dispname); | |
4834 | ||
4835 | /* default constructor */ | |
4836 | def = mputprintf(def, "public:\n" | |
4837 | "%s_template();\n", name); | |
4838 | src = mputprintf(src, "%s_template::%s_template()\n" | |
4839 | "{\n" | |
4840 | "}\n\n", name, name); | |
4841 | ||
4842 | /* constructor t1_template(template_sel other_value) */ | |
4843 | def = mputprintf(def, "%s_template(template_sel other_value);\n", name); | |
4844 | src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n" | |
4845 | " : Base_Template(other_value)\n" | |
4846 | "{\n" | |
4847 | "check_single_selection(other_value);\n" | |
4848 | "}\n\n", name, name); | |
4849 | ||
4850 | /* constructor t1_template(const t1& other_value) */ | |
4851 | def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name); | |
4852 | src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n" | |
4853 | "{\n" | |
4854 | "copy_value(other_value);\n" | |
4855 | "}\n\n", name, name, name); | |
4856 | ||
4857 | /* constructor t1_template(const OPTIONAL<t1>& other_value) */ | |
4858 | def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n", | |
4859 | name, name); | |
4860 | src = mputprintf(src, | |
4861 | "%s_template::%s_template(const OPTIONAL<%s>& other_value)\n" | |
4862 | "{\n" | |
4863 | "switch (other_value.get_selection()) {\n" | |
4864 | "case OPTIONAL_PRESENT:\n" | |
4865 | "copy_value((const %s&)other_value);\n" | |
4866 | "break;\n" | |
4867 | "case OPTIONAL_OMIT:\n" | |
4868 | "set_selection(OMIT_VALUE);\n" | |
4869 | "break;\n" | |
4870 | "default:\n" | |
4871 | "TTCN_error(\"Creating a template of type %s from an unbound optional " | |
4872 | "field.\");\n" | |
4873 | "}\n" | |
4874 | "}\n\n", name, name, name, name, dispname); | |
4875 | ||
4876 | /* copy constructor */ | |
4877 | def = mputprintf(def, "%s_template(const %s_template& other_value);\n", | |
4878 | name, name); | |
4879 | src = mputprintf(src, "%s_template::%s_template(const %s_template& " | |
4880 | "other_value)\n" | |
4881 | ": Base_Template()\n" /* yes, the base class _default_ constructor */ | |
4882 | "{\n" | |
4883 | "copy_template(other_value);\n" | |
4884 | "}\n\n", name, name, name); | |
4885 | ||
4886 | /* destructor */ | |
4887 | def = mputprintf(def, "~%s_template();\n", name); | |
4888 | src = mputprintf(src, "%s_template::~%s_template()\n" | |
4889 | "{\n" | |
4890 | "clean_up();\n" | |
4891 | "}\n\n", name, name); | |
4892 | ||
4893 | /* assignment operator <- template_sel */ | |
4894 | def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n", | |
4895 | name); | |
4896 | src = mputprintf(src, | |
4897 | "%s_template& %s_template::operator=(template_sel other_value)\n" | |
4898 | "{\n" | |
4899 | "check_single_selection(other_value);\n" | |
4900 | "clean_up();\n" | |
4901 | "set_selection(other_value);\n" | |
4902 | "return *this;\n" | |
4903 | "}\n\n", name, name); | |
4904 | ||
4905 | /* assignment operator <- value */ | |
4906 | def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n", | |
4907 | name, name); | |
4908 | ||
4909 | src = mputprintf(src, | |
4910 | "%s_template& %s_template::operator=(const %s& other_value)\n" | |
4911 | "{\n" | |
4912 | "clean_up();\n" | |
4913 | "copy_value(other_value);\n" | |
4914 | "return *this;\n" | |
4915 | "}\n\n", name, name, name); | |
4916 | ||
4917 | /* assignment operator <- optional value */ | |
4918 | def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& " | |
4919 | "other_value);\n", name, name); | |
4920 | ||
4921 | src = mputprintf(src, | |
4922 | "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n" | |
4923 | "{\n" | |
4924 | "clean_up();\n" | |
4925 | "switch (other_value.get_selection()) {\n" | |
4926 | "case OPTIONAL_PRESENT:\n" | |
4927 | "copy_value((const %s&)other_value);\n" | |
4928 | "break;\n" | |
4929 | "case OPTIONAL_OMIT:\n" | |
4930 | "set_selection(OMIT_VALUE);\n" | |
4931 | "break;\n" | |
4932 | "default:\n" | |
4933 | "TTCN_error(\"Assignment of an unbound optional field to a template " | |
4934 | "of type %s.\");\n" | |
4935 | "}\n" | |
4936 | "return *this;\n" | |
4937 | "}\n\n", name, name, name, name, dispname); | |
4938 | ||
4939 | /* assignment operator <- template*/ | |
4940 | def = mputprintf(def, | |
4941 | "%s_template& operator=(const %s_template& other_value);\n", | |
4942 | name, name); | |
4943 | ||
4944 | src = mputprintf(src, | |
4945 | "%s_template& %s_template::operator=(const %s_template& other_value)\n" | |
4946 | "{\n" | |
4947 | "if (&other_value != this) {\n" | |
4948 | "clean_up();\n" | |
4949 | "copy_template(other_value);\n" | |
4950 | "}\n" | |
4951 | "return *this;\n" | |
4952 | "}\n\n", name, name, name); | |
4953 | ||
4954 | /* match operation (template matching) */ | |
4955 | def = mputprintf(def, "boolean match(const %s& other_value) const;\n", | |
4956 | name); | |
4957 | ||
4958 | src = mputprintf(src, | |
4959 | "boolean %s_template::match(const %s& other_value) const\n" | |
4960 | "{\n" | |
4961 | "if (!other_value.is_bound()) return FALSE;\n" | |
4962 | "switch (template_selection) {\n" | |
4963 | "case ANY_VALUE:\n" | |
4964 | "case ANY_OR_OMIT:\n" | |
4965 | "return TRUE;\n" | |
4966 | "case OMIT_VALUE:\n" | |
4967 | "return FALSE;\n" | |
4968 | "case SPECIFIC_VALUE:\n", name, name); | |
4969 | for (i = 0; i < sdef->nElements; i++) { | |
4970 | src = mputprintf(src,"if(!other_value.%s().is_bound()) return FALSE;\n", sdef->elements[i].name); | |
4971 | if (sdef->elements[i].isOptional) src = mputprintf(src, | |
4972 | "if((other_value.%s().ispresent() ? " | |
4973 | "!single_value->field_%s.match((const %s&)other_value.%s()) : " | |
4974 | "!single_value->field_%s.match_omit()))", | |
4975 | sdef->elements[i].name, sdef->elements[i].name, | |
4976 | sdef->elements[i].type, sdef->elements[i].name, | |
4977 | sdef->elements[i].name); | |
4978 | else src = mputprintf(src, | |
4979 | "if(!single_value->field_%s.match(other_value.%s()))", | |
4980 | sdef->elements[i].name, sdef->elements[i].name); | |
4981 | src = mputstr(src, "return FALSE;\n"); | |
4982 | } | |
4983 | src = mputprintf(src, | |
4984 | "return TRUE;\n" | |
4985 | "case VALUE_LIST:\n" | |
4986 | "case COMPLEMENTED_LIST:\n" | |
4987 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
4988 | "list_count++)\n" | |
4989 | "if (value_list.list_value[list_count].match(other_value)) " | |
4990 | "return template_selection == VALUE_LIST;\n" | |
4991 | "return template_selection == COMPLEMENTED_LIST;\n" | |
4992 | "default:\n" | |
4993 | "TTCN_error(\"Matching an uninitialized/unsupported template of " | |
4994 | "type %s.\");\n" | |
4995 | "}\n" | |
4996 | "return FALSE;\n" | |
4997 | "}\n\n", dispname); | |
4998 | ||
4999 | /* is_bound */ | |
5000 | def = mputstr(def, "boolean is_bound() const;\n"); | |
5001 | ||
5002 | src = mputprintf(src, "boolean %s_template::is_bound() const\n" | |
5003 | "{\n" | |
5004 | "if (template_selection == UNINITIALIZED_TEMPLATE && !is_ifpresent) " | |
5005 | "return FALSE;\n", name); | |
5006 | src = mputstr(src, "if (template_selection != SPECIFIC_VALUE) return TRUE;\n"); | |
5007 | for (i = 0; i < sdef->nElements; i++) { | |
5008 | if (sdef->elements[i].isOptional) { | |
5009 | src = mputprintf(src, | |
5010 | "if (single_value->field_%s.is_omit() ||" | |
5011 | " single_value->field_%s.is_bound()) return TRUE;\n", | |
5012 | sdef->elements[i].name, sdef->elements[i].name); | |
5013 | } else { | |
5014 | src = mputprintf(src, | |
5015 | "if (single_value->field_%s.is_bound()) return TRUE;\n", | |
5016 | sdef->elements[i].name); | |
5017 | } | |
5018 | } | |
5019 | src = mputstr(src, "return FALSE;\n" | |
5020 | "}\n\n"); | |
5021 | ||
5022 | /* is_value */ | |
5023 | def = mputstr(def, "boolean is_value() const;\n"); | |
5024 | ||
5025 | src = mputprintf(src, "boolean %s_template::is_value() const\n" | |
5026 | "{\n" | |
5027 | "if (template_selection != SPECIFIC_VALUE || is_ifpresent) " | |
5028 | "return FALSE;\n", name); | |
5029 | for (i = 0; i < sdef->nElements; i++) { | |
5030 | if (sdef->elements[i].isOptional) { | |
5031 | src = mputprintf(src, | |
5032 | "if (!single_value->field_%s.is_omit() &&" | |
5033 | " !single_value->field_%s.is_value()) return FALSE;\n", | |
5034 | sdef->elements[i].name, sdef->elements[i].name); | |
5035 | } else { | |
5036 | src = mputprintf(src, | |
5037 | "if (!single_value->field_%s.is_value()) return FALSE;\n", | |
5038 | sdef->elements[i].name); | |
5039 | } | |
5040 | } | |
5041 | src = mputstr(src, "return TRUE;\n" | |
5042 | "}\n\n"); | |
5043 | ||
5044 | /* clean_up function */ | |
5045 | def = mputstr(def, "void clean_up();\n"); | |
5046 | src = mputprintf(src, | |
5047 | "void %s_template::clean_up()\n" | |
5048 | "{\n" | |
5049 | "switch (template_selection) {\n" | |
5050 | "case SPECIFIC_VALUE:\n" | |
5051 | "delete single_value;\n" | |
5052 | "break;\n" | |
5053 | "case VALUE_LIST:\n" | |
5054 | "case COMPLEMENTED_LIST:\n" | |
5055 | "delete [] value_list.list_value;\n" | |
5056 | "default:\n" | |
5057 | "break;\n" | |
5058 | "}\n" | |
5059 | "template_selection = UNINITIALIZED_TEMPLATE;\n" | |
5060 | "}\n\n", name); | |
5061 | ||
5062 | /* valueof operation */ | |
5063 | def = mputprintf(def, "%s valueof() const;\n", name); | |
5064 | ||
5065 | src = mputprintf(src, "%s %s_template::valueof() const\n" | |
5066 | "{\n" | |
5067 | "if (template_selection != SPECIFIC_VALUE || is_ifpresent)\n" | |
5068 | "TTCN_error(\"Performing valueof or send operation on a non-specific " | |
5069 | "template of type %s.\");\n" | |
5070 | "%s ret_val;\n", name, name, dispname, name); | |
5071 | for (i = 0; i < sdef->nElements; i++) { | |
5072 | if (sdef->elements[i].isOptional) { | |
5073 | src = mputprintf(src, | |
5074 | "if (single_value->field_%s.is_omit()) " | |
5075 | "ret_val.%s() = OMIT_VALUE;\n" | |
5076 | "else ", | |
5077 | sdef->elements[i].name, sdef->elements[i].name); | |
5078 | } | |
5079 | src = mputprintf(src, "if (single_value->field_%s.is_bound()) {\n" | |
5080 | "ret_val.%s() = single_value->field_%s.valueof();\n" | |
5081 | "}\n", | |
5082 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); | |
5083 | } | |
5084 | src = mputstr(src, "return ret_val;\n" | |
5085 | "}\n\n"); | |
5086 | ||
5087 | /* void set_type(template_sel, int) function */ | |
5088 | def = mputstr(def, | |
5089 | "void set_type(template_sel template_type, " | |
5090 | "unsigned int list_length);\n"); | |
5091 | ||
5092 | src = mputprintf(src, | |
5093 | "void %s_template::set_type(template_sel template_type, " | |
5094 | "unsigned int list_length)\n" | |
5095 | "{\n" | |
5096 | "if (template_type != VALUE_LIST " | |
5097 | "&& template_type != COMPLEMENTED_LIST)\n" | |
5098 | "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n" | |
5099 | "clean_up();\n" | |
5100 | "set_selection(template_type);\n" | |
5101 | "value_list.n_values = list_length;\n" | |
5102 | "value_list.list_value = new %s_template[list_length];\n" | |
5103 | "}\n\n", name, dispname, name); | |
5104 | ||
5105 | /* list_item(int) function */ | |
5106 | ||
5107 | def = mputprintf(def, | |
5108 | "%s_template& list_item(unsigned int list_index) const;\n", name); | |
5109 | ||
5110 | src = mputprintf(src, | |
5111 | "%s_template& %s_template::list_item(unsigned int list_index) const\n" | |
5112 | "{\n" | |
5113 | "if (template_selection != VALUE_LIST " | |
5114 | "&& template_selection != COMPLEMENTED_LIST)\n" | |
5115 | "TTCN_error(\"Accessing a list element of a non-list template of " | |
5116 | "type %s.\");\n" | |
5117 | "if (list_index >= value_list.n_values)\n" | |
5118 | "TTCN_error(\"Index overflow in a value list template of type " | |
5119 | "%s.\");\n" | |
5120 | "return value_list.list_value[list_index];\n" | |
5121 | "}\n\n", name, name, dispname, dispname); | |
5122 | ||
5123 | /* template field access functions (non-const & const) */ | |
5124 | for (i = 0; i < sdef->nElements; i++) { | |
5125 | def = mputprintf(def, "%s_template& %s();\n", | |
5126 | sdef->elements[i].type, sdef->elements[i].name); | |
5127 | src = mputprintf(src, "%s_template& %s_template::%s()\n" | |
5128 | "{\n" | |
5129 | "set_specific();\n" | |
5130 | "return single_value->field_%s;\n" | |
5131 | "}\n\n", | |
5132 | sdef->elements[i].type, name, sdef->elements[i].name, | |
5133 | sdef->elements[i].name); | |
5134 | def = mputprintf(def, "const %s_template& %s() const;\n", | |
5135 | sdef->elements[i].type, sdef->elements[i].name); | |
5136 | src = mputprintf(src, "const %s_template& %s_template::%s() const\n" | |
5137 | "{\n" | |
5138 | "if (template_selection != SPECIFIC_VALUE)\n" | |
5139 | "TTCN_error(\"Accessing field %s of a non-specific " | |
5140 | "template of type %s.\");\n" | |
5141 | "return single_value->field_%s;\n" | |
5142 | "}\n\n", | |
5143 | sdef->elements[i].type, name, sdef->elements[i].name, | |
5144 | sdef->elements[i].dispname, dispname, sdef->elements[i].name); | |
5145 | } | |
5146 | ||
5147 | /* sizeof operation */ | |
5148 | def = mputstr(def, "int size_of() const;\n"); | |
5149 | src = mputprintf(src, | |
5150 | "int %s_template::size_of() const\n" | |
5151 | "{\n" | |
5152 | " if (is_ifpresent) TTCN_error(\"Performing sizeof() operation on a " | |
5153 | "template of type %s which has an ifpresent attribute.\");\n" | |
5154 | " switch (template_selection)\n" | |
5155 | " {\n" | |
5156 | " case SPECIFIC_VALUE:\n", | |
5157 | name, dispname); | |
5158 | mandatory_fields_count = 0; | |
5159 | for (i = 0; i < sdef->nElements; i++) | |
5160 | if (!sdef->elements[i].isOptional) mandatory_fields_count++; | |
5161 | if(sdef->nElements == mandatory_fields_count){ | |
5162 | src = mputprintf(src," return %lu;\n", | |
5163 | (unsigned long) mandatory_fields_count); | |
5164 | }else{ | |
5165 | src = mputprintf(src, | |
5166 | " {" | |
5167 | " int ret_val = %lu;\n", (unsigned long) mandatory_fields_count); | |
5168 | for (i = 0; i < sdef->nElements; i++) | |
5169 | if (sdef->elements[i].isOptional) | |
5170 | src = mputprintf(src, | |
5171 | " if (single_value->field_%s.is_present()) ret_val++;\n", | |
5172 | sdef->elements[i].name); | |
5173 | src = mputstr(src, | |
5174 | " return ret_val;\n" | |
5175 | " }\n"); | |
5176 | } | |
5177 | src = mputprintf(src, | |
5178 | ||
5179 | " case VALUE_LIST:\n" | |
5180 | " {\n" | |
5181 | " if (value_list.n_values<1)\n" | |
5182 | " TTCN_error(\"Internal error: Performing sizeof() operation on a " | |
5183 | "template of type %s containing an empty list.\");\n" | |
5184 | " int item_size = value_list.list_value[0].size_of();\n" | |
5185 | " for (unsigned int l_idx = 1; l_idx < value_list.n_values; l_idx++)\n" | |
5186 | " {\n" | |
5187 | " if (value_list.list_value[l_idx].size_of()!=item_size)\n" | |
5188 | " TTCN_error(\"Performing sizeof() operation on a template " | |
5189 | "of type %s containing a value list with different sizes.\");\n" | |
5190 | " }\n" | |
5191 | " return item_size;\n" | |
5192 | " }\n" | |
5193 | " case OMIT_VALUE:\n" | |
5194 | " TTCN_error(\"Performing sizeof() operation on a template of type %s " | |
5195 | "containing omit value.\");\n" | |
5196 | " case ANY_VALUE:\n" | |
5197 | " case ANY_OR_OMIT:\n" | |
5198 | " TTCN_error(\"Performing sizeof() operation on a template of type %s " | |
5199 | "containing */? value.\");\n" | |
5200 | " case COMPLEMENTED_LIST:\n" | |
5201 | " TTCN_error(\"Performing sizeof() operation on a template of type %s " | |
5202 | "containing complemented list.\");\n" | |
5203 | " default:\n" | |
5204 | " TTCN_error(\"Performing sizeof() operation on an " | |
5205 | "uninitialized/unsupported template of type %s.\");\n" | |
5206 | " }\n" | |
5207 | " return 0;\n" | |
5208 | "}\n\n", | |
5209 | dispname,dispname,dispname,dispname,dispname,dispname); | |
5210 | ||
5211 | /* log function */ | |
5212 | def = mputstr(def, "void log() const;\n"); | |
5213 | src = mputprintf(src, | |
5214 | "void %s_template::log() const\n" | |
5215 | "{\n" | |
5216 | "switch (template_selection) {\n" | |
5217 | "case SPECIFIC_VALUE:\n", name); | |
5218 | for (i = 0; i < sdef->nElements; i++) { | |
5219 | src = mputstr(src, "TTCN_Logger::log_event_str(\""); | |
5220 | if (i == 0) src = mputc(src, '{'); | |
5221 | else src = mputc(src, ','); | |
5222 | src = mputprintf(src, " %s := \");\n" | |
5223 | "single_value->field_%s.log();\n", | |
5224 | sdef->elements[i].dispname, sdef->elements[i].name); | |
5225 | } | |
5226 | src = mputstr(src, | |
5227 | "TTCN_Logger::log_event_str(\" }\");\n" | |
5228 | "break;\n" | |
5229 | "case COMPLEMENTED_LIST:\n" | |
5230 | "TTCN_Logger::log_event_str(\"complement \");\n" | |
5231 | "case VALUE_LIST:\n" | |
5232 | "TTCN_Logger::log_char('(');\n" | |
5233 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
5234 | "list_count++) {\n" | |
5235 | "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n" | |
5236 | "value_list.list_value[list_count].log();\n" | |
5237 | "}\n" | |
5238 | "TTCN_Logger::log_char(')');\n" | |
5239 | "break;\n" | |
5240 | "default:\n" | |
5241 | "log_generic();\n" | |
5242 | "}\n" | |
5243 | "log_ifpresent();\n" | |
5244 | "}\n\n"); | |
5245 | ||
5246 | /* log_match function */ | |
5247 | def = mputprintf(def, "void log_match(const %s& match_value) " | |
5248 | "const;\n", name); | |
5249 | src = mputprintf(src, | |
5250 | "void %s_template::log_match(const %s& match_value) const\n" | |
5251 | "{\n" | |
5252 | "if(TTCN_Logger::VERBOSITY_COMPACT" | |
5253 | " == TTCN_Logger::get_matching_verbosity()){\n" | |
5254 | "if(match(match_value)){\n" | |
5255 | "TTCN_Logger::print_logmatch_buffer();\n" | |
5256 | "TTCN_Logger::log_event_str(\" matched\");\n" | |
5257 | "} else{\n" | |
5258 | "if (template_selection == SPECIFIC_VALUE) {\n" | |
5259 | "size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();\n" | |
5260 | , name, name); | |
5261 | for (i = 0; i < sdef->nElements; i++) { | |
5262 | if (sdef->elements[i].isOptional){ | |
5263 | src = mputprintf(src, | |
5264 | "if (match_value.%s().ispresent()){\n" | |
5265 | "if(!single_value->field_%s.match(match_value.%s())){\n" | |
5266 | "TTCN_Logger::log_logmatch_info(\".%s\");\n" | |
5267 | "single_value->field_%s.log_match(match_value.%s());\n" | |
5268 | "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n" | |
5269 | "}\n" | |
5270 | "} else {\n" | |
5271 | "if (!single_value->field_%s.match_omit()){\n " | |
5272 | "TTCN_Logger::log_logmatch_info(\".%s := omit with \");\n" | |
5273 | "TTCN_Logger::print_logmatch_buffer();\n" | |
5274 | "single_value->field_%s.log();\n" | |
5275 | "TTCN_Logger::log_event_str(\" unmatched\");\n" | |
5276 | "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n" | |
5277 | "}\n" | |
5278 | "}\n" | |
5279 | , sdef->elements[i].name, sdef->elements[i].name, | |
5280 | sdef->elements[i].name, sdef->elements[i].dispname, | |
5281 | sdef->elements[i].name, sdef->elements[i].name, | |
5282 | sdef->elements[i].name, sdef->elements[i].dispname, | |
5283 | sdef->elements[i].name); | |
5284 | }else{ | |
5285 | src = mputprintf(src, | |
5286 | "if(!single_value->field_%s.match(match_value.%s())){\n" | |
5287 | "TTCN_Logger::log_logmatch_info(\".%s\");\n" | |
5288 | "single_value->field_%s.log_match(match_value.%s());\n" | |
5289 | "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n" | |
5290 | "}\n",sdef->elements[i].name, sdef->elements[i].name, | |
5291 | sdef->elements[i].dispname, sdef->elements[i].name, | |
5292 | sdef->elements[i].name); | |
5293 | } | |
5294 | } | |
5295 | ||
5296 | src = mputstr(src,"}else {\n" | |
5297 | "TTCN_Logger::print_logmatch_buffer();\n" | |
5298 | "match_value.log();\n" | |
5299 | "TTCN_Logger::log_event_str(\" with \");\n" | |
5300 | "log();\n" | |
5301 | "TTCN_Logger::log_event_str(\" unmatched\");\n" | |
5302 | "}\n" | |
5303 | "}\n" | |
5304 | "return;\n" | |
5305 | "}\n" | |
5306 | "if (template_selection == SPECIFIC_VALUE) {\n"); | |
5307 | for (i = 0; i < sdef->nElements; i++) { | |
5308 | src = mputstr(src, "TTCN_Logger::log_event_str(\""); | |
5309 | if (i == 0) src = mputc(src, '{'); | |
5310 | else src = mputc(src, ','); | |
5311 | src = mputprintf(src, " %s := \");\n", sdef->elements[i].dispname); | |
5312 | if (sdef->elements[i].isOptional) src = mputprintf(src, | |
5313 | "if (match_value.%s().ispresent()) " | |
5314 | "single_value->field_%s.log_match(match_value.%s());\n" | |
5315 | "else {\n" | |
5316 | "TTCN_Logger::log_event_str(\"omit with \");\n" | |
5317 | "single_value->field_%s.log();\n" | |
5318 | "if (single_value->field_%s.match_omit()) " | |
5319 | "TTCN_Logger::log_event_str(\" matched\");\n" | |
5320 | "else TTCN_Logger::log_event_str(\" unmatched\");\n" | |
5321 | "}\n", | |
5322 | sdef->elements[i].name, sdef->elements[i].name, | |
5323 | sdef->elements[i].name, sdef->elements[i].name, | |
5324 | sdef->elements[i].name); | |
5325 | else src = mputprintf(src, | |
5326 | "single_value->field_%s.log_match(match_value.%s());\n", | |
5327 | sdef->elements[i].name, sdef->elements[i].name); | |
5328 | } | |
5329 | src = mputstr(src, | |
5330 | "TTCN_Logger::log_event_str(\" }\");\n" | |
5331 | "} else {\n" | |
5332 | "match_value.log();\n" | |
5333 | "TTCN_Logger::log_event_str(\" with \");\n" | |
5334 | "log();\n" | |
5335 | "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n" | |
5336 | "else TTCN_Logger::log_event_str(\" unmatched\");\n" | |
5337 | "}\n" | |
5338 | "}\n\n"); | |
5339 | ||
5340 | /*encode_text function*/ | |
5341 | def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); | |
5342 | src = mputprintf(src, | |
5343 | "void %s_template::encode_text(Text_Buf& text_buf) const\n" | |
5344 | "{\n" | |
5345 | "encode_text_base(text_buf);\n" | |
5346 | "switch (template_selection) {\n" | |
5347 | "case SPECIFIC_VALUE:\n", name); | |
5348 | for (i = 0; i < sdef->nElements; i++) { | |
5349 | src = mputprintf(src, "single_value->field_%s.encode_text(text_buf);\n", | |
5350 | sdef->elements[i].name); | |
5351 | } | |
5352 | src = mputprintf(src, | |
5353 | "case OMIT_VALUE:\n" | |
5354 | "case ANY_VALUE:\n" | |
5355 | "case ANY_OR_OMIT:\n" | |
5356 | "break;\n" | |
5357 | "case VALUE_LIST:\n" | |
5358 | "case COMPLEMENTED_LIST:\n" | |
5359 | "text_buf.push_int(value_list.n_values);\n" | |
5360 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
5361 | "list_count++)\n" | |
5362 | "value_list.list_value[list_count].encode_text(text_buf);\n" | |
5363 | "break;\n" | |
5364 | "default:\n" | |
5365 | "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported " | |
5366 | "template of type %s.\");\n" | |
5367 | "}\n" | |
5368 | "}\n\n", dispname); | |
5369 | ||
5370 | /*decode_text function*/ | |
5371 | def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); | |
5372 | src = mputprintf(src, | |
5373 | "void %s_template::decode_text(Text_Buf& text_buf)\n" | |
5374 | "{\n" | |
5375 | "clean_up();\n" | |
5376 | "decode_text_base(text_buf);\n" | |
5377 | "switch (template_selection) {\n" | |
5378 | "case SPECIFIC_VALUE:\n" | |
5379 | "single_value = new single_value_struct;\n", name); | |
5380 | for (i = 0; i < sdef->nElements; i++) { | |
5381 | src = mputprintf(src, "single_value->field_%s.decode_text(text_buf);\n", | |
5382 | sdef->elements[i].name); | |
5383 | } | |
5384 | src = mputprintf(src, | |
5385 | "case OMIT_VALUE:\n" | |
5386 | "case ANY_VALUE:\n" | |
5387 | "case ANY_OR_OMIT:\n" | |
5388 | "break;\n" | |
5389 | "case VALUE_LIST:\n" | |
5390 | "case COMPLEMENTED_LIST:\n" | |
5391 | "value_list.n_values = text_buf.pull_int().get_val();\n" | |
5392 | "value_list.list_value = new %s_template[value_list.n_values];\n" | |
5393 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
5394 | "list_count++)\n" | |
5395 | "value_list.list_value[list_count].decode_text(text_buf);\n" | |
5396 | "break;\n" | |
5397 | "default:\n" | |
5398 | "TTCN_error(\"Text decoder: An unknown/unsupported selection was " | |
5399 | "received in a template of type %s.\");\n" | |
5400 | "}\n" | |
5401 | "}\n\n", name, dispname); | |
5402 | ||
5403 | /* set_param() */ | |
5404 | def = mputstr(def, "void set_param(Module_Param& param);\n"); | |
5405 | src = mputprintf(src, | |
5406 | "void %s_template::set_param(Module_Param& param)\n" | |
5407 | "{\n" | |
5408 | " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n" | |
5409 | " param.get_id()->next_name()) {\n" | |
5410 | // Haven't reached the end of the module parameter name | |
5411 | // => the name refers to one of the fields, not to the whole record | |
5412 | " char* param_field = param.get_id()->get_current_name();\n" | |
5413 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" | |
5414 | " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n" | |
5415 | " \" name for %s template type `%s'\");\n" | |
5416 | " }\n" | |
5417 | " ", name, kind_str, dispname); | |
5418 | for (i = 0; i < sdef->nElements; i++) { | |
5419 | src = mputprintf(src, | |
5420 | "if (strcmp(\"%s\", param_field) == 0) {\n" | |
5421 | " %s().set_param(param);\n" | |
5422 | " return;\n" | |
5423 | " } else ", | |
5424 | sdef->elements[i].dispname, sdef->elements[i].name); | |
5425 | } | |
5426 | src = mputprintf(src, | |
5427 | "param.error(\"Field `%%s' not found in %s template type `%s'\", param_field);\n" | |
5428 | " }\n" | |
5429 | " param.basic_check(Module_Param::BC_TEMPLATE, \"%s template\");\n" | |
5430 | " switch (param.get_type()) {\n" | |
5431 | " case Module_Param::MP_Omit:\n" | |
5432 | " *this = OMIT_VALUE;\n" | |
5433 | " break;\n" | |
5434 | " case Module_Param::MP_Any:\n" | |
5435 | " *this = ANY_VALUE;\n" | |
5436 | " break;\n" | |
5437 | " case Module_Param::MP_AnyOrNone:\n" | |
5438 | " *this = ANY_OR_OMIT;\n" | |
5439 | " break;\n" | |
5440 | " case Module_Param::MP_List_Template:\n" | |
5441 | " case Module_Param::MP_ComplementList_Template:\n" | |
5442 | " set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());\n" | |
5443 | " for (size_t p_i=0; p_i<param.get_size(); p_i++) {\n" | |
5444 | " list_item(p_i).set_param(*param.get_elem(p_i));\n" | |
5445 | " }\n" | |
5446 | " break;\n" | |
5447 | " case Module_Param::MP_Value_List:\n" | |
5448 | " if (%lu<param.get_size()) {\n" | |
5449 | " param.error(\"%s template of type %s has %lu fields but list value has %%d fields\", (int)param.get_size());\n" | |
5450 | " }\n", | |
5451 | kind_str, dispname, kind_str, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements); | |
5452 | for (i = 0; i < sdef->nElements; ++i) { | |
5453 | src = mputprintf(src, | |
5454 | " if (param.get_size()>%lu && param.get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*param.get_elem(%lu));\n", | |
5455 | (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i); | |
5456 | } | |
5457 | src = mputstr(src, | |
5458 | " break;\n" | |
5459 | " case Module_Param::MP_Assignment_List: {\n" | |
5460 | " Vector<bool> value_used(param.get_size());\n" | |
5461 | " value_used.resize(param.get_size(), false);\n"); | |
5462 | for (i = 0; i < sdef->nElements; ++i) { | |
5463 | src = mputprintf(src, | |
5464 | " for (size_t val_idx=0; val_idx<param.get_size(); val_idx++) {\n" | |
5465 | " Module_Param* const curr_param = param.get_elem(val_idx);\n" | |
5466 | " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n" | |
5467 | " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n" | |
5468 | " %s().set_param(*curr_param);\n" | |
5469 | " }\n" | |
5470 | " value_used[val_idx]=true;\n" | |
5471 | " }\n" | |
5472 | " }\n" | |
5473 | , sdef->elements[i].dispname, sdef->elements[i].name); | |
5474 | } | |
5475 | src = mputprintf(src, | |
5476 | " for (size_t val_idx=0; val_idx<param.get_size(); val_idx++) if (!value_used[val_idx]) {\n" | |
5477 | " param.get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", param.get_elem(val_idx)->get_id()->get_name());\n" | |
5478 | " break;\n" | |
5479 | " }\n" | |
5480 | " } break;\n" | |
5481 | " default:\n" | |
5482 | " param.type_error(\"%s template\", \"%s\");\n" | |
5483 | " }\n" | |
5484 | " is_ifpresent = param.get_ifpresent();\n" | |
5485 | "}\n\n", dispname, kind_str, dispname); | |
5486 | ||
5487 | /* check template restriction */ | |
5488 | def = mputstr(def, "void check_restriction(template_res t_res, " | |
5489 | "const char* t_name=NULL) const;\n"); | |
5490 | src = mputprintf(src, | |
5491 | "void %s_template::check_restriction(" | |
5492 | "template_res t_res, const char* t_name) const\n" | |
5493 | "{\n" | |
5494 | "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n" | |
5495 | "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n" | |
5496 | "case TR_OMIT:\n" | |
5497 | "if (template_selection==OMIT_VALUE) return;\n" | |
5498 | "case TR_VALUE:\n" | |
5499 | "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n", | |
5500 | name); | |
5501 | for (i = 0; i < sdef->nElements; i++) { | |
5502 | src = mputprintf(src, "single_value->field_%s.check_restriction(" | |
5503 | "t_res, t_name ? t_name : \"%s\");\n", | |
5504 | sdef->elements[i].name, dispname); | |
5505 | } | |
5506 | src = mputprintf(src, | |
5507 | "return;\n" | |
5508 | "case TR_PRESENT:\n" | |
5509 | "if (!match_omit()) return;\n" | |
5510 | "break;\n" | |
5511 | "default:\n" | |
5512 | "return;\n" | |
5513 | "}\n" | |
5514 | "TTCN_error(\"Restriction `%%s' on template of type %%s " | |
5515 | "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n" | |
5516 | "}\n\n", dispname); | |
5517 | ||
5518 | defCommonRecordTemplate(name, &def, &src); | |
5519 | ||
5520 | def = mputstr(def, "};\n\n"); | |
5521 | ||
5522 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
5523 | Free(def); | |
5524 | ||
5525 | output->source.methods = mputstr(output->source.methods, src); | |
5526 | Free(src); | |
5527 | } | |
5528 | ||
5529 | static void defEmptyRecordClass(const struct_def *sdef, | |
5530 | output_struct *output) | |
5531 | { | |
5532 | const char *name = sdef->name, *dispname = sdef->dispname; | |
5533 | char *def = NULL, *src = NULL; | |
5534 | boolean ber_needed = sdef->isASN1 && enable_ber(); | |
5535 | boolean raw_needed = sdef->hasRaw && enable_raw(); | |
5536 | boolean text_needed = sdef->hasText && enable_text(); | |
5537 | boolean xer_needed = sdef->hasXer && enable_xer(); | |
5538 | boolean json_needed = sdef->hasJson && enable_json(); | |
5539 | ||
5540 | def = mputprintf(def, | |
5541 | #ifndef NDEBUG | |
5542 | "// written by %s in " __FILE__ " at line %d\n" | |
5543 | #endif | |
5544 | "class %s : public Base_Type {\n" | |
5545 | "boolean bound_flag;\n" | |
5546 | "public:\n" | |
5547 | #ifndef NDEBUG | |
5548 | , __FUNCTION__, __LINE__ | |
5549 | #endif | |
5550 | , name); | |
5551 | ||
5552 | /* default ctor */ | |
5553 | def = mputprintf(def, "%s();\n", name); | |
5554 | src = mprintf("%s::%s()\n" | |
5555 | "{\n" | |
5556 | "bound_flag = FALSE;\n" | |
5557 | "}\n\n", name, name); | |
5558 | ||
5559 | /* ctor from NULL_VALUE (i.e. {}) */ | |
5560 | def = mputprintf(def, "%s(null_type other_value);\n", name); | |
5561 | src = mputprintf(src, "%s::%s(null_type)\n" | |
5562 | "{\n" | |
5563 | "bound_flag = TRUE;\n" | |
5564 | "}\n\n", name, name); | |
5565 | ||
5566 | /* copy ctor */ | |
5567 | def = mputprintf(def, "%s(const %s& other_value);\n", name, name); | |
5568 | src = mputprintf(src, "%s::%s(const %s& other_value)\n" | |
5569 | "{\n" | |
5570 | "other_value.must_bound(\"Copying an unbound value of " | |
5571 | "type %s.\");\n" | |
5572 | "bound_flag = TRUE;\n" | |
5573 | "}\n\n", name, name, name, dispname); | |
5574 | ||
5575 | /* assignment op: from NULL_VALUE */ | |
5576 | def = mputprintf(def, "%s& operator=(null_type other_value);\n", name); | |
5577 | src = mputprintf(src, "%s& %s::operator=(null_type)\n" | |
5578 | "{\n" | |
5579 | "bound_flag = TRUE;\n" | |
5580 | "return *this;\n" | |
5581 | "}\n\n", name, name); | |
5582 | ||
5583 | /* assignment op: from itself */ | |
5584 | def = mputprintf(def, "%s& operator=(const %s& other_value);\n", name, | |
5585 | name); | |
5586 | src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n" | |
5587 | "{\n" | |
5588 | "other_value.must_bound(\"Assignment of an unbound value of type " | |
5589 | "%s.\");\n" | |
5590 | "bound_flag = TRUE;\n" | |
5591 | "return *this;\n" | |
5592 | "}\n\n", name, name, name, dispname); | |
5593 | ||
5594 | /* comparison op: with NULL_VALUE */ | |
5595 | def = mputstr(def, "boolean operator==(null_type other_value) const;\n"); | |
5596 | src = mputprintf(src, | |
5597 | "boolean %s::operator==(null_type) const\n" | |
5598 | "{\n" | |
5599 | "must_bound(\"Comparison of an unbound value of type %s.\");\n" | |
5600 | "return TRUE;\n" | |
5601 | "}\n\n", name, dispname); | |
5602 | ||
5603 | /* comparison op: with itself */ | |
5604 | def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n", | |
5605 | name); | |
5606 | src = mputprintf(src, | |
5607 | "boolean %s::operator==(const %s& other_value) const\n" | |
5608 | "{\n" | |
5609 | "must_bound(\"Comparison of an unbound value of type %s.\");\n" | |
5610 | "other_value.must_bound(\"Comparison of an unbound value of type " | |
5611 | "%s.\");\n" | |
5612 | "return TRUE;\n" | |
5613 | "}\n\n", name, name, dispname, dispname); | |
5614 | ||
5615 | /* non-equal operators */ | |
5616 | def = mputprintf(def, | |
5617 | "inline boolean operator!=(null_type other_value) const " | |
5618 | "{ return !(*this == other_value); }\n" | |
5619 | "inline boolean operator!=(const %s& other_value) const " | |
5620 | "{ return !(*this == other_value); }\n", name); | |
5621 | ||
5622 | ||
5623 | /* is_bound function */ | |
5624 | def = mputstr(def, "inline boolean is_bound() const " | |
5625 | "{ return bound_flag; }\n"); | |
5626 | ||
5627 | /* is_present function */ | |
5628 | def = mputstr(def, | |
5629 | "inline boolean is_present() const { return is_bound(); }\n"); | |
5630 | ||
5631 | /* is_value function */ | |
5632 | def = mputstr(def, "inline boolean is_value() const " | |
5633 | "{ return bound_flag; }\n"); | |
5634 | ||
5635 | /* clean_up function */ | |
5636 | def = mputstr(def, "inline void clean_up() " | |
5637 | "{ bound_flag = FALSE; }\n"); | |
5638 | ||
5639 | /* must_bound function */ | |
5640 | def = mputstr(def, "inline void must_bound(const char *err_msg) const " | |
5641 | "{ if (!bound_flag) TTCN_error(\"%s\", err_msg); }\n"); | |
5642 | ||
5643 | /* log function */ | |
5644 | def = mputstr(def, "void log() const;\n"); | |
5645 | src = mputprintf(src, "void %s::log() const\n" | |
5646 | "{\n" | |
5647 | "if (bound_flag) TTCN_Logger::log_event_str(\"{ }\");\n" | |
5648 | "else TTCN_Logger::log_event_unbound();\n" | |
5649 | "}\n\n", name); | |
5650 | ||
5651 | /* set_param function */ | |
5652 | def = mputstr(def, "void set_param(const Module_Param& param);\n"); | |
5653 | src = mputprintf(src, "void %s::set_param(const Module_Param& param)\n" | |
5654 | "{\n" | |
5655 | " param.basic_check(Module_Param::BC_VALUE, \"empty record/set value (i.e. { })\");\n" | |
5656 | " if (param.get_type()!=Module_Param::MP_Value_List || param.get_size()>0) {\n" | |
5657 | " param.type_error(\"empty record/set value (i.e. { })\", \"%s\");\n" | |
5658 | " }\n" | |
5659 | " bound_flag = TRUE;\n" | |
5660 | "}\n\n", name, dispname); | |
5661 | ||
5662 | /* encode_text function */ | |
5663 | def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); | |
5664 | src = mputprintf(src, "void %s::encode_text(Text_Buf& /*text_buf*/) const\n" | |
5665 | "{\n" | |
5666 | "must_bound(\"Text encoder: Encoding an unbound value of type %s.\");\n" | |
5667 | "}\n\n", name, dispname); | |
5668 | ||
5669 | /* decode_text function */ | |
5670 | def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); | |
5671 | src = mputprintf(src, "void %s::decode_text(Text_Buf& /*text_buf*/)\n" | |
5672 | "{\n" | |
5673 | "bound_flag = TRUE;\n" | |
5674 | "}\n\n", name); | |
5675 | ||
5676 | if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) | |
5677 | def_encdec(name, &def, &src, ber_needed, raw_needed, | |
5678 | text_needed, xer_needed, json_needed, FALSE); | |
5679 | ||
5680 | /* BER functions */ | |
5681 | if(ber_needed) { | |
5682 | /* BER_encode_TLV() */ | |
5683 | src=mputprintf | |
5684 | (src, | |
5685 | "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td," | |
5686 | " unsigned p_coding) const\n" | |
5687 | "{\n" | |
5688 | " BER_chk_descr(p_td);\n" | |
5689 | " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n" | |
5690 | " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n" | |
5691 | " return new_tlv;\n" | |
5692 | "}\n" | |
5693 | "\n" | |
5694 | , name | |
5695 | ); | |
5696 | ||
5697 | /* BER_decode_TLV() */ | |
5698 | src=mputprintf | |
5699 | (src, | |
5700 | "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td," | |
5701 | " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n" | |
5702 | "{\n" | |
5703 | " BER_chk_descr(p_td);\n" | |
5704 | " ASN_BER_TLV_t stripped_tlv;\n" | |
5705 | " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n" | |
5706 | " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n" | |
5707 | " stripped_tlv.chk_constructed_flag(TRUE);\n" | |
5708 | " bound_flag=TRUE;\n" | |
5709 | " return TRUE;\n" | |
5710 | "}\n" | |
5711 | "\n" | |
5712 | , name, sdef->dispname | |
5713 | ); | |
5714 | } /* if ber_needed */ | |
5715 | if(text_needed){ | |
5716 | src = mputprintf(src, | |
5717 | "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td," | |
5718 | "TTCN_Buffer& p_buf) const{\n" | |
5719 | " int encoded_length=0;\n" | |
5720 | " if(p_td.text->begin_encode){\n" | |
5721 | " p_buf.put_cs(*p_td.text->begin_encode);\n" | |
5722 | " encoded_length+=p_td.text->begin_encode->lengthof();\n" | |
5723 | " }\n" | |
5724 | " if(!bound_flag) {\n" | |
5725 | " TTCN_EncDec_ErrorContext::error\n" | |
5726 | " (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
5727 | " }\n" | |
5728 | " if(p_td.text->end_encode){\n" | |
5729 | " p_buf.put_cs(*p_td.text->end_encode);\n" | |
5730 | " encoded_length+=p_td.text->end_encode->lengthof();\n" | |
5731 | " }\n" | |
5732 | " return encoded_length;\n" | |
5733 | "}\n" | |
5734 | ,name | |
5735 | ); | |
5736 | src = mputprintf(src, | |
5737 | "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td," | |
5738 | " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n" | |
509718e0 | 5739 | " bound_flag = TRUE;\n" |
970ed795 EL |
5740 | " int decoded_length=0;\n" |
5741 | " if(p_td.text->begin_decode){\n" | |
5742 | " int tl;\n" | |
5743 | " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n" | |
5744 | " if(no_err)return -1;\n" | |
5745 | " TTCN_EncDec_ErrorContext::error\n" | |
5746 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
5747 | " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)" | |
5748 | ", p_td.name);\n" | |
5749 | " return 0;\n" | |
5750 | " }\n" | |
5751 | " decoded_length+=tl;\n" | |
5752 | " p_buf.increase_pos(tl);\n" | |
5753 | " }\n" | |
5754 | " if(p_td.text->end_decode){\n" | |
5755 | " int tl;\n" | |
5756 | " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" | |
5757 | " if(no_err)return -1;\n" | |
5758 | " TTCN_EncDec_ErrorContext::error\n" | |
5759 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
5760 | " not found for '%%s': \",(const char*)*(p_td.text->end_decode)" | |
5761 | ", p_td.name);\n" | |
5762 | " return 0;\n" | |
5763 | " }\n" | |
5764 | " decoded_length+=tl;\n" | |
5765 | " p_buf.increase_pos(tl);\n" | |
5766 | " }\n" | |
970ed795 EL |
5767 | " return decoded_length;\n" |
5768 | "}\n" | |
5769 | ,name | |
5770 | ); | |
5771 | ||
5772 | } | |
5773 | /* RAW functions */ | |
5774 | if (raw_needed) { | |
5775 | src = mputprintf(src, | |
5776 | "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td, " | |
5777 | "RAW_enc_tree& /*myleaf*/) const\n" | |
5778 | "{\n" | |
5779 | "if (!bound_flag) TTCN_EncDec_ErrorContext::error" | |
5780 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value of " | |
5781 | "type %%s.\", p_td.name);\n" | |
5782 | "return 0;\n" | |
5783 | "}\n\n", name); | |
5784 | ||
5785 | src = mputprintf(src, | |
5786 | "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, " | |
5787 | "TTCN_Buffer& p_buf, int, raw_order_t, boolean, int, boolean)\n" | |
5788 | "{\n" | |
5789 | "bound_flag = TRUE;\n" | |
5790 | "return p_buf.increase_pos_padd(p_td.raw->prepadding) + " | |
5791 | "p_buf.increase_pos_padd(p_td.raw->padding);\n" | |
5792 | "}\n\n", name); | |
5793 | } | |
5794 | ||
5795 | if (xer_needed) { /* XERSTUFF codegen for empty record/SEQUENCE */ | |
5796 | src=mputprintf(src, | |
5797 | "boolean %s::can_start(const char *p_name, const char *p_uri, " | |
5798 | "const XERdescriptor_t& p_td, unsigned int p_flavor) {\n" | |
5799 | " boolean e_xer = is_exer(p_flavor);\n" | |
5800 | " if (e_xer && (p_td.xer_bits & UNTAGGED)) return false;\n" | |
5801 | " else return check_name(p_name, p_td, e_xer) && (!e_xer || check_namespace(p_uri, p_td));\n" | |
5802 | "}\n\n" | |
5803 | , name | |
5804 | ||
5805 | ); | |
5806 | src = mputprintf(src, | |
af710487 | 5807 | "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, " |
5808 | "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const{\n" | |
970ed795 EL |
5809 | " int encoded_length=(int)p_buf.get_len();\n" |
5810 | " int is_indented = !is_canonical(p_flavor);\n" | |
5811 | " int e_xer = is_exer(p_flavor);\n" | |
5812 | " if (is_indented) do_indent(p_buf, p_indent);\n" | |
5813 | " p_buf.put_c('<');\n" | |
5814 | " if (e_xer) write_ns_prefix(p_td, p_buf);\n" | |
5815 | " p_buf.put_s((size_t)p_td.namelens[e_xer]-2, (cbyte*)p_td.names[e_xer]);\n" | |
5816 | " p_buf.put_s(2 + is_indented, (cbyte*)\"/>\\n\");\n" | |
5817 | " return (int)p_buf.get_len() - encoded_length;\n" | |
5818 | "}\n\n" | |
5819 | , name); | |
5820 | src = mputprintf(src, | |
5821 | #ifndef NDEBUG | |
5822 | "// written by %s in " __FILE__ " at %d\n" | |
5823 | #endif | |
5824 | "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, " | |
af710487 | 5825 | "unsigned int p_flavor, embed_values_dec_struct_t*)\n" |
970ed795 EL |
5826 | "{\n" |
5827 | " int e_xer = is_exer(p_flavor);\n" | |
5828 | " bound_flag = true;\n" | |
5829 | " int rd_ok, depth=-1;\n" | |
5830 | " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" | |
5831 | " int type = p_reader.NodeType();\n" | |
5832 | " if (type==XML_READER_TYPE_ELEMENT) {\n" | |
5833 | " verify_name(p_reader, p_td, e_xer);\n" | |
5834 | " depth=p_reader.Depth();\n" | |
5835 | " if (p_reader.IsEmptyElement()) {\n" | |
5836 | " rd_ok = p_reader.Read(); break;\n" | |
5837 | " }\n" | |
5838 | " else if ((p_flavor & XER_MASK) == XER_CANONICAL) {\n" | |
5839 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, " | |
5840 | "\"Expected an empty element tag\");\n" | |
5841 | " }\n" | |
5842 | " }\n" | |
5843 | " else if (type == XML_READER_TYPE_END_ELEMENT && depth != -1) {\n" | |
5844 | " verify_end(p_reader, p_td, depth, e_xer);\n" | |
5845 | " rd_ok = p_reader.Read(); break;\n" | |
5846 | " }\n" | |
5847 | " }\n" | |
5848 | " return 1;\n" | |
5849 | "}\n\n" | |
5850 | #ifndef NDEBUG | |
5851 | , __FUNCTION__, __LINE__ | |
5852 | #endif | |
5853 | , name); | |
5854 | } | |
5855 | if (json_needed) { | |
5856 | // JSON encode, RT1 | |
5857 | src = mputprintf(src, | |
5858 | "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n" | |
5859 | "{\n" | |
5860 | " if (!is_bound()) {\n" | |
5861 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" | |
5862 | " \"Encoding an unbound value of type %s.\");\n" | |
5863 | " return -1;\n" | |
5864 | " }\n\n" | |
5865 | " return p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL) + \n" | |
5866 | " p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n" | |
5867 | "}\n\n" | |
5868 | , name, dispname); | |
5869 | ||
5870 | // JSON decode, RT1 | |
5871 | src = mputprintf(src, | |
5872 | "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n" | |
5873 | "{\n" | |
5874 | " json_token_t token = JSON_TOKEN_NONE;\n" | |
5875 | " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n" | |
5876 | " if (JSON_TOKEN_ERROR == token) {\n" | |
5877 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n" | |
5878 | " return JSON_ERROR_FATAL;\n" | |
5879 | " }\n" | |
5880 | " else if (JSON_TOKEN_OBJECT_START != token) {\n" | |
5881 | " return JSON_ERROR_INVALID_TOKEN;\n" | |
5882 | " }\n\n" | |
5883 | " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n" | |
5884 | " if (JSON_TOKEN_OBJECT_END != token) {\n" | |
5885 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n" | |
5886 | " return JSON_ERROR_FATAL;\n" | |
5887 | " }\n\n" | |
5888 | " bound_flag = true;\n\n" | |
5889 | " return dec_len;\n" | |
5890 | "}\n\n" | |
5891 | , name); | |
5892 | } | |
5893 | ||
5894 | /* closing class definition */ | |
5895 | def = mputstr(def, "};\n\n"); | |
5896 | ||
5897 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
5898 | Free(def); | |
5899 | ||
5900 | output->source.methods = mputstr(output->source.methods, src); | |
5901 | Free(src); | |
5902 | ||
5903 | output->header.function_prototypes = | |
5904 | mputprintf(output->header.function_prototypes, | |
5905 | "extern boolean operator==(null_type null_value, const %s& " | |
5906 | "other_value);\n", name); | |
5907 | output->source.function_bodies = | |
5908 | mputprintf(output->source.function_bodies, | |
5909 | "boolean operator==(null_type, const %s& other_value)\n" | |
5910 | "{\n" | |
5911 | "other_value.must_bound(\"Comparison of an unbound value of type " | |
5912 | "%s.\");\n" | |
5913 | "return TRUE;\n" | |
5914 | "}\n\n", name, dispname); | |
5915 | ||
5916 | output->header.function_prototypes = | |
5917 | mputprintf(output->header.function_prototypes, | |
5918 | "inline boolean operator!=(null_type null_value, const %s& " | |
5919 | "other_value) " | |
5920 | "{ return !(null_value == other_value); }\n", name); | |
5921 | } | |
5922 | ||
5923 | static void defEmptyRecordTemplate(const char *name, const char *dispname, | |
5924 | output_struct *output) | |
5925 | { | |
5926 | char *def = NULL, *src = NULL; | |
5927 | ||
5928 | /* class definition */ | |
5929 | def = mprintf("class %s_template : public Base_Template {\n" | |
5930 | "struct {\n" | |
5931 | "unsigned int n_values;\n" | |
5932 | "%s_template *list_value;\n" | |
5933 | "} value_list;\n", name, name); | |
5934 | ||
5935 | /* copy_template function */ | |
5936 | def = mputprintf(def, "void copy_template(const %s_template& " | |
5937 | "other_value);\n\n", name); | |
5938 | src = mputprintf(src, | |
5939 | "void %s_template::copy_template(const %s_template& other_value)\n" | |
5940 | "{\n" | |
5941 | "set_selection(other_value);\n" | |
5942 | "switch (template_selection) {\n" | |
5943 | "case OMIT_VALUE:\n" | |
5944 | "case ANY_VALUE:\n" | |
5945 | "case ANY_OR_OMIT:\n" | |
5946 | "case SPECIFIC_VALUE:\n" | |
5947 | "break;\n" | |
5948 | "case VALUE_LIST:\n" | |
5949 | "case COMPLEMENTED_LIST:\n" | |
5950 | "value_list.n_values = other_value.value_list.n_values;\n" | |
5951 | "value_list.list_value = new %s_template[value_list.n_values];\n" | |
5952 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
5953 | "list_count++)\n" | |
5954 | "value_list.list_value[list_count].copy_template(" | |
5955 | "other_value.value_list.list_value[list_count]);\n" | |
5956 | "break;\n" | |
5957 | "default:\n" | |
5958 | "TTCN_error(\"Copying an uninitialized/unsupported template of type " | |
5959 | "%s.\");\n" | |
5960 | "break;\n" | |
5961 | "}\n" | |
5962 | "}\n\n", name, name, name, dispname); | |
5963 | ||
5964 | /* default ctor */ | |
5965 | def = mputprintf(def, "public:\n" | |
5966 | "%s_template();\n", name); | |
5967 | src = mputprintf(src, "%s_template::%s_template()\n" | |
5968 | "{\n" | |
5969 | "}\n\n", name, name); | |
5970 | ||
5971 | /* ctor for generic wildcards */ | |
5972 | def = mputprintf(def, "%s_template(template_sel other_value);\n", name); | |
5973 | src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n" | |
5974 | " : Base_Template(other_value)\n" | |
5975 | "{\n" | |
5976 | "check_single_selection(other_value);\n" | |
5977 | "}\n\n", name, name); | |
5978 | ||
5979 | /* ctor for value {} */ | |
5980 | def = mputprintf(def, "%s_template(null_type other_value);\n", name); | |
5981 | src = mputprintf(src, "%s_template::%s_template(null_type)\n" | |
5982 | " : Base_Template(SPECIFIC_VALUE)\n" | |
5983 | "{\n" | |
5984 | "}\n\n", name, name); | |
5985 | ||
5986 | /* ctor for specific value */ | |
5987 | def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name); | |
5988 | src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n" | |
5989 | " : Base_Template(SPECIFIC_VALUE)\n" | |
5990 | "{\n" | |
5991 | "other_value.must_bound(\"Creating a template from an unbound value of " | |
5992 | "type %s.\");\n" | |
5993 | "}\n\n", name, name, name, dispname); | |
5994 | ||
5995 | /* ctor for optional value */ | |
5996 | def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n", | |
5997 | name, name); | |
5998 | src = mputprintf(src, "%s_template::%s_template(const OPTIONAL<%s>& " | |
5999 | "other_value)\n" | |
6000 | "{\n" | |
6001 | "switch (other_value.get_selection()) {\n" | |
6002 | "case OPTIONAL_PRESENT:\n" | |
6003 | "set_selection(SPECIFIC_VALUE);\n" | |
6004 | "break;\n" | |
6005 | "case OPTIONAL_OMIT:\n" | |
6006 | "set_selection(OMIT_VALUE);\n" | |
6007 | "break;\n" | |
6008 | "default:\n" | |
6009 | "TTCN_error(\"Creating a template of type %s from an unbound optional " | |
6010 | "field.\");\n" | |
6011 | "}\n" | |
6012 | "}\n\n", name, name, name, dispname); | |
6013 | ||
6014 | /* copy ctor */ | |
6015 | def = mputprintf(def, "%s_template(const %s_template& other_value);\n", | |
6016 | name, name); | |
6017 | src = mputprintf(src, "%s_template::%s_template(const %s_template& " | |
6018 | "other_value)\n" | |
6019 | ": Base_Template()" /* yes, the base class _default_ constructor */ | |
6020 | "{\n" | |
6021 | "copy_template(other_value);\n" | |
6022 | "}\n\n", name, name, name); | |
6023 | ||
6024 | /* dtor */ | |
6025 | def = mputprintf(def, "~%s_template();\n", name); | |
6026 | src = mputprintf(src, "%s_template::~%s_template()\n" | |
6027 | "{\n" | |
6028 | "clean_up();\n" | |
6029 | "}\n\n", name, name); | |
6030 | ||
6031 | /* clean_up function */ | |
6032 | def = mputstr(def, "void clean_up();\n"); | |
6033 | src = mputprintf(src, "void %s_template::clean_up()\n" | |
6034 | "{\n" | |
6035 | "if (template_selection == VALUE_LIST || " | |
6036 | "template_selection == COMPLEMENTED_LIST)\n" | |
6037 | "delete [] value_list.list_value;\n" | |
6038 | "template_selection = UNINITIALIZED_TEMPLATE;\n" | |
6039 | "}\n\n", name); | |
6040 | ||
6041 | /* assignment op for generic wildcards */ | |
6042 | def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n", | |
6043 | name); | |
6044 | src = mputprintf(src, "%s_template& %s_template::operator=(template_sel " | |
6045 | "other_value)\n" | |
6046 | "{\n" | |
6047 | "check_single_selection(other_value);\n" | |
6048 | "clean_up();\n" | |
6049 | "set_selection(other_value);\n" | |
6050 | "return *this;\n" | |
6051 | "}\n\n", name, name); | |
6052 | ||
6053 | /* assignment op for value {} */ | |
6054 | def = mputprintf(def, "%s_template& operator=(null_type other_value);\n", | |
6055 | name); | |
6056 | src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n" | |
6057 | "{\n" | |
6058 | "clean_up();\n" | |
6059 | "set_selection(SPECIFIC_VALUE);\n" | |
6060 | "return *this;\n" | |
6061 | "}\n\n", name, name); | |
6062 | ||
6063 | /* assignment op for specific value */ | |
6064 | def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n", | |
6065 | name, name); | |
6066 | src = mputprintf(src, "%s_template& %s_template::operator=(const %s& " | |
6067 | "other_value)\n" | |
6068 | "{\n" | |
6069 | "other_value.must_bound(\"Assignment of an unbound value of type %s " | |
6070 | "to a template.\");\n" | |
6071 | "clean_up();\n" | |
6072 | "set_selection(SPECIFIC_VALUE);\n" | |
6073 | "return *this;\n" | |
6074 | "}\n\n", name, name, name, dispname); | |
6075 | ||
6076 | /* assignment op for optional value */ | |
6077 | def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& " | |
6078 | "other_value);\n", name, name); | |
6079 | src = mputprintf(src, "%s_template& %s_template::operator=" | |
6080 | "(const OPTIONAL<%s>& other_value)\n" | |
6081 | "{\n" | |
6082 | "clean_up();\n" | |
6083 | "switch (other_value.get_selection()) {\n" | |
6084 | "case OPTIONAL_PRESENT:\n" | |
6085 | "set_selection(SPECIFIC_VALUE);\n" | |
6086 | "break;\n" | |
6087 | "case OPTIONAL_OMIT:\n" | |
6088 | "set_selection(OMIT_VALUE);\n" | |
6089 | "break;\n" | |
6090 | "default:\n" | |
6091 | "TTCN_error(\"Assignment of an unbound optional field to a template " | |
6092 | "of type %s.\");\n" | |
6093 | "}\n" | |
6094 | "return *this;\n" | |
6095 | "}\n\n", name, name, name, dispname); | |
6096 | ||
6097 | /* assignment op for itself */ | |
6098 | def = mputprintf(def, "%s_template& operator=(const %s_template& " | |
6099 | "other_value);\n", name, name); | |
6100 | src = mputprintf(src, "%s_template& %s_template::operator=" | |
6101 | "(const %s_template& other_value)\n" | |
6102 | "{\n" | |
6103 | "if (&other_value != this) {\n" | |
6104 | "clean_up();\n" | |
6105 | "set_selection(other_value);\n" | |
6106 | "}\n" | |
6107 | "return *this;\n" | |
6108 | "}\n\n", name, name, name); | |
6109 | ||
6110 | /* match operation with {} */ | |
6111 | def = mputstr(def, "boolean match(null_type other_value) const;\n"); | |
6112 | src = mputprintf(src, "boolean %s_template::match(null_type other_value) " | |
6113 | "const\n" | |
6114 | "{\n" | |
6115 | "switch (template_selection) {\n" | |
6116 | "case ANY_VALUE:\n" | |
6117 | "case ANY_OR_OMIT:\n" | |
6118 | "case SPECIFIC_VALUE:\n" | |
6119 | "return TRUE;\n" | |
6120 | "case OMIT_VALUE:\n" | |
6121 | "return FALSE;\n" | |
6122 | "case VALUE_LIST:\n" | |
6123 | "case COMPLEMENTED_LIST:\n" | |
6124 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
6125 | "list_count++)\n" | |
6126 | "if (value_list.list_value[list_count].match(other_value)) " | |
6127 | "return template_selection == VALUE_LIST;\n" | |
6128 | "return template_selection == COMPLEMENTED_LIST;\n" | |
6129 | "default:\n" | |
6130 | "TTCN_error(\"Matching an uninitialized/unsupported template of " | |
6131 | "type %s.\");\n" | |
6132 | "}\n" | |
6133 | "return FALSE;\n" | |
6134 | "}\n\n", name, dispname); | |
6135 | ||
6136 | /* match operation with specific value */ | |
6137 | def = mputprintf(def, "boolean match(const %s& other_value) const;\n", | |
6138 | name); | |
6139 | src = mputprintf(src, "boolean %s_template::match(const %s& other_value) " | |
6140 | "const\n" | |
6141 | "{\n" | |
6142 | "if (!other_value.is_bound()) return FALSE;" | |
6143 | "return match(NULL_VALUE);\n" | |
6144 | "}\n\n", name, name); | |
6145 | ||
6146 | /* valueof operation */ | |
6147 | def = mputprintf(def, "%s valueof() const;\n", name); | |
6148 | src = mputprintf(src, "%s %s_template::valueof() const\n" | |
6149 | "{\n" | |
6150 | "if (template_selection != SPECIFIC_VALUE || is_ifpresent) " | |
6151 | "TTCN_error(\"Performing a valueof or send operation on a " | |
6152 | "non-specific template of type %s.\");\n" | |
6153 | "return NULL_VALUE;\n" | |
6154 | "}\n\n", name, name, dispname); | |
6155 | ||
6156 | /* void set_type(template_sel, int) function */ | |
6157 | def = mputstr(def, | |
6158 | "void set_type(template_sel template_type, " | |
6159 | "unsigned int list_length);\n"); | |
6160 | ||
6161 | src = mputprintf(src, | |
6162 | "void %s_template::set_type(template_sel template_type, " | |
6163 | "unsigned int list_length)\n" | |
6164 | "{\n" | |
6165 | "if (template_type != VALUE_LIST " | |
6166 | "&& template_type != COMPLEMENTED_LIST)\n" | |
6167 | "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n" | |
6168 | "clean_up();\n" | |
6169 | "set_selection(template_type);\n" | |
6170 | "value_list.n_values = list_length;\n" | |
6171 | "value_list.list_value = new %s_template[list_length];\n" | |
6172 | "}\n\n", name, dispname, name); | |
6173 | ||
6174 | /* list_item(int) function */ | |
6175 | ||
6176 | def = mputprintf(def, | |
6177 | "%s_template& list_item(unsigned int list_index) const;\n", name); | |
6178 | ||
6179 | src = mputprintf(src, | |
6180 | "%s_template& %s_template::list_item(unsigned int list_index) const\n" | |
6181 | "{\n" | |
6182 | "if (template_selection != VALUE_LIST " | |
6183 | "&& template_selection != COMPLEMENTED_LIST)\n" | |
6184 | "TTCN_error(\"Accessing a list element of a non-list template of " | |
6185 | "type %s.\");\n" | |
6186 | "if (list_index >= value_list.n_values)\n" | |
6187 | "TTCN_error(\"Index overflow in a value list template of type " | |
6188 | "%s.\");\n" | |
6189 | "return value_list.list_value[list_index];\n" | |
6190 | "}\n\n", name, name, dispname, dispname); | |
6191 | ||
6192 | /* log function */ | |
6193 | def = mputstr(def, "void log() const;\n"); | |
6194 | src = mputprintf(src, "void %s_template::log() const\n" | |
6195 | "{\n" | |
6196 | "switch (template_selection) {\n" | |
6197 | "case SPECIFIC_VALUE:\n" | |
6198 | "TTCN_Logger::log_event_str(\"{ }\");\n" | |
6199 | "break;\n" | |
6200 | "case COMPLEMENTED_LIST:\n" | |
6201 | "TTCN_Logger::log_event_str(\"complement \");\n" | |
6202 | "case VALUE_LIST:\n" | |
6203 | "TTCN_Logger::log_char('(');\n" | |
6204 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
6205 | "list_count++) {\n" | |
6206 | "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n" | |
6207 | "value_list.list_value[list_count].log();\n" | |
6208 | "}\n" | |
6209 | "TTCN_Logger::log_char(')');\n" | |
6210 | "break;\n" | |
6211 | "default:\n" | |
6212 | "log_generic();\n" | |
6213 | "}\n" | |
6214 | "log_ifpresent();\n" | |
6215 | "}\n\n", name); | |
6216 | ||
6217 | /* log_match function */ | |
6218 | def = mputprintf(def, "void log_match(const %s& match_value) const;\n", | |
6219 | name); | |
6220 | src = mputprintf(src, "void %s_template::log_match(const %s& match_value) " | |
6221 | "const\n" | |
6222 | "{\n" | |
6223 | "match_value.log();\n" | |
6224 | "TTCN_Logger::log_event_str(\" with \");\n" | |
6225 | "log();\n" | |
6226 | "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n" | |
6227 | "else TTCN_Logger::log_event_str(\" unmatched\");\n" | |
6228 | "}\n\n", name, name); | |
6229 | ||
6230 | /* encode_text function */ | |
6231 | def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); | |
6232 | src = mputprintf(src, "void %s_template::encode_text(Text_Buf& text_buf) " | |
6233 | "const\n" | |
6234 | "{\n" | |
6235 | "encode_text_base(text_buf);\n" | |
6236 | "switch (template_selection) {\n" | |
6237 | "case OMIT_VALUE:\n" | |
6238 | "case ANY_VALUE:\n" | |
6239 | "case ANY_OR_OMIT:\n" | |
6240 | "case SPECIFIC_VALUE:\n" | |
6241 | "break;\n" | |
6242 | "case VALUE_LIST:\n" | |
6243 | "case COMPLEMENTED_LIST:\n" | |
6244 | "text_buf.push_int(value_list.n_values);\n" | |
6245 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
6246 | "list_count++)\n" | |
6247 | "value_list.list_value[list_count].encode_text(text_buf);\n" | |
6248 | "break;\n" | |
6249 | "default:\n" | |
6250 | "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported " | |
6251 | "template of type %s.\");\n" | |
6252 | "}\n" | |
6253 | "}\n\n", name, dispname); | |
6254 | ||
6255 | /* decode_text function */ | |
6256 | def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); | |
6257 | src = mputprintf(src, "void %s_template::decode_text(Text_Buf& text_buf)\n" | |
6258 | "{\n" | |
6259 | "clean_up();\n" | |
6260 | "decode_text_base(text_buf);\n" | |
6261 | "switch (template_selection) {\n" | |
6262 | "case OMIT_VALUE:\n" | |
6263 | "case ANY_VALUE:\n" | |
6264 | "case ANY_OR_OMIT:\n" | |
6265 | "case SPECIFIC_VALUE:\n" | |
6266 | "break;\n" | |
6267 | "case VALUE_LIST:\n" | |
6268 | "case COMPLEMENTED_LIST:\n" | |
6269 | "value_list.n_values = text_buf.pull_int().get_val();\n" | |
6270 | "value_list.list_value = new %s_template[value_list.n_values];\n" | |
6271 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
6272 | "list_count++)\n" | |
6273 | "value_list.list_value[list_count].decode_text(text_buf);\n" | |
6274 | "break;\n" | |
6275 | "default:\n" | |
6276 | "TTCN_error(\"Text decoder: An unknown/unsupported selection was " | |
6277 | "received in a template of type %s.\");\n" | |
6278 | "}\n" | |
6279 | "}\n\n", name, name, dispname); | |
6280 | ||
6281 | /* set_param() */ | |
6282 | def = mputstr(def, "void set_param(const Module_Param& param);\n"); | |
6283 | src = mputprintf(src, | |
6284 | "void %s_template::set_param(const Module_Param& param)\n" | |
6285 | "{\n" | |
6286 | " param.basic_check(Module_Param::BC_TEMPLATE, \"empty record/set template\");\n" | |
6287 | " switch (param.get_type()) {\n" | |
6288 | " case Module_Param::MP_Omit:\n" | |
6289 | " *this = OMIT_VALUE;\n" | |
6290 | " break;\n" | |
6291 | " case Module_Param::MP_Any:\n" | |
6292 | " *this = ANY_VALUE;\n" | |
6293 | " break;\n" | |
6294 | " case Module_Param::MP_AnyOrNone:\n" | |
6295 | " *this = ANY_OR_OMIT;\n" | |
6296 | " break;\n" | |
6297 | " case Module_Param::MP_List_Template:\n" | |
6298 | " case Module_Param::MP_ComplementList_Template:\n" | |
6299 | " set_type(param.get_type()==Module_Param::MP_List_Template ? VALUE_LIST : COMPLEMENTED_LIST, param.get_size());\n" | |
6300 | " for (size_t p_i=0; p_i<param.get_size(); p_i++) {\n" | |
6301 | " list_item(p_i).set_param(*param.get_elem(p_i));\n" | |
6302 | " }\n" | |
6303 | " break;\n" | |
6304 | " case Module_Param::MP_Value_List:\n" | |
6305 | " if (param.get_size()>0) param.type_error(\"empty record/set template\", \"%s\");\n" | |
6306 | " *this = NULL_VALUE;\n" | |
6307 | " break;\n" | |
6308 | " default:\n" | |
6309 | " param.type_error(\"empty record/set template\", \"%s\");\n" | |
6310 | " }\n" | |
6311 | " is_ifpresent = param.get_ifpresent();\n" | |
6312 | "}\n\n", name, dispname, dispname); | |
6313 | ||
6314 | /* check template restriction */ | |
6315 | def = mputstr(def, "void check_restriction(template_res t_res, " | |
6316 | "const char* t_name=NULL) const;\n"); | |
6317 | src = mputprintf(src, | |
6318 | "void %s_template::check_restriction(" | |
6319 | "template_res t_res, const char* t_name) const\n" | |
6320 | "{\n" | |
6321 | "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n" | |
6322 | "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n" | |
6323 | "case TR_OMIT:\n" | |
6324 | "if (template_selection==OMIT_VALUE) return;\n" | |
6325 | "case TR_VALUE:\n" | |
6326 | "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n" | |
6327 | "return;\n" | |
6328 | "case TR_PRESENT:\n" | |
6329 | "if (!match_omit()) return;\n" | |
6330 | "break;\n" | |
6331 | "default:\n" | |
6332 | "return;\n" | |
6333 | "}\n" | |
6334 | "TTCN_error(\"Restriction `%%s' on template of type %%s " | |
6335 | "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n" | |
6336 | "}\n\n", name, dispname); | |
6337 | ||
6338 | defCommonRecordTemplate(name, &def, &src); | |
6339 | ||
6340 | def = mputstr(def, "};\n\n"); | |
6341 | ||
6342 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
6343 | Free(def); | |
6344 | ||
6345 | output->source.methods = mputstr(output->source.methods, src); | |
6346 | Free(src); | |
6347 | } | |
6348 | ||
6349 | static void defCommonRecordTemplate(const char *name, | |
6350 | char **def, char **src) | |
6351 | { | |
6352 | /* TTCN-3 ispresent() function */ | |
6353 | *def = mputstr(*def, "boolean is_present() const;\n"); | |
6354 | *src = mputprintf(*src, | |
6355 | "boolean %s_template::is_present() const\n" | |
6356 | "{\n" | |
6357 | "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n" | |
6358 | "return !match_omit();\n" | |
6359 | "}\n\n", name); | |
6360 | ||
6361 | /* match_omit() */ | |
6362 | *def = mputstr(*def, "boolean match_omit() const;\n"); | |
6363 | *src = mputprintf(*src, | |
6364 | "boolean %s_template::match_omit() const\n" | |
6365 | "{\n" | |
6366 | "if (is_ifpresent) return TRUE;\n" | |
6367 | "switch (template_selection) {\n" | |
6368 | "case OMIT_VALUE:\n" | |
6369 | "case ANY_OR_OMIT:\n" | |
6370 | "return TRUE;\n" | |
6371 | "case VALUE_LIST:\n" | |
6372 | "case COMPLEMENTED_LIST:\n" | |
6373 | "for (unsigned int l_idx=0; l_idx<value_list.n_values; l_idx++)\n" | |
6374 | "if (value_list.list_value[l_idx].match_omit())\n" | |
6375 | "return template_selection==VALUE_LIST;\n" | |
6376 | "return template_selection==COMPLEMENTED_LIST;\n" | |
6377 | "default:\n" | |
6378 | "return FALSE;\n" | |
6379 | "}\n" | |
6380 | "return FALSE;\n" | |
6381 | "}\n\n", name); | |
6382 | } | |
6383 | ||
6384 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ | |
6385 | ||
6386 | void defRecordClass2(const struct_def *sdef, output_struct *output) | |
6387 | { | |
6388 | size_t i; | |
6389 | size_t optional_num = 0; | |
6390 | const char *name = sdef->name; | |
6391 | char *def = NULL, *src = NULL; | |
6392 | ||
6393 | boolean xer_needed = sdef->hasXer && enable_xer(); | |
6394 | boolean raw_needed = sdef->hasRaw && enable_raw(); | |
6395 | boolean has_optional = FALSE; | |
6396 | boolean has_default = FALSE; | |
6397 | ||
6398 | const char* base_class = (sdef->nElements==0) ? "Empty_Record_Type" : "Record_Type"; | |
6399 | ||
6400 | /* class declaration code */ | |
6401 | output->header.class_decls = mputprintf(output->header.class_decls, | |
6402 | "class %s;\n", name); | |
6403 | ||
6404 | /* class definition and source code */ | |
6405 | def=mputprintf(def, "class %s : public %s {\n", name, base_class); | |
6406 | ||
6407 | /* data members */ | |
6408 | for (i = 0; i < sdef->nElements; i++) { | |
6409 | if(sdef->elements[i].isOptional) { | |
6410 | optional_num++; | |
6411 | def = mputprintf(def, " OPTIONAL<%s> field_%s;\n", | |
6412 | sdef->elements[i].type, | |
6413 | sdef->elements[i].name); | |
6414 | } else { | |
6415 | def = mputprintf(def, " %s field_%s;\n", | |
6416 | sdef->elements[i].type, sdef->elements[i].name); | |
6417 | } | |
6418 | } | |
6419 | if (sdef->nElements) { | |
6420 | def = mputprintf(def, " Base_Type* fld_vec[%lu];\n", (unsigned long)sdef->nElements); | |
6421 | } | |
6422 | ||
6423 | /* default constructor */ | |
6424 | if (sdef->nElements==0) { | |
6425 | def = mputprintf(def, "public:\n" | |
6426 | " %s();\n", name); | |
6427 | src = mputprintf(src, | |
6428 | "%s::%s() : Empty_Record_Type() {}\n\n", | |
6429 | name, name); | |
6430 | } else { | |
6431 | def = mputstr(def, " void init_vec();\n"); | |
6432 | src = mputprintf(src, "void %s::init_vec() { ", name); | |
6433 | for (i = 0; i < sdef->nElements; i++) { | |
6434 | src = mputprintf(src, "fld_vec[%lu]=&field_%s; ", | |
6435 | (unsigned long)i, sdef->elements[i].name); | |
6436 | } | |
6437 | src = mputstr(src, " }\n\n"); | |
6438 | ||
6439 | def = mputprintf(def, "public:\n" | |
6440 | " %s();\n", name); | |
6441 | src = mputprintf(src, | |
6442 | "%s::%s() : Record_Type() { init_vec(); }\n\n", name, name); | |
6443 | } | |
6444 | ||
6445 | /* copy constructor */ | |
6446 | if (sdef->nElements) { | |
6447 | def = mputprintf(def, " %s(const %s& other_value);\n", name, name); | |
6448 | src = mputprintf(src, "%s::%s(const %s& other_value) : Record_Type(other_value)\n", name, name, name); | |
6449 | src = mputstr(src, "{\n" | |
6450 | " if(!other_value.is_bound()) " | |
6451 | "TTCN_error(\"Copying an unbound record/set value.\");\n" | |
6452 | "bound_flag = TRUE;\n"); | |
6453 | for (i = 0; i < sdef->nElements; i++) { | |
6454 | src = mputprintf(src, | |
6455 | "if (other_value.field_%s.is_bound() )\n" | |
6456 | " field_%s = other_value.field_%s;\n", | |
6457 | sdef->elements[i].name, sdef->elements[i].name, | |
6458 | sdef->elements[i].name); | |
6459 | } | |
6460 | ||
6461 | src = mputstr(src, "init_vec();\n" | |
6462 | "}\n\n"); | |
6463 | } else { | |
6464 | def = mputprintf(def, " %s(const %s& other_value): %s(other_value) {}\n", name, name, base_class); | |
6465 | } | |
6466 | ||
6467 | if (sdef->nElements>0) { /* constructor by fields */ | |
6468 | def = mputprintf(def, " %s(", name); | |
6469 | src = mputprintf(src, "%s::%s(", name, name); | |
6470 | for (i = 0; i < sdef->nElements; i++) { | |
6471 | char *tmp = NULL; | |
6472 | if (i > 0) tmp = mputstr(tmp, ",\n "); | |
6473 | if (sdef->elements[i].isOptional) | |
6474 | tmp = mputprintf | |
6475 | (tmp, | |
6476 | "const OPTIONAL<%s>& par_%s", | |
6477 | sdef->elements[i].type, sdef->elements[i].name); | |
6478 | else | |
6479 | tmp = mputprintf | |
6480 | (tmp, | |
6481 | "const %s& par_%s", | |
6482 | sdef->elements[i].type, sdef->elements[i].name); | |
6483 | def = mputstr(def, tmp); | |
6484 | src = mputstr(src, tmp); | |
6485 | Free(tmp); | |
6486 | } | |
6487 | def = mputstr(def, ");\n"); | |
6488 | src = mputprintf(src, ") : "); | |
6489 | for (i = 0; i < sdef->nElements; i++) { | |
6490 | if (i > 0) src = mputstr(src, ",\n "); | |
6491 | src = mputprintf(src, "field_%s(par_%s)", sdef->elements[i].name, | |
6492 | sdef->elements[i].name); | |
6493 | } | |
6494 | src = mputstr(src, "\n" | |
6495 | "{\n" | |
6496 | "init_vec();\n" | |
6497 | "bound_flag = TRUE;\n" | |
6498 | "}\n\n"); | |
6499 | } else { /* constructor from null */ | |
6500 | def = mputprintf(def, " %s(null_type) {bound_flag = TRUE;}\n", name); | |
6501 | } | |
6502 | ||
6503 | /* assignment operators */ | |
6504 | def = mputprintf(def, "inline %s& operator=(const %s& other_value) " | |
6505 | "{ set_value(&other_value); return *this; }\n\n", name, name); | |
6506 | if (sdef->nElements == 0) { | |
6507 | def = mputprintf(def, "inline %s& operator=(null_type) " | |
6508 | "{ bound_flag = TRUE; return *this; }\n", name); | |
6509 | } | |
6510 | ||
6511 | /* == operator */ | |
6512 | def = mputprintf(def, "inline boolean operator==(const %s& other_value) " | |
6513 | "const { return is_equal(&other_value); }\n", name); | |
6514 | /* != operator */ | |
6515 | def = mputprintf(def, | |
6516 | " inline boolean operator!=(const %s& other_value) const\n" | |
6517 | " { return !is_equal(&other_value); }\n\n", name); | |
6518 | ||
6519 | for (i = 0; i < sdef->nElements; i++) { | |
6520 | if(sdef->elements[i].isOptional) | |
6521 | def = mputprintf | |
6522 | (def, | |
6523 | " inline OPTIONAL<%s>& %s()\n" | |
6524 | " {return field_%s;}\n" | |
6525 | " inline const OPTIONAL<%s>& %s() const\n" | |
6526 | " {return field_%s;}\n", | |
6527 | sdef->elements[i].type, sdef->elements[i].name, | |
6528 | sdef->elements[i].name, | |
6529 | sdef->elements[i].type, sdef->elements[i].name, | |
6530 | sdef->elements[i].name); | |
6531 | else def = mputprintf | |
6532 | (def, | |
6533 | " inline %s& %s()\n" | |
6534 | " {return field_%s;}\n" | |
6535 | " inline const %s& %s() const\n" | |
6536 | " {return field_%s;}\n", | |
6537 | sdef->elements[i].type, sdef->elements[i].name, | |
6538 | sdef->elements[i].name, sdef->elements[i].type, | |
6539 | sdef->elements[i].name, sdef->elements[i].name); | |
6540 | ||
6541 | } | |
6542 | ||
6543 | /* override virtual functions where needed */ | |
6544 | def = mputprintf(def, | |
6545 | "Base_Type* clone() const { return new %s(*this); }\n" | |
6546 | "const TTCN_Typedescriptor_t* get_descriptor() const;\n" | |
6547 | "boolean is_set() const { return %s; }\n", | |
6548 | name, | |
6549 | (sdef->kind==SET) ? "TRUE" : "FALSE"); | |
6550 | src = mputprintf(src, | |
6551 | "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n", | |
6552 | name, name); | |
6553 | ||
6554 | if (sdef->nElements > 0) { | |
6555 | ||
6556 | /* field access functions */ | |
6557 | def = mputprintf(def, | |
6558 | "Base_Type* get_at(int index_value) { return fld_vec[index_value]; }\n" | |
6559 | "const Base_Type* get_at(int index_value) const { return fld_vec[index_value]; }\n\n" | |
6560 | "int get_count() const { return %lu; }\n", (unsigned long)sdef->nElements); | |
6561 | ||
6562 | /* override if there are optional fields */ | |
6563 | if (optional_num) { | |
6564 | def = mputprintf(def, | |
6565 | "int optional_count() const { return %lu; }\n", (unsigned long)optional_num); | |
6566 | } | |
6567 | ||
6568 | if (sdef->opentype_outermost) | |
6569 | def = mputstr(def, "boolean is_opentype_outermost() const { return TRUE; }\n"); | |
6570 | ||
6571 | /* FIXME: use static member in Record_Type and initialize somewhere */ | |
6572 | if (default_as_optional) | |
6573 | def = mputstr(def, "boolean default_as_optional() const { return TRUE; }\n"); | |
6574 | ||
6575 | for (i = 0; i < sdef->nElements; i++) { | |
6576 | if (sdef->elements[i].isOptional) { | |
6577 | has_optional = TRUE; | |
6578 | break; | |
6579 | } | |
6580 | } | |
6581 | ||
6582 | for (i = 0; i < sdef->nElements; i++) { | |
6583 | if (sdef->elements[i].isDefault) { | |
6584 | has_default = TRUE; | |
6585 | break; | |
6586 | } | |
6587 | } | |
6588 | def = mputstr(def, | |
6589 | "static const TTCN_Typedescriptor_t* fld_descriptors[];\n" | |
6590 | "const TTCN_Typedescriptor_t* fld_descr(int p_index) const;\n\n" | |
6591 | "static const char* fld_names[];\n" | |
6592 | "const char* fld_name(int p_index) const;\n\n"); | |
6593 | ||
6594 | src = mputprintf(src, "const TTCN_Typedescriptor_t* %s::fld_descriptors[] = ", name); | |
6595 | for (i = 0; i < sdef->nElements; i++) { | |
6596 | src = mputprintf(src, "%c &%s_descr_", | |
6597 | (i ? ',' : '{'), sdef->elements[i].typedescrname); | |
6598 | } | |
6599 | src = mputstr(src, " };\n"); | |
6600 | src = mputprintf(src, | |
6601 | "const TTCN_Typedescriptor_t* %s::fld_descr(int p_index) const " | |
6602 | "{ return fld_descriptors[p_index]; }\n\n", name); | |
6603 | ||
6604 | src = mputprintf(src, "const char* %s::fld_names[] = ", name); | |
6605 | for (i = 0; i < sdef->nElements; i++) { | |
6606 | src = mputprintf(src, "%c \"%s\"", | |
6607 | (i ? ',' : '{'), sdef->elements[i].dispname); | |
6608 | } | |
6609 | src = mputstr(src, " };\n"); | |
6610 | ||
6611 | src = mputprintf(src, | |
6612 | "const char* %s::fld_name(int p_index) const " | |
6613 | "{ return fld_names[p_index]; }\n\n", name); | |
6614 | ||
6615 | if (has_optional) { | |
6616 | def = mputstr(def, | |
6617 | "static const int optional_indexes[];\n" | |
6618 | "const int* get_optional_indexes() const;\n\n"); | |
6619 | src = mputprintf(src, "const int %s::optional_indexes[] = { ", name); | |
6620 | for (i = 0; i < sdef->nElements; i++) { | |
6621 | if (sdef->elements[i].isOptional) { | |
6622 | src = mputprintf(src, "%lu, ", (unsigned long)i); | |
6623 | } | |
6624 | } | |
6625 | src = mputstr(src, "-1 };\n"); | |
6626 | src = mputprintf(src, | |
6627 | "const int* %s::get_optional_indexes() const " | |
6628 | "{ return optional_indexes; }\n\n", name); | |
6629 | } | |
6630 | ||
6631 | if (has_default) { | |
6632 | def = mputstr(def, | |
6633 | "static const default_struct default_indexes[];\n" | |
6634 | "const default_struct* get_default_indexes() const;\n"); | |
6635 | src = mputprintf(src, "const Record_Type::default_struct %s::default_indexes[] = { ", name); | |
6636 | for (i = 0; i < sdef->nElements; i++) { | |
6637 | if (sdef->elements[i].isDefault) { | |
6638 | src = mputprintf(src, "{%lu,&%s}, ", | |
6639 | (unsigned long)i, sdef->elements[i].defvalname); | |
6640 | } | |
6641 | } | |
6642 | src = mputstr(src, "{-1,NULL} };\n"); | |
6643 | src = mputprintf(src, | |
6644 | "const Record_Type::default_struct* %s::get_default_indexes() const " | |
6645 | "{ return default_indexes; }\n", name); | |
6646 | } | |
6647 | ||
6648 | if (raw_needed) { | |
6649 | struct raw_option_struct *raw_options; | |
6650 | boolean haslengthto, haspointer, hascrosstag, has_ext_bit; | |
6651 | boolean generate_raw_function = FALSE; | |
6652 | ||
6653 | raw_options = (struct raw_option_struct*) | |
6654 | Malloc(sdef->nElements * sizeof(*raw_options)); | |
6655 | ||
6656 | set_raw_options(sdef, raw_options, &haslengthto, | |
6657 | &haspointer, &hascrosstag, &has_ext_bit); | |
6658 | ||
6659 | /* set the value of generate_raw_function: if the coding/decoding is too | |
6660 | complex for this type then generate the functions, otherwise generate | |
6661 | helper functions only which are called by the default RAW enc/dec | |
6662 | functions */ | |
6663 | if (haslengthto || haspointer || hascrosstag) { | |
6664 | generate_raw_function = TRUE; | |
6665 | goto check_generate_end; | |
6666 | } | |
6667 | for (i = 0; i < sdef->nElements; i++) { | |
6668 | if (raw_options[i].lengthto || raw_options[i].lengthof || | |
6669 | raw_options[i].lengthoffield || raw_options[i].pointerto || | |
6670 | raw_options[i].pointerof || raw_options[i].ptrbase || | |
6671 | raw_options[i].extbitgroup || raw_options[i].tag_type || | |
6672 | raw_options[i].delayed_decode || raw_options[i].nof_dependent_fields | |
6673 | || raw_options[i].dependent_fields) { | |
6674 | generate_raw_function = TRUE; | |
6675 | goto check_generate_end; | |
6676 | } | |
6677 | } | |
6678 | for (i = 0; i < sdef->nElements; i++) { | |
6679 | if (raw_options[i].lengthof || raw_options[i].lengthoffield || | |
6680 | raw_options[i].nof_dependent_fields || | |
6681 | raw_options[i].dependent_fields) { | |
6682 | generate_raw_function = TRUE; | |
6683 | goto check_generate_end; | |
6684 | } | |
6685 | } | |
6686 | if (sdef->raw.ext_bit_goup_num || sdef->raw.ext_bit_groups || | |
6687 | sdef->raw.lengthto || sdef->raw.lengthindex || | |
6688 | sdef->raw.taglist.nElements || sdef->raw.crosstaglist.nElements || | |
6689 | sdef->raw.presence.fieldnum || sdef->raw.presence.fields || | |
6690 | sdef->raw.member_name) { | |
6691 | generate_raw_function = TRUE; | |
6692 | goto check_generate_end; | |
6693 | } | |
6694 | for (i = 0; i < sdef->nElements; i++) { | |
6695 | if (sdef->elements[i].hasRaw) { | |
6696 | generate_raw_function = TRUE; | |
6697 | goto check_generate_end; | |
6698 | } | |
6699 | } | |
6700 | check_generate_end: | |
6701 | ||
6702 | if (generate_raw_function) { | |
6703 | def = mputprintf(def, | |
6704 | "int RAW_encode(const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n" | |
6705 | "virtual int RAW_encode_negtest(const Erroneous_descriptor_t *, const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n" | |
6706 | "int RAW_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, " | |
6707 | "int, raw_order_t, boolean no_err = FALSE, " | |
6708 | "int sel_field = -1, boolean first_call = TRUE);\n"); | |
6709 | src = generate_raw_coding(src, sdef, raw_options, haspointer, | |
6710 | hascrosstag, has_ext_bit); | |
6711 | } else { /* generate helper functions for the default RAW enc/dec */ | |
6712 | if (has_ext_bit) | |
6713 | def = mputstr(def,"boolean raw_has_ext_bit() const { return TRUE; }\n"); | |
6714 | } | |
6715 | for (i = 0; i < sdef->nElements; i++) { | |
6716 | Free(raw_options[i].lengthoffield); | |
6717 | Free(raw_options[i].dependent_fields); | |
6718 | } | |
6719 | Free(raw_options); | |
6720 | } /* if (raw_needed) */ | |
6721 | ||
6722 | if (xer_needed) { /* XERSTUFF codegen for record/SEQUENCE in RT2 */ | |
6723 | size_t num_attributes = 0; | |
6724 | ||
6725 | /* XER descriptors needed because of the xer antipattern */ | |
6726 | def = mputstr(def, | |
6727 | "static const XERdescriptor_t* xer_descriptors[];\n" | |
6728 | "const XERdescriptor_t* xer_descr(int p_index) const;\n" | |
6729 | "virtual boolean can_start_v(const char *name, const char *prefix, " | |
6730 | "XERdescriptor_t const& xd, unsigned int flavor);\n" | |
6731 | "static boolean can_start (const char *name, const char *prefix, " | |
6732 | "XERdescriptor_t const& xd, unsigned int flavor);\n"); | |
6733 | src = mputprintf(src, "const XERdescriptor_t* %s::xer_descriptors[] = ", name); | |
6734 | for (i = 0; i < sdef->nElements; i++) { | |
6735 | src = mputprintf(src, "%c &%s_xer_", | |
6736 | (i ? ',' : '{'), sdef->elements[i].typegen); | |
6737 | } | |
6738 | src = mputstr(src, " };\n"); | |
6739 | src = mputprintf(src, | |
6740 | "const XERdescriptor_t* %s::xer_descr(int p_index) const " | |
6741 | "{ return xer_descriptors[p_index]; }\n" | |
6742 | /* The virtual can_start_v hands off to the static can_start. | |
6743 | * We must make a virtual call in Record_Type::XER_decode because | |
6744 | * we don't know the actual type (derived from Record_Type) */ | |
6745 | "boolean %s::can_start_v(const char *p_name, const char *p_uri, " | |
6746 | "XERdescriptor_t const& p_td, unsigned int p_flavor)\n" | |
6747 | "{ return can_start(p_name, p_uri, p_td, p_flavor); }\n" | |
6748 | "boolean %s::can_start(const char *p_name, const char *p_uri, " | |
6749 | "XERdescriptor_t const& p_td, unsigned int p_flavor) {\n" | |
6750 | " boolean e_xer = is_exer(p_flavor);\n" | |
6751 | " 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" | |
6752 | , name , name, name); | |
6753 | for (i = 0; i < sdef->nElements; i++) { | |
6754 | src = mputprintf(src, | |
6755 | " else if (%s::can_start(p_name, p_uri, %s_xer_, p_flavor)) return true;\n" | |
6756 | , sdef->elements[i].type, sdef->elements[i].typegen); | |
6757 | } | |
6758 | src = mputstr(src, | |
6759 | " return false;\n" | |
6760 | "}\n\n"); | |
6761 | /* end of antipattern */ | |
6762 | ||
6763 | /* calculate num_attributes in compile time */ | |
6764 | for ( i=0; i < sdef->nElements; ++i ) { | |
6765 | if (sdef->elements[i].xerAttribute | |
6766 | ||(sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) ++num_attributes; | |
6767 | else if (num_attributes) break; | |
6768 | } | |
6769 | ||
6770 | /* generate helper virtual functions for XER encdec */ | |
6771 | if (num_attributes) { | |
6772 | def = mputprintf(def, | |
6773 | "int get_xer_num_attr() const { return %lu; }\n", | |
6774 | (unsigned long)num_attributes); | |
6775 | } | |
6776 | } | |
6777 | else { /* XER not needed */ | |
6778 | def = mputstr(def, | |
6779 | "boolean can_start_v(const char *, const char *, XERdescriptor_t const&, unsigned int)\n" | |
6780 | "{ return FALSE; }\n" | |
6781 | ); | |
6782 | } /* if (xer_needed) */ | |
6783 | } /* if (sdef->nElements > 0) */ | |
6784 | ||
6785 | /* end of class definition */ | |
6786 | def = mputstr(def, "};\n\n"); | |
6787 | ||
6788 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
6789 | Free(def); | |
6790 | ||
6791 | output->source.methods = mputstr(output->source.methods, src); | |
6792 | Free(src); | |
6793 | } | |
6794 | ||
6795 | void defRecordTemplate2(const struct_def *sdef, output_struct *output) | |
6796 | { | |
6797 | int i; | |
6798 | const char *name = sdef->name; | |
6799 | char *def = NULL, *src = NULL; | |
6800 | ||
6801 | const char* base_class = (sdef->nElements==0) ? "Empty_Record_Template" : "Record_Template"; | |
6802 | ||
6803 | /* class declaration */ | |
6804 | output->header.class_decls = mputprintf(output->header.class_decls, | |
6805 | "class %s_template;\n", name); | |
6806 | ||
6807 | /* template class definition */ | |
6808 | def = mputprintf(def, "class %s_template : public %s {\n", name, base_class); | |
6809 | ||
6810 | if (sdef->nElements>0) { | |
6811 | /* set_specific function (used in field access members) */ | |
6812 | def = mputstr(def, "void set_specific();\n"); | |
6813 | src = mputprintf(src, "void %s_template::set_specific()\n" | |
6814 | "{\n" | |
6815 | "if (template_selection != SPECIFIC_VALUE) {\n" | |
6816 | "%s" | |
6817 | "clean_up();\n" | |
6818 | "single_value.n_elements = %lu;\n" | |
6819 | "single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);\n" | |
6820 | "set_selection(SPECIFIC_VALUE);\n", | |
6821 | name, sdef->nElements ? "boolean was_any = (template_selection == ANY_VALUE || template_selection == ANY_OR_OMIT);\n" : "", | |
6822 | (unsigned long)sdef->nElements); | |
6823 | for (i = 0; i < sdef->nElements; i++) { | |
6824 | src = mputprintf(src, | |
6825 | "single_value.value_elements[%d] = was_any ? new %s_template(%s) : new %s_template;\n", | |
6826 | i, sdef->elements[i].type, | |
6827 | sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE", | |
6828 | sdef->elements[i].type); | |
6829 | } | |
6830 | src = mputstr(src, | |
6831 | "}\n" | |
6832 | "}\n\n"); | |
6833 | } | |
6834 | ||
6835 | /* default constructor */ | |
6836 | def = mputprintf(def, "public:\n" | |
6837 | "%s_template(): %s() {}\n", name, base_class); | |
6838 | ||
6839 | if (sdef->nElements==0) { | |
6840 | /* ctor for value {} */ | |
6841 | def = mputprintf(def, "%s_template(null_type) : " | |
6842 | "Empty_Record_Template() { set_selection(SPECIFIC_VALUE); }\n", | |
6843 | name); | |
6844 | } | |
6845 | ||
6846 | /* constructor t1_template(template_sel other_value) */ | |
6847 | def = mputprintf(def, "%s_template(template_sel other_value): " | |
6848 | "%s(other_value) {}\n", name, base_class); | |
6849 | ||
6850 | /* constructor t1_template(const t1& other_value) */ | |
6851 | def = mputprintf(def, "%s_template(const %s& other_value): " | |
6852 | "%s() { copy_value(&other_value); }\n", | |
6853 | name, name, base_class); | |
6854 | ||
6855 | /* constructor t1_template(const OPTIONAL<t1>& other_value) */ | |
6856 | def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value): " | |
6857 | "%s() { copy_optional(&other_value); }\n", | |
6858 | name, name, base_class); | |
6859 | ||
6860 | /* copy constructor */ | |
6861 | def = mputprintf(def, "%s_template(const %s_template& other_value): %s() " | |
6862 | "{ copy_template(other_value); }\n", name, name, base_class); | |
6863 | ||
6864 | /* assignment operator <- template_sel */ | |
6865 | def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n", | |
6866 | name); | |
6867 | src = mputprintf(src, | |
6868 | "%s_template& %s_template::operator=(template_sel other_value)\n" | |
6869 | "{\n" | |
6870 | "check_single_selection(other_value);\n" | |
6871 | "clean_up();\n" | |
6872 | "set_selection(other_value);\n" | |
6873 | "return *this;\n" | |
6874 | "}\n\n", name, name); | |
6875 | ||
6876 | /* assignment operator <- value */ | |
6877 | def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n", | |
6878 | name, name); | |
6879 | src = mputprintf(src, | |
6880 | "%s_template& %s_template::operator=(const %s& other_value)\n" | |
6881 | "{\n" | |
6882 | "clean_up();\n" | |
6883 | "copy_value(&other_value);\n" | |
6884 | "return *this;\n" | |
6885 | "}\n\n", name, name, name); | |
6886 | ||
6887 | /* assignment operator <- optional value */ | |
6888 | def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& " | |
6889 | "other_value);\n", name, name); | |
6890 | src = mputprintf(src, | |
6891 | "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n" | |
6892 | "{\n" | |
6893 | "clean_up();\n" | |
6894 | "copy_optional(&other_value);\n" | |
6895 | "return *this;\n" | |
6896 | "}\n\n", name, name, name); | |
6897 | ||
6898 | /* assignment operator <- template*/ | |
6899 | def = mputprintf(def, | |
6900 | "%s_template& operator=(const %s_template& other_value);\n", | |
6901 | name, name); | |
6902 | src = mputprintf(src, | |
6903 | "%s_template& %s_template::operator=(const %s_template& other_value)\n" | |
6904 | "{\n" | |
6905 | "if (&other_value != this) {\n" | |
6906 | "clean_up();\n" | |
6907 | "copy_template(other_value);\n" | |
6908 | "}\n" | |
6909 | "return *this;\n" | |
6910 | "}\n\n", name, name, name); | |
6911 | ||
6912 | if (sdef->nElements==0) { | |
6913 | /* assignment op for value {} */ | |
6914 | def = mputprintf(def, "%s_template& operator=(null_type other_value);\n", | |
6915 | name); | |
6916 | src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n" | |
6917 | "{\n" | |
6918 | "clean_up();\n" | |
6919 | "set_selection(SPECIFIC_VALUE);\n" | |
6920 | "return *this;\n" | |
6921 | "}\n\n", name, name); | |
6922 | } | |
6923 | ||
6924 | /* match operation (template matching) */ | |
6925 | def = mputprintf(def, "inline boolean match(const %s& other_value) const " | |
6926 | "{ return matchv(&other_value); }\n", name); | |
6927 | ||
6928 | /* log_match */ | |
6929 | def = mputprintf(def, "inline void log_match(const %s& match_value) const " | |
6930 | "{ log_matchv(&match_value); }\n", name); | |
6931 | ||
6932 | /* valueof operation */ | |
6933 | def = mputprintf(def, "%s valueof() const;\n", name); | |
6934 | ||
6935 | src = mputprintf(src, "%s %s_template::valueof() const\n" | |
6936 | "{\n" | |
6937 | "%s ret_val;\n" | |
6938 | "valueofv(&ret_val);\n" | |
6939 | "return ret_val;\n" | |
6940 | "}\n\n", name, name, name); | |
6941 | ||
6942 | /* list_item(int) function */ | |
6943 | ||
6944 | def = mputprintf(def, | |
6945 | "inline %s_template& list_item(unsigned int list_index) const " | |
6946 | "{ return *(static_cast<%s_template*>(get_list_item(list_index))); }\n", name, name); | |
6947 | ||
6948 | if (sdef->nElements>0) { | |
6949 | /* template field access functions (non-const & const) */ | |
6950 | for (i = 0; i < sdef->nElements; i++) { | |
6951 | def = mputprintf(def, | |
6952 | "%s_template& %s();\n" | |
6953 | "const %s_template& %s() const;\n", | |
6954 | sdef->elements[i].type, sdef->elements[i].name, | |
6955 | sdef->elements[i].type, sdef->elements[i].name); | |
6956 | src = mputprintf(src, | |
6957 | "%s_template& %s_template::%s() { return *(static_cast<%s_template*>(get_at(%d))); }\n" | |
6958 | "const %s_template& %s_template::%s() const { return *(static_cast<const %s_template*>(get_at(%d))); }\n", | |
6959 | sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i, | |
6960 | sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i); | |
6961 | } | |
6962 | } | |
6963 | ||
6964 | /* virtual functions */ | |
6965 | def = mputprintf(def, | |
6966 | "%s* create() const { return new %s_template; }\n" | |
6967 | "const TTCN_Typedescriptor_t* get_descriptor() const;\n", | |
6968 | base_class, name); | |
6969 | src = mputprintf(src, | |
6970 | "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const { return &%s_descr_; }\n", | |
6971 | name, name); | |
6972 | ||
6973 | if (sdef->nElements>0) { | |
6974 | def = mputprintf(def, "const char* fld_name(int p_index) const;\n"); | |
6975 | src = mputprintf(src, | |
6976 | "const char* %s_template::fld_name(int p_index) const { return %s::fld_names[p_index]; }\n", | |
6977 | name, name); | |
6978 | } | |
6979 | ||
6980 | def = mputstr(def, "};\n\n"); | |
6981 | ||
6982 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
6983 | Free(def); | |
6984 | ||
6985 | output->source.methods = mputstr(output->source.methods, src); | |
6986 | Free(src); | |
6987 | } | |
6988 |