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