Commit | Line | Data |
---|---|---|
d44e3c4f | 1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * Baji, Laszlo | |
10 | * Balasko, Jeno | |
11 | * Baranyi, Botond | |
12 | * Beres, Szabolcs | |
13 | * Cserveni, Akos | |
14 | * Delic, Adam | |
15 | * Feher, Csaba | |
16 | * Forstner, Matyas | |
17 | * Kovacs, Ferenc | |
18 | * Kremer, Peter | |
19 | * Ormandi, Matyas | |
20 | * Raduly, Csaba | |
21 | * Szabados, Kristof | |
22 | * Szabo, Bence Janos | |
23 | * Szabo, Janos Zoltan – initial implementation | |
24 | * Szalai, Gabor | |
25 | * | |
26 | ******************************************************************************/ | |
970ed795 EL |
27 | #include <string.h> |
28 | #include "datatypes.h" | |
29 | #include "../common/memory.h" | |
30 | #include "record.h" | |
31 | #include "encdec.h" | |
32 | ||
33 | #include "main.hh" | |
34 | #include "error.h" | |
35 | #include "ttcn3/compiler.h" | |
36 | ||
37 | static void defEmptyRecordClass(const struct_def *sdef, | |
38 | output_struct *output); | |
39 | ||
40 | static void defEmptyRecordTemplate(const char *name, const char *dispname, | |
41 | output_struct *output); | |
42 | ||
43 | /** this is common code for both empty and non-empty cases, called from | |
44 | * both functions for template generation */ | |
45 | static void defCommonRecordTemplate(const char *name, | |
46 | char **def, char **src); | |
47 | ||
48 | /** code generation for original runtime */ | |
49 | static void defRecordClass1(const struct_def *sdef, output_struct *output); | |
50 | static void defRecordTemplate1(const struct_def *sdef, output_struct *output); | |
51 | /** code generation for alternative runtime (TITAN_RUNTIME_2) */ | |
52 | static void defRecordClass2(const struct_def *sdef, output_struct *output); | |
53 | static void defRecordTemplate2(const struct_def *sdef, output_struct *output); | |
54 | ||
55 | void defRecordClass(const struct_def *sdef, output_struct *output) | |
56 | { | |
57 | if (use_runtime_2) defRecordClass2(sdef, output); | |
58 | else defRecordClass1(sdef, output); | |
59 | } | |
60 | ||
61 | void defRecordTemplate(const struct_def *sdef, output_struct *output) | |
62 | { | |
63 | if (use_runtime_2) defRecordTemplate2(sdef, output); | |
64 | else defRecordTemplate1(sdef, output); | |
65 | } | |
66 | ||
67 | struct raw_option_struct { | |
68 | boolean lengthto; /* indicates whether this field contains a length */ | |
69 | int lengthof; /* how many length indicators this field counted in */ | |
70 | int *lengthoffield; /* the list of length indicator field indices */ | |
71 | boolean pointerto; | |
72 | int pointerof; | |
73 | boolean ptrbase; | |
74 | int extbitgroup; | |
75 | int tag_type; | |
76 | boolean delayed_decode; /* indicates whether the field has to be decoded | |
77 | out of order (later) */ | |
78 | int nof_dependent_fields; /* list of fields that are to be decoded */ | |
79 | int *dependent_fields; /* after this field */ | |
80 | }; | |
81 | ||
82 | static char *genRawFieldDecodeLimit(char *src, const struct_def *sdef, | |
83 | int i, const struct raw_option_struct *raw_options); | |
84 | ||
85 | static char *genRawDecodeRecordField(char *src, const struct_def *sdef, | |
86 | int i, const struct raw_option_struct *raw_options, boolean delayed_decode, | |
87 | int *prev_ext_group); | |
88 | ||
89 | static void set_raw_options(const struct_def *sdef, | |
90 | struct raw_option_struct *raw_options, boolean* haslengthto, | |
91 | boolean* haspointer, boolean* hascrosstag, boolean* has_ext_bit); | |
92 | ||
93 | static char *generate_raw_coding(char *src, | |
94 | const struct_def *sdef, struct raw_option_struct *raw_options, | |
95 | boolean haspointer, boolean hascrosstag, boolean has_ext_bit); | |
96 | static char *generate_raw_coding_negtest(char *src, | |
97 | const struct_def *sdef, struct raw_option_struct *raw_options); | |
98 | ||
99 | void set_raw_options(const struct_def *sdef, | |
100 | struct raw_option_struct *raw_options, boolean *haslengthto, | |
101 | boolean *haspointer, boolean *hascrosstag, boolean *has_ext_bit) | |
102 | { | |
103 | int i; | |
104 | for (i = 0; i < sdef->nElements; i++) { | |
105 | raw_options[i].lengthto = FALSE; | |
106 | raw_options[i].lengthof = 0; | |
107 | raw_options[i].lengthoffield = NULL; | |
108 | raw_options[i].pointerto = FALSE; | |
109 | raw_options[i].pointerof = 0; | |
110 | raw_options[i].ptrbase = FALSE; | |
111 | raw_options[i].extbitgroup = 0; | |
112 | raw_options[i].tag_type = 0; | |
113 | raw_options[i].delayed_decode = FALSE; | |
114 | raw_options[i].nof_dependent_fields = 0; | |
115 | raw_options[i].dependent_fields = NULL; | |
116 | } | |
117 | *haslengthto = FALSE; | |
118 | *haspointer = FALSE; | |
119 | *hascrosstag = FALSE; | |
120 | *has_ext_bit = sdef->hasRaw && sdef->raw.extension_bit!=XDEFNO && | |
121 | sdef->raw.extension_bit!=XDEFDEFAULT; | |
122 | for(i=0;i<sdef->nElements;i++){ | |
123 | if(sdef->elements[i].hasRaw && | |
124 | sdef->elements[i].raw.crosstaglist.nElements){ | |
125 | *hascrosstag = TRUE; | |
126 | break; | |
127 | } | |
128 | } | |
129 | if(sdef->hasRaw){ /* fill tag_type. 0-No tag, >0 index of the tag + 1 */ | |
130 | for(i=0;i<sdef->raw.taglist.nElements;i++){ | |
131 | raw_options[sdef->raw.taglist.list[i].fieldnum].tag_type= i+1; | |
132 | } | |
133 | for(i=0;i<sdef->raw.ext_bit_goup_num;i++){ | |
134 | int k; | |
135 | for(k=sdef->raw.ext_bit_groups[i].from; | |
136 | k<=sdef->raw.ext_bit_groups[i].to;k++) | |
137 | raw_options[k].extbitgroup=i+1; | |
138 | } | |
139 | } | |
140 | for(i=0;i<sdef->nElements;i++){ | |
141 | if (sdef->elements[i].hasRaw && sdef->elements[i].raw.lengthto_num > 0) { | |
142 | int j; | |
143 | *haslengthto = TRUE; | |
144 | raw_options[i].lengthto = TRUE; | |
145 | for(j = 0; j < sdef->elements[i].raw.lengthto_num; j++) { | |
146 | int field_index = sdef->elements[i].raw.lengthto[j]; | |
147 | raw_options[field_index].lengthoffield = (int*) | |
148 | Realloc(raw_options[field_index].lengthoffield, | |
149 | (raw_options[field_index].lengthof + 1) * sizeof(int)); | |
150 | raw_options[field_index].lengthoffield[ | |
151 | raw_options[field_index].lengthof] = i; | |
152 | raw_options[field_index].lengthof++; | |
153 | } | |
154 | } | |
155 | if(sdef->elements[i].hasRaw && sdef->elements[i].raw.pointerto!=-1){ | |
156 | raw_options[i].pointerto = TRUE; | |
157 | raw_options[sdef->elements[i].raw.pointerto].pointerof=i+1; | |
158 | *haspointer = TRUE; | |
159 | raw_options[sdef->elements[i].raw.pointerbase].ptrbase = TRUE; | |
160 | } | |
161 | } | |
162 | if (sdef->kind == RECORD && *hascrosstag) { | |
163 | /* looking for fields that require delayed decoding because of | |
164 | forward references in CROSSTAG */ | |
165 | for (i = 0; i < sdef->nElements; i++) { | |
166 | int j; | |
167 | /* we are looking for a field index that is greater than i */ | |
168 | size_t max_index = i; | |
169 | if (!sdef->elements[i].hasRaw) continue; | |
170 | for (j = 0; j < sdef->elements[i].raw.crosstaglist.nElements; j++) { | |
171 | int k; | |
172 | rawAST_coding_taglist *crosstag = | |
173 | sdef->elements[i].raw.crosstaglist.list + j; | |
174 | for (k = 0; k < crosstag->nElements; k++) { | |
175 | rawAST_coding_field_list *keyid = crosstag->fields + k; | |
176 | if (keyid->nElements >= 1) { | |
177 | int field_index = keyid->fields[0].nthfield; | |
178 | if (field_index > max_index) max_index = field_index; | |
179 | } | |
180 | } | |
181 | } | |
182 | if (max_index > i) { | |
183 | raw_options[i].delayed_decode = TRUE; | |
184 | raw_options[max_index].nof_dependent_fields++; | |
185 | raw_options[max_index].dependent_fields = (int*) | |
186 | Realloc(raw_options[max_index].dependent_fields, | |
187 | raw_options[max_index].nof_dependent_fields * | |
188 | sizeof(*raw_options[max_index].dependent_fields)); | |
189 | raw_options[max_index].dependent_fields[ | |
190 | raw_options[max_index].nof_dependent_fields - 1] = i; | |
191 | } | |
192 | } | |
193 | } | |
194 | } | |
195 | ||
196 | char* generate_raw_coding(char* src, | |
197 | const struct_def *sdef, struct raw_option_struct *raw_options, | |
198 | boolean haspointer, boolean hascrosstag, boolean has_ext_bit) | |
199 | { | |
200 | int i; | |
201 | const char *name = sdef->name; | |
202 | ||
203 | if (sdef->kind == SET) { /* set decoder start */ | |
204 | size_t mand_num = 0; | |
205 | for (i = 0; i < sdef->nElements; i++) { | |
206 | if (!sdef->elements[i].isOptional) mand_num++; | |
207 | } | |
208 | src = mputprintf(src, "int %s::RAW_decode(const TTCN_Typedescriptor_t& " | |
209 | "p_td, TTCN_Buffer& p_buf, int limit, raw_order_t top_bit_ord, " | |
210 | "boolean, int, boolean)\n" | |
211 | "{\n" | |
970ed795 EL |
212 | "int prepaddlength = p_buf.increase_pos_padd(p_td.raw->prepadding);\n" |
213 | "limit -= prepaddlength;\n" | |
214 | "int decoded_length = 0;\n" | |
215 | "int field_map[%lu];\n" | |
216 | "memset(field_map, 0, sizeof(field_map));\n", | |
217 | name, (unsigned long) sdef->nElements); | |
218 | if (mand_num > 0) | |
219 | src = mputstr(src, "size_t nof_mand_fields = 0;\n"); | |
220 | for (i = 0; i < sdef->nElements; i++) { | |
221 | if (sdef->elements[i].isOptional) | |
222 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
223 | sdef->elements[i].name); | |
224 | } | |
225 | src = mputstr(src, | |
226 | "raw_order_t local_top_order;\n" | |
227 | "if (p_td.raw->top_bit_order == TOP_BIT_INHERITED) " | |
228 | "local_top_order = top_bit_ord;\n" | |
229 | "else if (p_td.raw->top_bit_order == TOP_BIT_RIGHT) " | |
230 | "local_top_order = ORDER_MSB;\n" | |
231 | "else local_top_order = ORDER_LSB;\n" | |
232 | "while (limit > 0) {\n" | |
233 | "size_t fl_start_pos = p_buf.get_pos_bit();\n" | |
234 | ); | |
235 | for (i = 0; i < sdef->nElements; i++) { /* decoding fields with tag */ | |
236 | if (raw_options[i].tag_type && | |
237 | sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements > 0) { | |
238 | rawAST_coding_taglist* cur_choice = | |
239 | sdef->raw.taglist.list + raw_options[i].tag_type - 1; | |
240 | size_t j; | |
241 | boolean has_fixed = FALSE, has_variable = FALSE, flag_needed = FALSE; | |
242 | for (j = 0; j < cur_choice->nElements; j++) { | |
243 | if (cur_choice->fields[j].start_pos >= 0) { | |
244 | if (has_fixed || has_variable) flag_needed = TRUE; | |
245 | has_fixed = TRUE; | |
246 | } else { | |
247 | if (has_fixed) flag_needed = TRUE; | |
248 | has_variable = TRUE; | |
249 | } | |
250 | if (has_fixed && has_variable) break; | |
251 | } | |
252 | src = mputprintf(src, "if (field_map[%lu] == 0) {\n", | |
253 | (unsigned long) i); | |
254 | if (flag_needed) | |
255 | src = mputstr(src, "boolean already_failed = FALSE;\n"); | |
256 | if (has_fixed) { | |
257 | /* first check the fields we can precode | |
258 | * try to decode those key variables whose position we know | |
259 | * this way we might be able to step over bad values faster | |
260 | */ | |
261 | boolean first_fixed = TRUE; | |
262 | src = mputstr(src, "raw_order_t temporal_top_order;\n" | |
263 | "int temporal_decoded_length;\n"); | |
264 | for (j = 0; j < cur_choice->nElements; j++) { | |
265 | size_t k; | |
266 | rawAST_coding_field_list *cur_field_list = cur_choice->fields + j; | |
267 | if (cur_field_list->start_pos < 0) continue; | |
268 | if (!first_fixed) src = mputstr(src, "if (!already_failed) {\n"); | |
269 | for (k = cur_field_list->nElements - 1; k > 0; k--) { | |
270 | src = mputprintf(src, "if (%s_descr_.raw->top_bit_order == " | |
271 | "TOP_BIT_RIGHT) temporal_top_order = ORDER_MSB;\n" | |
272 | "else if (%s_descr_.raw->top_bit_order == TOP_BIT_LEFT) " | |
273 | "temporal_top_order = ORDER_LSB;\n" | |
274 | "else ", cur_field_list->fields[k - 1].typedescr, | |
275 | cur_field_list->fields[k - 1].typedescr); | |
276 | } | |
277 | src = mputprintf(src, "temporal_top_order = top_bit_ord;\n" | |
278 | "%s temporal_%lu;\n" | |
279 | "p_buf.set_pos_bit(fl_start_pos + %d);\n" | |
280 | "temporal_decoded_length = temporal_%lu.RAW_decode(%s_descr_, " | |
281 | "p_buf, limit, temporal_top_order, TRUE);\n" | |
282 | "p_buf.set_pos_bit(fl_start_pos);\n" | |
283 | "if (temporal_decoded_length > 0 && temporal_%lu == %s) {\n" | |
284 | "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, " | |
285 | "p_buf, limit, local_top_order, TRUE);\n" | |
286 | "if (decoded_field_length %s 0 && (", | |
287 | cur_field_list->fields[cur_field_list->nElements - 1].type, | |
288 | (unsigned long) j, cur_field_list->start_pos, (unsigned long) j, | |
289 | cur_field_list->fields[cur_field_list->nElements - 1].typedescr, | |
290 | (unsigned long) j, cur_field_list->value, | |
291 | sdef->elements[i].name, | |
292 | sdef->elements[i].isOptional ? "()" : "", | |
293 | sdef->elements[i].typedescrname, | |
294 | sdef->elements[i].isOptional ? ">" : ">="); | |
295 | src = genRawFieldChecker(src, cur_choice, TRUE); | |
296 | src = mputstr(src, ")) {\n" | |
297 | "decoded_length += decoded_field_length;\n" | |
298 | "limit -= decoded_field_length;\n"); | |
299 | if (!sdef->elements[i].isOptional) | |
300 | src = mputstr(src, "nof_mand_fields++;\n"); | |
301 | src = mputprintf(src, "field_map[%lu] = 1;\n" | |
302 | "continue;\n" | |
303 | "} else {\n" | |
304 | "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i); | |
305 | if (sdef->elements[i].isOptional) | |
306 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
307 | sdef->elements[i].name); | |
308 | if (flag_needed) src = mputstr(src, "already_failed = TRUE;\n"); | |
309 | src = mputstr(src, "}\n" | |
310 | "}\n"); | |
311 | if (first_fixed) first_fixed = FALSE; | |
312 | else src = mputstr(src, "}\n"); | |
313 | } | |
314 | } | |
315 | if (has_variable) { | |
316 | /* if there is one tag key whose position we don't know | |
317 | * and we couldn't decide yet if element can be decoded or not | |
318 | * than we have to decode it. | |
319 | */ | |
320 | if (flag_needed) src = mputstr(src, "if (!already_failed) {\n"); | |
321 | src = mputprintf(src, "int decoded_field_length = " | |
322 | "field_%s%s.RAW_decode(%s_descr_, p_buf, limit, " | |
323 | "local_top_order, TRUE);\n" | |
324 | "if (decoded_field_length %s 0 && (", | |
325 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
326 | sdef->elements[i].typedescrname, | |
327 | sdef->elements[i].isOptional ? ">" : ">="); | |
328 | src = genRawFieldChecker(src, cur_choice, TRUE); | |
329 | src = mputstr(src, ")) {\n" | |
330 | "decoded_length += decoded_field_length;\n" | |
331 | "limit -= decoded_field_length;\n"); | |
332 | if (!sdef->elements[i].isOptional) | |
333 | src = mputstr(src, "nof_mand_fields++;\n"); | |
334 | src = mputprintf(src, "field_map[%lu] = 1;\n" | |
335 | "continue;\n" | |
336 | "} else {\n" | |
337 | "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i); | |
338 | if (sdef->elements[i].isOptional) | |
339 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
340 | sdef->elements[i].name); | |
341 | src = mputstr(src, "}\n"); | |
342 | if (flag_needed) src = mputstr(src, "}\n"); | |
343 | } | |
344 | src = mputstr(src, "}\n"); | |
345 | } | |
346 | } | |
347 | for (i = 0; i < sdef->nElements; i++) { | |
348 | /* decoding fields without TAG */ | |
349 | if (!raw_options[i].tag_type) { | |
350 | boolean repeatable; | |
351 | if (sdef->elements[i].of_type && sdef->elements[i].hasRaw && | |
352 | sdef->elements[i].raw.repeatable == XDEFYES) repeatable = TRUE; | |
353 | else { | |
354 | repeatable = FALSE; | |
355 | src = mputprintf(src, "if (field_map[%lu] == 0) ", | |
356 | (unsigned long) i); | |
357 | } | |
358 | src = mputprintf(src, "{\n" | |
359 | "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, " | |
360 | "p_buf, limit, local_top_order, TRUE", | |
361 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
362 | sdef->elements[i].typedescrname); | |
363 | if (repeatable) | |
364 | src = mputprintf(src, ", -1, field_map[%lu] == 0", | |
365 | (unsigned long) i); | |
366 | src = mputprintf(src, ");\n" | |
367 | "if (decoded_field_length %s 0) {\n" | |
368 | "decoded_length += decoded_field_length;\n" | |
369 | "limit -= decoded_field_length;\n", | |
370 | sdef->elements[i].isOptional ? ">" : ">="); | |
371 | if (repeatable) { | |
372 | if (!sdef->elements[i].isOptional) src = mputprintf(src, | |
373 | "if (field_map[%lu] == 0) nof_mand_fields++;\n", | |
374 | (unsigned long) i); | |
375 | src = mputprintf(src, "field_map[%lu]++;\n", (unsigned long) i); | |
376 | } else { | |
377 | if (!sdef->elements[i].isOptional) | |
378 | src = mputstr(src, "nof_mand_fields++;\n"); | |
379 | src = mputprintf(src, "field_map[%lu] = 1;\n", (unsigned long) i); | |
380 | } | |
381 | src = mputstr(src, "continue;\n" | |
382 | "} else {\n" | |
383 | "p_buf.set_pos_bit(fl_start_pos);\n"); | |
384 | if (sdef->elements[i].isOptional) { | |
385 | if (repeatable) | |
386 | src = mputprintf(src, "if (field_map[%lu] == 0) ", | |
387 | (unsigned long) i); | |
388 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
389 | sdef->elements[i].name); | |
390 | } | |
391 | src = mputstr(src, "}\n" | |
392 | "}\n"); | |
393 | } | |
394 | } | |
395 | for (i = 0; i < sdef->nElements; i++){ | |
396 | /* decoding fields with tag OTHERWISE */ | |
397 | if (raw_options[i].tag_type && | |
398 | sdef->raw.taglist.list[raw_options[i].tag_type-1].nElements == 0) { | |
399 | src = mputprintf(src, "if (field_map[%lu] == 0) {\n" | |
400 | "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, " | |
401 | "p_buf, limit, local_top_order, TRUE);\n" | |
402 | "if (decoded_field_length %s 0) {\n" | |
403 | "decoded_length += decoded_field_length;\n" | |
404 | "limit -= decoded_field_length;\n", (unsigned long) i, | |
405 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
406 | sdef->elements[i].typedescrname, | |
407 | sdef->elements[i].isOptional ? ">" : ">="); | |
408 | if (!sdef->elements[i].isOptional) | |
409 | src = mputstr(src, "nof_mand_fields++;\n"); | |
410 | src = mputprintf(src, "field_map[%lu] = 1;\n" | |
411 | "continue;\n" | |
412 | "} else {\n" | |
413 | "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i); | |
414 | if (sdef->elements[i].isOptional) | |
415 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", | |
416 | sdef->elements[i].name); | |
417 | src = mputstr(src, "}\n" | |
418 | "}\n"); | |
419 | } | |
420 | } | |
421 | src = mputstr(src, "break;\n" /* no field decoded successfully, quit */ | |
422 | "}\n"); | |
423 | if (mand_num > 0) src = mputprintf(src, | |
424 | "if (nof_mand_fields != %lu) return limit ? -1 : -TTCN_EncDec::ET_INCOMPL_MSG;\n", | |
425 | (unsigned long) mand_num); | |
426 | /* If not all required fields were decoded and there are no bits left, | |
427 | * that means that the last field was decoded successfully but used up | |
428 | * the buffer. Signal "incomplete". If there were bits left, that means that | |
429 | * no field could be decoded from them; signal an error. | |
430 | */ | |
431 | src = mputstr(src, "return decoded_length + prepaddlength + " | |
432 | "p_buf.increase_pos_padd(p_td.raw->padding);\n" | |
433 | "}\n\n"); | |
434 | } else { | |
435 | /* set decoder end, record decoder start */ | |
436 | int prev_ext_group = 0; | |
437 | src = mputprintf(src, | |
438 | "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, " | |
439 | "TTCN_Buffer& p_buf, int limit, raw_order_t top_bit_ord, boolean no_err, " | |
440 | "int, boolean)\n" | |
441 | "{ (void)no_err;\n" | |
970ed795 EL |
442 | " int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n" |
443 | " limit-=prepaddlength;\n" | |
444 | " size_t last_decoded_pos = p_buf.get_pos_bit();\n" | |
445 | " int decoded_length = 0;\n" | |
446 | " int decoded_field_length = 0;\n" | |
447 | " raw_order_t local_top_order;\n" | |
448 | , name); | |
449 | if (hascrosstag) { | |
450 | src = mputstr(src, " int selected_field = -1;\n"); | |
451 | } | |
452 | if (sdef->raw.ext_bit_goup_num) { | |
453 | src=mputstr(src, " int group_limit = 0;\n"); | |
454 | } | |
455 | src=mputstr(src, | |
456 | " if(p_td.raw->top_bit_order==TOP_BIT_INHERITED)" | |
457 | "local_top_order=top_bit_ord;\n" | |
458 | " else if(p_td.raw->top_bit_order==TOP_BIT_RIGHT)local_top_order" | |
459 | "=ORDER_MSB;\n" | |
460 | " else local_top_order=ORDER_LSB;\n" | |
461 | ); | |
462 | if(has_ext_bit){ | |
463 | src=mputstr(src, | |
464 | " {\n" | |
465 | " cbyte* data=p_buf.get_read_data();\n" | |
466 | " int count=1;\n" | |
467 | " unsigned mask = 1 << (local_top_order==ORDER_LSB ? 0 : 7);\n" | |
468 | " if(p_td.raw->extension_bit==EXT_BIT_YES){\n" | |
469 | " while((data[count-1] & mask)==0 && count*8<(int)limit) count++;\n" | |
470 | " }\n" | |
471 | " else{\n" | |
472 | " while((data[count-1] & mask)!=0 && count*8<(int)limit) count++;\n" | |
473 | " }\n" | |
474 | " if(limit) limit=count*8;\n" | |
475 | " }\n" | |
476 | ); | |
477 | } | |
478 | if(haspointer) | |
479 | src=mputstr(src, | |
480 | " int end_of_available_data=last_decoded_pos+limit;\n"); | |
481 | for(i=0;i<sdef->nElements;i++){ | |
482 | if(raw_options[i].pointerof) | |
483 | src=mputprintf(src, | |
484 | " int start_of_field%lu=-1;\n" | |
485 | ,(unsigned long) i | |
486 | ); | |
487 | if(raw_options[i].ptrbase) | |
488 | src=mputprintf(src, | |
489 | " int start_pos_of_field%lu=-1;\n" | |
490 | ,(unsigned long) i | |
491 | ); | |
492 | if(raw_options[i].lengthto) | |
493 | src=mputprintf(src, | |
494 | " int value_of_length_field%lu = 0;\n" | |
495 | ,(unsigned long) i | |
496 | ); | |
497 | } | |
498 | for(i=0;i<sdef->nElements;i++){ /* decoding fields */ | |
499 | if (raw_options[i].delayed_decode) { | |
500 | int j; | |
501 | /* checking whether there are enough bits in the buffer to decode | |
502 | the field */ | |
503 | src = mputstr(src, " if ("); | |
504 | src = genRawFieldDecodeLimit(src, sdef, i, raw_options); | |
505 | src = mputprintf(src, " < %d) return -TTCN_EncDec::ET_LEN_ERR;\n", | |
506 | sdef->elements[i].raw.length); | |
507 | /* skipping over the field that has to be decoded later because of | |
508 | forward referencing in CROSSTAG */ | |
509 | src = mputprintf(src, | |
510 | " size_t start_of_field%lu = p_buf.get_pos_bit();\n" | |
511 | " p_buf.set_pos_bit(start_of_field%lu + %d);\n" | |
512 | " decoded_length += %d;\n" | |
513 | " last_decoded_pos += %d;\n" | |
514 | " limit -= %d;\n", | |
515 | (unsigned long) i, (unsigned long) i, sdef->elements[i].raw.length, | |
516 | sdef->elements[i].raw.length, | |
517 | sdef->elements[i].raw.length, sdef->elements[i].raw.length); | |
518 | for (j = 0; j < raw_options[i].lengthof; j++) { | |
519 | src = mputprintf(src, | |
520 | " value_of_length_field%d -= %d;\n", | |
521 | raw_options[i].lengthoffield[j], sdef->elements[i].raw.length); | |
522 | } | |
523 | } else { | |
524 | src = genRawDecodeRecordField(src, sdef, i, raw_options, FALSE, | |
525 | &prev_ext_group); | |
526 | if (raw_options[i].nof_dependent_fields > 0) { | |
527 | int j; | |
528 | for (j = 0; j < raw_options[i].nof_dependent_fields; j++) { | |
529 | int dependent_field_index = raw_options[i].dependent_fields[j]; | |
530 | /* seek to the beginning of the dependent field */ | |
531 | src = mputprintf(src, | |
532 | " p_buf.set_pos_bit(start_of_field%d);\n", | |
533 | dependent_field_index); | |
534 | /* decode the dependent field */ | |
535 | src = genRawDecodeRecordField(src, sdef, dependent_field_index, | |
536 | raw_options, TRUE, &prev_ext_group); | |
537 | } | |
538 | if (i < sdef->nElements - 1) { | |
539 | /* seek back if there are more regular fields to decode */ | |
540 | src = mputstr(src, | |
541 | " p_buf.set_pos_bit(last_decoded_pos);\n"); | |
542 | } | |
543 | } | |
544 | } | |
545 | } /* decoding fields*/ | |
546 | ||
547 | if(sdef->hasRaw && sdef->raw.presence.nElements > 0) | |
548 | { | |
549 | src = mputstr(src, " if ("); | |
550 | src = genRawFieldChecker(src, &sdef->raw.presence, FALSE); | |
551 | src = mputstr(src, ") return -1;\n"); | |
552 | } | |
553 | ||
554 | src=mputstr(src, | |
555 | " p_buf.set_pos_bit(last_decoded_pos);\n" | |
556 | " return decoded_length+prepaddlength+" | |
557 | "p_buf.increase_pos_padd(p_td.raw->padding);\n}\n\n"); | |
558 | } /* record decoder end */ | |
559 | ||
560 | src = mputprintf(src, /* encoder */ | |
561 | "int %s::RAW_encode(const TTCN_Typedescriptor_t&%s, " | |
562 | "RAW_enc_tree& myleaf) const {\n", name, | |
563 | use_runtime_2 ? " p_td" : ""); | |
564 | if (use_runtime_2) { | |
565 | src = mputstr(src, " if (err_descr) return RAW_encode_negtest(err_descr, p_td, myleaf);\n"); | |
566 | } | |
567 | src = mputprintf(src, | |
568 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
569 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
570 | " int encoded_length = 0;\n" | |
571 | " myleaf.isleaf = false;\n" | |
572 | " myleaf.body.node.num_of_nodes = %lu;\n" | |
573 | " myleaf.body.node.nodes = init_nodes_of_enc_tree(%lu);\n", | |
574 | (unsigned long)sdef->nElements, (unsigned long)sdef->nElements); | |
575 | /* init nodes */ | |
576 | for (i = 0; i < sdef->nElements; i++) { | |
577 | if (sdef->elements[i].isOptional) { | |
578 | src = mputprintf(src, | |
579 | " if (field_%s.ispresent()) {\n", sdef->elements[i].name); | |
580 | } | |
581 | src = mputprintf(src, | |
582 | " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(true, &myleaf, " | |
583 | "&(myleaf.curr_pos), %lu, %s_descr_.raw);\n", | |
584 | (unsigned long)i, (unsigned long)i, sdef->elements[i].typedescrname); | |
585 | if (sdef->elements[i].isOptional) { | |
586 | src = mputprintf(src, | |
587 | " }\n" | |
588 | " else myleaf.body.node.nodes[%lu] = NULL;\n", (unsigned long)i); | |
589 | } | |
590 | } | |
591 | for (i = 0; i < sdef->raw.ext_bit_goup_num; i++) { | |
592 | if (sdef->raw.ext_bit_groups[i].ext_bit != XDEFNO) { | |
593 | src = mputprintf(src, | |
594 | " {\n" | |
595 | " int node_idx = %d;\n" | |
596 | " while (node_idx <= %d && myleaf.body.node.nodes[node_idx] == NULL) node_idx++;\n" | |
597 | " if (myleaf.body.node.nodes[node_idx]) {\n" | |
598 | " myleaf.body.node.nodes[node_idx]->ext_bit_handling = 1;\n" | |
599 | " myleaf.body.node.nodes[node_idx]->ext_bit = %s;\n }\n" | |
600 | " node_idx = %d;\n" | |
601 | " while (node_idx >= %d && myleaf.body.node.nodes[node_idx] == NULL) node_idx--;\n" | |
602 | " if (myleaf.body.node.nodes[node_idx]) myleaf.body.node.nodes[node_idx]" | |
603 | "->ext_bit_handling += 2;\n" | |
604 | " }\n", | |
605 | sdef->raw.ext_bit_groups[i].from, | |
606 | sdef->raw.ext_bit_groups[i].to, | |
607 | sdef->raw.ext_bit_groups[i].ext_bit == XDEFYES ? "EXT_BIT_YES" : "EXT_BIT_REVERSE", | |
608 | sdef->raw.ext_bit_groups[i].to, | |
609 | sdef->raw.ext_bit_groups[i].from); | |
610 | } | |
611 | } | |
612 | for (i = 0; i < sdef->nElements; i++) { | |
613 | /* encoding fields */ | |
614 | if (sdef->elements[i].isOptional) { | |
615 | src = mputprintf(src, | |
616 | " if (field_%s.ispresent()) {\n", sdef->elements[i].name); | |
617 | } | |
618 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex == NULL | |
619 | && sdef->elements[i].raw.union_member_num == 0) { | |
620 | /* encoding of lenghto fields */ | |
621 | int a; | |
622 | src = mputprintf(src, | |
623 | " encoded_length += %d;\n" | |
624 | " myleaf.body.node.nodes[%lu]->calc = CALC_LENGTH;\n" | |
625 | " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n" | |
626 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.num_of_fields = %d;\n" | |
627 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.unit = %d;\n" | |
628 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields = " | |
629 | "init_lengthto_fields_list(%d);\n" | |
630 | " myleaf.body.node.nodes[%lu]->length = %d;\n", | |
631 | sdef->elements[i].raw.fieldlength, (unsigned long)i, | |
632 | (unsigned long)i, sdef->elements[i].typedescrname, | |
633 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
634 | (unsigned long)i, sdef->elements[i].raw.unit, | |
635 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
636 | (unsigned long)i, sdef->elements[i].raw.fieldlength); | |
637 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
638 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
639 | src = mputprintf(src, | |
640 | " if (field_%s.ispresent()) {\n", | |
641 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
642 | } | |
643 | src = mputprintf(src, | |
644 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].level = " | |
645 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
646 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].pos = " | |
647 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", | |
648 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a], | |
649 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]); | |
650 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
651 | src = mputprintf(src, | |
652 | " } else {\n" | |
653 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].level = 0;\n" | |
654 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].pos = 0;\n" | |
655 | " }\n", (unsigned long)i, a, (unsigned long)i, a); | |
656 | } | |
657 | } | |
658 | } else if (raw_options[i].pointerto) { | |
659 | /* encoding of pointerto fields */ | |
660 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { | |
661 | src = mputprintf(src, | |
662 | " if (field_%s.ispresent()) {\n", | |
663 | sdef->elements[sdef->elements[i].raw.pointerto].name); | |
664 | } | |
665 | src = mputprintf(src, | |
666 | " encoded_length += %d;\n" | |
667 | " myleaf.body.node.nodes[%lu]->calc = CALC_POINTER;\n" | |
668 | " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n" | |
669 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.unit = %d;\n" | |
670 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.ptr_offset = %d;\n" | |
671 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.ptr_base = %d;\n" | |
672 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.target.level = " | |
673 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
674 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.target.pos = " | |
675 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n" | |
676 | " myleaf.body.node.nodes[%lu]->length = %d;\n", | |
677 | sdef->elements[i].raw.fieldlength,(unsigned long)i, | |
678 | (unsigned long)i, sdef->elements[i].typedescrname, | |
679 | (unsigned long)i, sdef->elements[i].raw.unit, | |
680 | (unsigned long)i, sdef->elements[i].raw.ptroffset, | |
681 | (unsigned long)i, sdef->elements[i].raw.pointerbase, | |
682 | (unsigned long)i, sdef->elements[i].raw.pointerto, | |
683 | (unsigned long)i, sdef->elements[i].raw.pointerto, | |
684 | (unsigned long)i, sdef->elements[i].raw.fieldlength); | |
685 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { | |
686 | src = mputprintf(src, | |
687 | " } else {\n" | |
688 | " INTEGER atm;\n" | |
689 | " atm = 0;\n" | |
690 | " encoded_length += atm.RAW_encode(%s_descr_" | |
691 | ", *myleaf.body.node.nodes[%lu]);\n" | |
692 | " }\n", | |
693 | sdef->elements[i].typedescrname, (unsigned long)i); | |
694 | } | |
695 | } else { | |
696 | /* encoding of normal fields */ | |
697 | src = mputprintf(src, | |
698 | " encoded_length += field_%s%s.RAW_encode(%s_descr_" | |
699 | ", *myleaf.body.node.nodes[%lu]);\n", | |
700 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
701 | sdef->elements[i].typedescrname, (unsigned long)i); | |
702 | } | |
703 | if (sdef->elements[i].isOptional) { | |
704 | src = mputstr(src, " }\n"); | |
705 | } | |
706 | } | |
707 | for (i = 0; i < sdef->nElements; i++) { | |
708 | /* fill presence, tag and crosstag */ | |
709 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex) { | |
710 | /* encoding of lenghto fields */ | |
711 | int a; | |
712 | if (sdef->elements[i].isOptional) { | |
713 | src = mputprintf(src, | |
714 | " if (field_%s.ispresent()) {\n", | |
715 | sdef->elements[i].name); | |
716 | } | |
717 | src = mputprintf(src, | |
718 | " if (myleaf.body.node.nodes[%lu]->body.node.nodes[%d]) {\n" | |
719 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
720 | "calc = CALC_LENGTH;\n" | |
721 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
722 | "coding_descr = &%s_descr_;\n" | |
723 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
724 | "calcof.lengthto.num_of_fields = %d;\n" | |
725 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
726 | "calcof.lengthto.unit = %d;\n" | |
727 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
728 | "calcof.lengthto.fields = " | |
729 | "init_lengthto_fields_list(%d);\n", | |
730 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
731 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
732 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
733 | sdef->elements[i].raw.lengthindex->typedescr, | |
734 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
735 | sdef->elements[i].raw.lengthto_num, | |
736 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
737 | sdef->elements[i].raw.unit, | |
738 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
739 | sdef->elements[i].raw.lengthto_num); | |
740 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
741 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
742 | src = mputprintf(src, | |
743 | " if (field_%s.ispresent()) {\n", | |
744 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
745 | } | |
746 | src = mputprintf(src, | |
747 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]" | |
748 | "->calcof.lengthto.fields[%d].level = " | |
749 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
750 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]" | |
751 | "->calcof.lengthto.fields[%d].pos = " | |
752 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", | |
753 | (unsigned long)i,sdef->elements[i].raw.lengthindex->nthfield, | |
754 | a, sdef->elements[i].raw.lengthto[a], | |
755 | (unsigned long)i,sdef->elements[i].raw.lengthindex->nthfield, | |
756 | a, sdef->elements[i].raw.lengthto[a]); | |
757 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
758 | src = mputprintf(src, | |
759 | " } else {\n" | |
760 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
761 | "calcof.lengthto.fields[%d].level = 0;\n" | |
762 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" | |
763 | "calcof.lengthto.fields[%d].pos = 0;\n" | |
764 | " }\n", | |
765 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a, | |
766 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a); | |
767 | } | |
768 | } | |
769 | src = mputstr(src, " }\n"); | |
770 | if (sdef->elements[i].isOptional) { | |
771 | src = mputstr(src, " }\n"); | |
772 | } | |
773 | } | |
774 | if (raw_options[i].lengthto && sdef->elements[i].raw.union_member_num) { | |
775 | /* encoding of lenghto fields */ | |
776 | int a; | |
777 | if (sdef->elements[i].isOptional) { | |
778 | src = mputprintf(src, | |
779 | " if (field_%s.ispresent()) ", sdef->elements[i].name); | |
780 | } | |
781 | ||
782 | src = mputprintf(src, | |
783 | " {\n" | |
784 | " int sel_field = 0;\n" | |
785 | " while (myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field] == NULL) " | |
786 | "{ sel_field++; }\n" | |
787 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" | |
788 | "calc = CALC_LENGTH;\n" | |
789 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" | |
790 | "calcof.lengthto.num_of_fields = %d;\n" | |
791 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" | |
792 | "calcof.lengthto.unit = %d;\n" | |
793 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" | |
794 | "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", | |
795 | (unsigned long)i,(unsigned long)i, | |
796 | (unsigned long)i,sdef->elements[i].raw.lengthto_num, | |
797 | (unsigned long)i,sdef->elements[i].raw.unit, | |
798 | (unsigned long)i,sdef->elements[i].raw.lengthto_num); | |
799 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
800 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
801 | src = mputprintf(src, | |
802 | " if (field_%s.ispresent()) {\n", | |
803 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
804 | } | |
805 | src = mputprintf(src, | |
806 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" | |
807 | "->calcof.lengthto.fields[%d].level = " | |
808 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
809 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" | |
810 | "->calcof.lengthto.fields[%d].pos = " | |
811 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", | |
812 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a], | |
813 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]); | |
814 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
815 | src = mputprintf(src, | |
816 | " }else{\n" | |
817 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" | |
818 | "->calcof.lengthto.fields[%d].level = 0;\n" | |
819 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" | |
820 | "->calcof.lengthto.fields[%d].pos = 0;\n" | |
821 | " }\n", | |
822 | (unsigned long)i, a, | |
823 | (unsigned long)i, a); | |
824 | } | |
825 | } | |
826 | src = mputstr(src, | |
827 | " }\n"); | |
828 | } | |
829 | if (raw_options[i].tag_type && sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements) { | |
830 | /* tag */ | |
831 | rawAST_coding_taglist *cur_choice = | |
832 | sdef->raw.taglist.list + raw_options[i].tag_type - 1; | |
833 | src = mputstr(src, " if ("); | |
834 | if (sdef->elements[i].isOptional) { | |
835 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); | |
836 | } | |
837 | src = genRawFieldChecker(src, cur_choice, FALSE); | |
838 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); | |
839 | src = mputstr(src,") {\n"); | |
840 | src = genRawTagChecker(src, cur_choice); | |
841 | src=mputstr(src," }\n"); | |
842 | } | |
843 | if (sdef->elements[i].hasRaw && sdef->elements[i].raw.presence.nElements) { | |
844 | /* presence */ | |
845 | src = mputstr(src, " if ("); | |
846 | if (sdef->elements[i].isOptional) { | |
847 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); | |
848 | } | |
849 | src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, FALSE); | |
850 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); | |
851 | src = mputstr(src, ") {\n"); | |
852 | src = genRawTagChecker(src, &sdef->elements[i].raw.presence); | |
853 | src = mputstr(src," }\n"); | |
854 | } | |
855 | if (sdef->elements[i].hasRaw && | |
856 | sdef->elements[i].raw.crosstaglist.nElements) { | |
857 | /* crosstag */ | |
858 | int a; | |
859 | if (sdef->elements[i].isOptional) { | |
860 | src = mputprintf(src, | |
861 | " if (field_%s.ispresent()) {\n", | |
862 | sdef->elements[i].name); | |
863 | } | |
864 | src = mputprintf(src, | |
865 | " switch (field_%s%s.get_selection()) {\n", | |
866 | sdef->elements[i].name,sdef->elements[i].isOptional ? "()" : ""); | |
867 | for (a = 0; a < sdef->elements[i].raw.crosstaglist.nElements; a++) { | |
868 | rawAST_coding_taglist *cur_choice = | |
869 | sdef->elements[i].raw.crosstaglist.list + a; | |
870 | if (cur_choice->nElements > 0) { | |
871 | src = mputprintf(src, " case %s%s%s:\n" | |
872 | " if (", sdef->elements[i].type, | |
873 | "::ALT_", cur_choice->fieldName); | |
874 | src = genRawFieldChecker(src, cur_choice, FALSE); | |
875 | src = mputstr(src, ") {\n"); | |
876 | if (!strcmp(cur_choice->fields[0].value, "OMIT_VALUE")) { | |
877 | if (cur_choice->fields[0].nElements != 1) | |
878 | NOTSUPP("omit value with multiple fields in CROSSTAG"); | |
879 | /* eliminating the corresponding encoded leaf, which will have | |
880 | the same effect as if the referred field had been omit */ | |
881 | src = mputprintf(src, | |
882 | " encoded_length -= myleaf.body.node.nodes[%d]->length;\n" | |
883 | " delete myleaf.body.node.nodes[%d];\n" | |
884 | " myleaf.body.node.nodes[%d] = NULL;\n", | |
885 | cur_choice->fields[0].fields[0].nthfield, | |
886 | cur_choice->fields[0].fields[0].nthfield, | |
887 | cur_choice->fields[0].fields[0].nthfield); | |
888 | } else { | |
889 | int ll; | |
890 | src = mputprintf(src, | |
891 | " RAW_enc_tr_pos pr_pos;\n" | |
892 | " pr_pos.level = myleaf.curr_pos.level + %d;\n" | |
893 | " int new_pos[] = { ", | |
894 | cur_choice->fields[0].nElements); | |
895 | for (ll = 0; ll < cur_choice->fields[0].nElements; ll++) { | |
896 | if (ll > 0) src = mputstr(src, ", "); | |
897 | src = mputprintf(src, "%d", | |
898 | cur_choice->fields[0].fields[ll].nthfield); | |
899 | } | |
900 | src = mputprintf(src, " };\n" | |
901 | " pr_pos.pos = init_new_tree_pos(myleaf.curr_pos, %d, " | |
902 | "new_pos);\n", | |
903 | cur_choice->fields[0].nElements); | |
904 | if (cur_choice->fields[0].value[0] == ' ') { | |
905 | /* the value is a string literal (the encoder can be called | |
906 | on that object directly */ | |
907 | src = mputprintf(src, | |
908 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" | |
909 | " if (temp_leaf != NULL)\n" | |
910 | " %s.RAW_encode(%s_descr_,*temp_leaf);\n" | |
911 | " else\n" | |
912 | " TTCN_EncDec_ErrorContext::error\n" | |
913 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged," | |
914 | " but omitted value.\");\n", | |
915 | cur_choice->fields[0].value, | |
916 | cur_choice->fields[0].fields[ | |
917 | cur_choice->fields[0].nElements - 1].typedescr); | |
918 | } else { | |
919 | /* a temporary object needs to be created for encoding */ | |
920 | src = mputprintf(src, | |
921 | " %s new_val(%s);\n" | |
922 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" | |
923 | " if (temp_leaf != NULL)\n" | |
924 | " new_val.RAW_encode(%s_descr_,*temp_leaf);\n" | |
925 | " else\n" | |
926 | " TTCN_EncDec_ErrorContext::error\n" | |
927 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged," | |
928 | " but omitted value.\");\n", | |
929 | cur_choice->fields[0].fields[ | |
930 | cur_choice->fields[0].nElements - 1].type, | |
931 | cur_choice->fields[0].value, | |
932 | cur_choice->fields[0].fields[ | |
933 | cur_choice->fields[0].nElements - 1].typedescr); | |
934 | } | |
935 | src = mputstr(src, " free_tree_pos(pr_pos.pos);\n"); | |
936 | } | |
937 | src = mputstr(src, " }\n" | |
938 | " break;\n"); | |
939 | } | |
940 | } | |
941 | src = mputstr(src, " default:;\n" | |
942 | " }\n"); | |
943 | if (sdef->elements[i].isOptional) src = mputstr(src, " }\n"); | |
944 | } | |
945 | } | |
946 | /* presence */ | |
947 | if (sdef->hasRaw && sdef->raw.presence.nElements > 0) { | |
948 | src = mputstr(src, " if ("); | |
949 | src = genRawFieldChecker(src, &sdef->raw.presence, FALSE); | |
950 | src = mputstr(src,") {\n"); | |
951 | src = genRawTagChecker(src, &sdef->raw.presence); | |
952 | src = mputstr(src," }\n"); | |
953 | } | |
954 | src = mputstr(src, " return myleaf.length = encoded_length;\n}\n\n"); | |
955 | ||
956 | if (use_runtime_2) | |
957 | src = generate_raw_coding_negtest(src, sdef, raw_options); | |
958 | return src; | |
959 | } | |
960 | ||
961 | char *generate_raw_coding_negtest(char *src, const struct_def *sdef, | |
962 | struct raw_option_struct *raw_options) | |
963 | { | |
964 | int i; | |
965 | const char *name = sdef->name; | |
966 | src = mputprintf(src, | |
967 | /* Count the nodes and discover the new node order only. No node creation | |
968 | or encoding. */ | |
969 | "int %s::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr, " | |
970 | "const TTCN_Typedescriptor_t& /*p_td*/, RAW_enc_tree& myleaf) const\n" | |
971 | "{\n" | |
972 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
973 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
974 | " int idx_map[%lu];\n" | |
975 | " for (int idx_map_idx = 0; idx_map_idx < %lu; ++idx_map_idx)\n" | |
976 | " idx_map[idx_map_idx] = -1;\n" | |
977 | " (void)idx_map;\n" | |
978 | " int encoded_length = 0;\n" | |
979 | " int num_fields = get_count();\n" | |
980 | " myleaf.isleaf = false;\n" | |
981 | " myleaf.body.node.num_of_nodes = 0;\n" | |
982 | " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n" | |
983 | " if ((p_err_descr->omit_before != -1) &&\n" | |
984 | " (field_idx < p_err_descr->omit_before))\n" | |
985 | " continue;\n" | |
986 | " const Erroneous_values_t *err_vals = p_err_descr->get_field_err_values(field_idx);\n" | |
987 | " const Erroneous_descriptor_t *emb_descr = p_err_descr->get_field_emb_descr(field_idx);\n" | |
988 | " if (err_vals && err_vals->before)\n" | |
989 | " ++myleaf.body.node.num_of_nodes;\n" | |
990 | " if (err_vals && err_vals->value) {\n" | |
991 | " if (err_vals->value->errval) {\n" | |
992 | " // Field is modified, but it's still there. Otherwise, it's\n" | |
993 | " // initialized to `-1'.\n" | |
994 | " idx_map[field_idx] = -2;\n" | |
995 | " ++myleaf.body.node.num_of_nodes;\n" | |
996 | " }\n" | |
997 | " } else {\n" | |
998 | " if (emb_descr) idx_map[field_idx] = -2;\n" | |
999 | " else idx_map[field_idx] = myleaf.body.node.num_of_nodes;\n" | |
1000 | " ++myleaf.body.node.num_of_nodes;\n" | |
1001 | " }\n" | |
1002 | " if (err_vals && err_vals->after)\n" | |
1003 | " ++myleaf.body.node.num_of_nodes;\n" | |
1004 | " if ((p_err_descr->omit_after != -1) &&\n" | |
1005 | " (field_idx >= p_err_descr->omit_after))\n" | |
1006 | " break;\n" | |
1007 | " }\n", | |
1008 | name, (unsigned long)sdef->nElements, (unsigned long)sdef->nElements); | |
1009 | /* Init nodes. */ | |
1010 | src = mputprintf(src, | |
1011 | " myleaf.body.node.nodes =\n" | |
1012 | " init_nodes_of_enc_tree(myleaf.body.node.num_of_nodes);\n" | |
1013 | " TTCN_EncDec_ErrorContext e_c;\n" | |
1014 | " int node_pos = 0;\n" | |
1015 | " int next_optional_idx = 0;\n" | |
1016 | " const int *my_optional_indexes = get_optional_indexes();\n" | |
1017 | " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n" | |
1018 | " boolean is_optional_field = my_optional_indexes &&\n" | |
1019 | " (my_optional_indexes[next_optional_idx] == field_idx);\n" | |
1020 | " if ((p_err_descr->omit_before != -1) &&\n" | |
1021 | " (field_idx < p_err_descr->omit_before)) {\n" | |
1022 | " if (is_optional_field) ++next_optional_idx;\n" | |
1023 | " continue;\n" | |
1024 | " }\n" | |
1025 | " const Erroneous_values_t *err_vals =\n" | |
1026 | " p_err_descr->get_field_err_values(field_idx);\n" | |
1027 | " if (err_vals && err_vals->before) {\n" | |
1028 | " if (err_vals->before->errval == NULL)\n" | |
1029 | " TTCN_error(\"internal error: erroneous before value missing\");\n" | |
1030 | " if (err_vals->before->raw) {\n" | |
1031 | " myleaf.body.node.nodes[node_pos] =\n" | |
1032 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1033 | " node_pos, err_vals->before->errval" | |
1034 | "->get_descriptor()->raw);\n" | |
1035 | " } else {\n" | |
1036 | " if (err_vals->before->type_descr == NULL)\n" | |
1037 | " TTCN_error(\"internal error: erroneous before typedescriptor " | |
1038 | "missing\");\n" | |
1039 | " myleaf.body.node.nodes[node_pos] =\n" | |
1040 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1041 | " node_pos, err_vals->before->type_descr->raw);\n" | |
1042 | " }\n" | |
1043 | " ++node_pos;\n" | |
1044 | " }\n" | |
1045 | " if (err_vals && err_vals->value) {\n" | |
1046 | " if (err_vals->value->errval) {\n" | |
1047 | " e_c.set_msg(\"'%%s'(erroneous value): \", fld_name(field_idx));\n" | |
1048 | " if (err_vals->value->raw) {\n" | |
1049 | " myleaf.body.node.nodes[node_pos] =\n" | |
1050 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1051 | " node_pos, err_vals->value->errval" | |
1052 | "->get_descriptor()->raw);\n" | |
1053 | " } else {\n" | |
1054 | " if (err_vals->value->type_descr == NULL)\n" | |
1055 | " TTCN_error(\"internal error: erroneous value typedescriptor " | |
1056 | "missing\");\n" | |
1057 | " myleaf.body.node.nodes[node_pos] =\n" | |
1058 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1059 | " node_pos, err_vals->value->type_descr->raw);\n" | |
1060 | " }\n" | |
1061 | " ++node_pos;\n" | |
1062 | " }\n" | |
1063 | " } else {\n" | |
1064 | " e_c.set_msg(\"'%%s': \", fld_name(field_idx));\n" | |
1065 | " if (!is_optional_field || get_at(field_idx)->ispresent()) {\n" | |
1066 | " myleaf.body.node.nodes[node_pos] =\n" | |
1067 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1068 | " node_pos, fld_descr(field_idx)->raw);\n" | |
1069 | " } else {\n" | |
1070 | " // `omitted' field.\n" | |
1071 | " myleaf.body.node.nodes[node_pos] = NULL;\n" | |
1072 | " }\n" | |
1073 | " ++node_pos;\n" | |
1074 | " }\n" | |
1075 | " if (err_vals && err_vals->after) {\n" | |
1076 | " if (err_vals->after->errval == NULL)\n" | |
1077 | " TTCN_error(\"internal error: erroneous before value missing\");\n" | |
1078 | " if (err_vals->after->raw) {\n" | |
1079 | " myleaf.body.node.nodes[node_pos] =\n" | |
1080 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1081 | " node_pos, err_vals->after->errval" | |
1082 | "->get_descriptor()->raw);\n" | |
1083 | " } else {\n" | |
1084 | " if (err_vals->after->type_descr == NULL)\n" | |
1085 | " TTCN_error(\"internal error: erroneous after typedescriptor " | |
1086 | "missing\");\n" | |
1087 | " myleaf.body.node.nodes[node_pos] =\n" | |
1088 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" | |
1089 | " node_pos, err_vals->after->type_descr->raw);\n" | |
1090 | " }\n" | |
1091 | " ++node_pos;\n" | |
1092 | " }\n" | |
1093 | " if (is_optional_field) ++next_optional_idx;\n" | |
1094 | " if ((p_err_descr->omit_after != -1) &&\n" | |
1095 | " (field_idx >= p_err_descr->omit_after))\n" | |
1096 | " break;\n" | |
1097 | " }\n"); | |
1098 | /* Handling of the tricky attributes. A simple integer array will be used | |
1099 | to track changes (field positions) in the record. | |
1100 | int idx_map[n_fields] = { | |
1101 | -1 (= field 0. was omitted), | |
1102 | 1 (= field 1. can be found at index 1.), | |
1103 | -2 (= field 2. is still at index 2., but its value has changed) }; */ | |
1104 | for (i = 0; i < sdef->raw.ext_bit_goup_num; i++) { | |
1105 | if (sdef->raw.ext_bit_groups[i].ext_bit != XDEFNO) { | |
1106 | src = mputprintf(src, | |
1107 | " {\n" | |
1108 | " bool in_between_modified = false;\n" | |
1109 | " for (int idx_map_idx = %d; idx_map_idx <= %d; ++idx_map_idx)\n" | |
1110 | " if (idx_map[idx_map_idx] < 0) {\n" | |
1111 | " in_between_modified = true;\n" | |
1112 | " break;\n" | |
1113 | " }\n" | |
1114 | " if (idx_map[%d] < 0 || idx_map[%d] < 0 ||\n" | |
1115 | " %d != idx_map[%d] - idx_map[%d] || in_between_modified) {\n" | |
1116 | " e_c.set_msg(\"Field #%d and/or #%d: \");\n" | |
1117 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1118 | " \"Conflicting negative testing attributes, extension bit " | |
1119 | "group #%d will be ignored\");\n" | |
1120 | " } else {\n" | |
1121 | " int node_idx = idx_map[%d];\n" | |
1122 | " while (node_idx <= idx_map[%d] &&\n" | |
1123 | " myleaf.body.node.nodes[node_idx] == NULL)\n" | |
1124 | " node_idx++;\n" | |
1125 | " if (myleaf.body.node.nodes[node_idx]) {\n" | |
1126 | " myleaf.body.node.nodes[node_idx]->ext_bit_handling = 1;\n" | |
1127 | " myleaf.body.node.nodes[node_idx]->ext_bit = %s;\n" | |
1128 | " }\n" | |
1129 | " node_idx = idx_map[%d];\n" | |
1130 | " while (node_idx >= idx_map[%d] &&\n" | |
1131 | " myleaf.body.node.nodes[node_idx] == NULL)\n" | |
1132 | " node_idx--;\n" | |
1133 | " if (myleaf.body.node.nodes[node_idx])\n" | |
1134 | " myleaf.body.node.nodes[node_idx]->ext_bit_handling += 2;\n" | |
1135 | " }\n" | |
1136 | " }\n", | |
1137 | sdef->raw.ext_bit_groups[i].from, | |
1138 | sdef->raw.ext_bit_groups[i].to, | |
1139 | sdef->raw.ext_bit_groups[i].from, | |
1140 | sdef->raw.ext_bit_groups[i].to, | |
1141 | sdef->raw.ext_bit_groups[i].to - sdef->raw.ext_bit_groups[i].from, | |
1142 | sdef->raw.ext_bit_groups[i].to, | |
1143 | sdef->raw.ext_bit_groups[i].from, | |
1144 | sdef->raw.ext_bit_groups[i].from, | |
1145 | sdef->raw.ext_bit_groups[i].to, i, | |
1146 | sdef->raw.ext_bit_groups[i].from, | |
1147 | sdef->raw.ext_bit_groups[i].to, | |
1148 | sdef->raw.ext_bit_groups[i].ext_bit == XDEFYES ? "EXT_BIT_YES" : "EXT_BIT_REVERSE", | |
1149 | sdef->raw.ext_bit_groups[i].to, | |
1150 | sdef->raw.ext_bit_groups[i].from); | |
1151 | } | |
1152 | } | |
1153 | for (i = 0; i < sdef->nElements; i++) { | |
1154 | if (sdef->elements[i].isOptional) { | |
1155 | src = mputprintf(src, | |
1156 | " if (field_%s.ispresent()) {\n", | |
1157 | sdef->elements[i].name); | |
1158 | } | |
1159 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex == NULL | |
1160 | && sdef->elements[i].raw.union_member_num == 0) { | |
1161 | /* Encoding of lenghto fields. */ | |
1162 | int a; | |
1163 | src = mputprintf(src, | |
1164 | " if (idx_map[%lu] < 0) {\n" | |
1165 | " e_c.set_msg(\"Field '%s': \");\n" | |
1166 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1167 | " \"Conflicting negative testing attributes, LENGTHTO " | |
1168 | "attribute will be ignored\");\n" | |
1169 | " } else {\n" | |
1170 | " bool negtest_confl_lengthto = false;\n", | |
1171 | (unsigned long)i, sdef->elements[i].name); | |
1172 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1173 | src = mputprintf(src, | |
1174 | " if (idx_map[%lu] < 0) {\n" | |
1175 | " negtest_confl_lengthto = true;\n" | |
1176 | " e_c.set_msg(\"Field '%s': \");\n" | |
1177 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1178 | " \"Conflicting negative testing attributes, LENGTHTO " | |
1179 | "attribute will be ignored\");\n" | |
1180 | " }\n", | |
1181 | (unsigned long)sdef->elements[i].raw.lengthto[a], | |
1182 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1183 | } | |
1184 | src = mputprintf(src, | |
1185 | " if (!negtest_confl_lengthto) {\n" | |
1186 | " encoded_length += %d;\n" | |
1187 | " myleaf.body.node.nodes[idx_map[%lu]]->calc = CALC_LENGTH;\n" | |
1188 | " myleaf.body.node.nodes[idx_map[%lu]]->coding_descr = &%s_descr_;\n" | |
1189 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.num_of_fields = %d;\n" | |
1190 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.unit = %d;\n" | |
1191 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields = " | |
1192 | "init_lengthto_fields_list(%d);\n" | |
1193 | " myleaf.body.node.nodes[idx_map[%lu]]->length = %d;\n", | |
1194 | sdef->elements[i].raw.fieldlength, (unsigned long)i, | |
1195 | (unsigned long)i, sdef->elements[i].typedescrname, | |
1196 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
1197 | (unsigned long)i, sdef->elements[i].raw.unit, | |
1198 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
1199 | (unsigned long)i, sdef->elements[i].raw.fieldlength); | |
1200 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1201 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1202 | src = mputprintf(src, | |
1203 | " if (field_%s.ispresent()) {\n", | |
1204 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1205 | } | |
1206 | src = mputprintf(src, | |
1207 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields[%lu].level = " | |
1208 | "myleaf.body.node.nodes[idx_map[%lu]]->curr_pos.level;\n" | |
1209 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields[%lu].pos = " | |
1210 | "myleaf.body.node.nodes[idx_map[%lu]]->curr_pos.pos;\n", | |
1211 | (unsigned long)i, (unsigned long)a, | |
1212 | (unsigned long)sdef->elements[i].raw.lengthto[a], | |
1213 | (unsigned long)i, (unsigned long)a, | |
1214 | (unsigned long)sdef->elements[i].raw.lengthto[a]); | |
1215 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1216 | src = mputprintf(src, | |
1217 | " } else {\n" | |
1218 | " myleaf.body.node.nodes[idx_map[%lu]]->" | |
1219 | "calcof.lengthto.fields[%lu].level = 0;\n" | |
1220 | " myleaf.body.node.nodes[idx_map[%lu]]->" | |
1221 | "calcof.lengthto.fields[%lu].pos = 0;\n" | |
1222 | " }\n", | |
1223 | (unsigned long)i, (unsigned long)a, | |
1224 | (unsigned long)i, (unsigned long)a); | |
1225 | } | |
1226 | } | |
1227 | /* Closing inner index check. */ | |
1228 | src = mputstr(src, | |
1229 | " }\n"); | |
1230 | /* Closing outer index check. */ | |
1231 | src = mputstr(src, | |
1232 | " }\n"); | |
1233 | } else if (raw_options[i].pointerto) { | |
1234 | /* Encoding of pointerto fields. */ | |
1235 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { | |
1236 | src = mputprintf(src, | |
1237 | " if (field_%s.ispresent()) {\n", | |
1238 | sdef->elements[sdef->elements[i].raw.pointerto].name); | |
1239 | } | |
1240 | src = mputprintf(src, | |
1241 | " bool in_between_modified_pointerto_%s = false;\n" | |
1242 | " for (int idx_map_idx = %d; idx_map_idx <= %d; ++idx_map_idx) {\n" | |
1243 | " if (idx_map[idx_map_idx] < 0) {\n" | |
1244 | " in_between_modified_pointerto_%s = true;\n" | |
1245 | " break;\n" | |
1246 | " }\n" | |
1247 | " }\n" | |
1248 | " if (idx_map[%lu] < 0 || idx_map[%lu] < 0 ||\n" | |
1249 | " %lu != idx_map[%lu] - idx_map[%lu] || in_between_modified_pointerto_%s) {\n" | |
1250 | " e_c.set_msg(\"Field '%s' and/or '%s': \");\n" | |
1251 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1252 | " \"Conflicting negative testing attributes, POINTERTO " | |
1253 | "attribute will be ignored\");\n" | |
1254 | " } else {\n" | |
1255 | " encoded_length += %d;\n" | |
1256 | " myleaf.body.node.nodes[idx_map[%lu]]->calc = CALC_POINTER;\n" | |
1257 | " myleaf.body.node.nodes[idx_map[%lu]]->coding_descr = &%s_descr_;\n" | |
1258 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.unit = %d;\n" | |
1259 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.ptr_offset = %d;\n" | |
1260 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.ptr_base = %d;\n" | |
1261 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.target.level = " | |
1262 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
1263 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.target.pos = " | |
1264 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n" | |
1265 | " myleaf.body.node.nodes[idx_map[%lu]]->length = %d;\n" | |
1266 | " }\n", | |
1267 | sdef->elements[i].name, | |
1268 | i, sdef->elements[i].raw.pointerto, | |
1269 | sdef->elements[i].name, (unsigned long)i, | |
1270 | (unsigned long)sdef->elements[i].raw.pointerto, | |
1271 | (unsigned long)sdef->elements[i].raw.pointerto - (unsigned long)i, | |
1272 | (unsigned long)sdef->elements[i].raw.pointerto, (unsigned long)i, | |
1273 | sdef->elements[i].name, sdef->elements[i].name, | |
1274 | sdef->elements[sdef->elements[i].raw.pointerto].name, | |
1275 | sdef->elements[i].raw.fieldlength, (unsigned long)i, | |
1276 | (unsigned long)i, sdef->elements[i].typedescrname, | |
1277 | (unsigned long)i, sdef->elements[i].raw.unit, | |
1278 | (unsigned long)i, sdef->elements[i].raw.ptroffset, | |
1279 | (unsigned long)i, sdef->elements[i].raw.pointerbase, | |
1280 | (unsigned long)i, sdef->elements[i].raw.pointerto, | |
1281 | (unsigned long)i, sdef->elements[i].raw.pointerto, | |
1282 | (unsigned long)i, sdef->elements[i].raw.fieldlength); | |
1283 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { | |
1284 | src = mputprintf(src, | |
1285 | " } else {\n" | |
1286 | " INTEGER atm;\n" | |
1287 | " atm = 0;\n" | |
1288 | " encoded_length += atm.RAW_encode(%s_descr_, " | |
1289 | "*myleaf.body.node.nodes[idx_map[%lu]]);\n" | |
1290 | " }\n", | |
1291 | sdef->elements[i].typedescrname, (unsigned long)i); | |
1292 | } | |
1293 | } else { | |
1294 | /* Encoding of normal fields with no negative testing. Needed for the | |
1295 | later phase. */ | |
1296 | src = mputprintf(src, | |
1297 | " if (idx_map[%lu] >= 0) " | |
1298 | "encoded_length += field_%s%s.RAW_encode(%s_descr_, " | |
1299 | "*myleaf.body.node.nodes[idx_map[%lu]]);\n", | |
1300 | (unsigned long)i, sdef->elements[i].name, | |
1301 | sdef->elements[i].isOptional ? "()" : "", | |
1302 | sdef->elements[i].typedescrname, (unsigned long)i); | |
1303 | } | |
1304 | if (sdef->elements[i].isOptional) { | |
1305 | src = mputstr(src, | |
1306 | " }\n"); | |
1307 | } | |
1308 | } | |
1309 | for (i = 0; i < sdef->nElements; i++) { | |
1310 | /* Fill presence, tag and crosstag. */ | |
1311 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex) { | |
1312 | /* Encoding of lenghto fields with lengthindex. */ | |
1313 | int a; | |
1314 | if (sdef->elements[i].isOptional) { | |
1315 | src = mputprintf(src, | |
1316 | " if (field_%s.ispresent()) {\n", | |
1317 | sdef->elements[i].name); | |
1318 | } | |
1319 | src = mputprintf(src, | |
1320 | " if (idx_map[%lu] < 0) {\n" | |
1321 | " e_c.set_msg(\"Field '%s': \");\n" | |
1322 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1323 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " | |
1324 | "attribute will be ignored\");\n" | |
1325 | " } else {\n" | |
1326 | " if (myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]) {\n" | |
1327 | " bool negtest_confl_lengthto = false;\n", | |
1328 | (unsigned long)i, sdef->elements[i].name, (unsigned long)i, | |
1329 | sdef->elements[i].raw.lengthindex->nthfield); | |
1330 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1331 | src = mputprintf(src, | |
1332 | " if (idx_map[%lu] < 0) {\n" | |
1333 | " negtest_confl_lengthto = true;\n" | |
1334 | " e_c.set_msg(\"Field '%s': \");\n" | |
1335 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1336 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " | |
1337 | "attribute will be ignored\");\n" | |
1338 | " }\n", | |
1339 | (unsigned long)sdef->elements[i].raw.lengthto[a], | |
1340 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1341 | } | |
1342 | src = mputprintf(src, | |
1343 | " if (!negtest_confl_lengthto) {\n" | |
1344 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1345 | "calc = CALC_LENGTH;\n" | |
1346 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1347 | "coding_descr = &%s_descr_;\n" | |
1348 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1349 | "calcof.lengthto.num_of_fields = %d;\n" | |
1350 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1351 | "calcof.lengthto.unit = %d;\n" | |
1352 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1353 | "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", | |
1354 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1355 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1356 | sdef->elements[i].raw.lengthindex->typedescr, | |
1357 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1358 | sdef->elements[i].raw.lengthto_num, | |
1359 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1360 | sdef->elements[i].raw.unit, | |
1361 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, | |
1362 | sdef->elements[i].raw.lengthto_num); | |
1363 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1364 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1365 | src = mputprintf(src, | |
1366 | " if (field_%s.ispresent()) {\n", | |
1367 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1368 | } | |
1369 | src = mputprintf(src, | |
1370 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]" | |
1371 | "->calcof.lengthto.fields[%d].level = " | |
1372 | "myleaf.body.node.nodes[idx_map[%d]]->curr_pos.level;\n" | |
1373 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]" | |
1374 | "->calcof.lengthto.fields[%d].pos = " | |
1375 | "myleaf.body.node.nodes[idx_map[%d]]->curr_pos.pos;\n", | |
1376 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a, | |
1377 | sdef->elements[i].raw.lengthto[a], (unsigned long)i, | |
1378 | sdef->elements[i].raw.lengthindex->nthfield, a, | |
1379 | sdef->elements[i].raw.lengthto[a]); | |
1380 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1381 | src = mputprintf(src, | |
1382 | " } else {\n" | |
1383 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1384 | "calcof.lengthto.fields[%d].level = 0;\n" | |
1385 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" | |
1386 | "calcof.lengthto.fields[%d].pos = 0;\n" | |
1387 | " }\n", | |
1388 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a, | |
1389 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a); | |
1390 | } | |
1391 | } | |
1392 | /* Closing index check. */ | |
1393 | src = mputstr(src, | |
1394 | " }\n"); | |
1395 | src = mputstr(src, " }\n }\n"); | |
1396 | if (sdef->elements[i].isOptional) { | |
1397 | src = mputstr(src, " }\n"); | |
1398 | } | |
1399 | } | |
1400 | if (raw_options[i].lengthto && sdef->elements[i].raw.union_member_num) { | |
1401 | /* Encoding of lenghto fields. */ | |
1402 | int a; | |
1403 | if (sdef->elements[i].isOptional) { | |
1404 | src = mputprintf(src, | |
1405 | " if (field_%s.ispresent()) ", sdef->elements[i].name); | |
1406 | } | |
1407 | src = mputprintf(src, | |
1408 | " {\n" | |
1409 | " if (idx_map[%lu] < 0) {\n" | |
1410 | " e_c.set_msg(\"Field '%s': \");\n" | |
1411 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1412 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " | |
1413 | "attribute will be ignored\");\n" | |
1414 | " } else {\n" | |
1415 | " bool negtest_confl_lengthto = false;\n", | |
1416 | (unsigned long)i, sdef->elements[i].name); | |
1417 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1418 | src = mputprintf(src, | |
1419 | " if (idx_map[%lu] < 0) {\n" | |
1420 | " negtest_confl_lengthto = true;\n" | |
1421 | " e_c.set_msg(\"Field '%s': \");\n" | |
1422 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1423 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " | |
1424 | "attribute will be ignored\");\n" | |
1425 | " }\n", | |
1426 | (unsigned long)sdef->elements[i].raw.lengthto[a], | |
1427 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1428 | } | |
1429 | src = mputprintf(src, | |
1430 | " if (!negtest_confl_lengthto) {\n" | |
1431 | " int sel_field = 0;\n" | |
1432 | " while (myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field] == NULL) " | |
1433 | "{ sel_field++; }\n" | |
1434 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" | |
1435 | "calc = CALC_LENGTH;\n" | |
1436 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" | |
1437 | "calcof.lengthto.num_of_fields = %d;\n" | |
1438 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" | |
1439 | "calcof.lengthto.unit = %d;\n" | |
1440 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" | |
1441 | "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", | |
1442 | (unsigned long)i, (unsigned long)i, | |
1443 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, | |
1444 | (unsigned long)i, sdef->elements[i].raw.unit, | |
1445 | (unsigned long)i, sdef->elements[i].raw.lengthto_num); | |
1446 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { | |
1447 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1448 | src = mputprintf(src, | |
1449 | " if (field_%s.ispresent()) {\n", | |
1450 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); | |
1451 | } | |
1452 | src = mputprintf(src, | |
1453 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" | |
1454 | "->calcof.lengthto.fields[%d].level = " | |
1455 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" | |
1456 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" | |
1457 | "->calcof.lengthto.fields[%d].pos = " | |
1458 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", | |
1459 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a], | |
1460 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]); | |
1461 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { | |
1462 | src = mputprintf(src, | |
1463 | " } else {\n" | |
1464 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" | |
1465 | "->calcof.lengthto.fields[%d].level = 0;\n" | |
1466 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" | |
1467 | "->calcof.lengthto.fields[%d].pos = 0;\n" | |
1468 | " }\n", | |
1469 | (unsigned long)i, a, | |
1470 | (unsigned long)i, a); | |
1471 | } | |
1472 | } | |
1473 | /* Closing inner index check. */ | |
1474 | src = mputstr(src, | |
1475 | " }\n"); | |
1476 | /* Closing outer index check. */ | |
1477 | src = mputstr(src, | |
1478 | " }\n"); | |
1479 | /* Closing ispresent or local block. */ | |
1480 | src = mputstr(src, | |
1481 | " }\n"); | |
1482 | } | |
1483 | if (raw_options[i].tag_type && | |
1484 | sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements) { | |
1485 | /* Plain, old tag. */ | |
1486 | rawAST_coding_taglist *cur_choice = | |
1487 | sdef->raw.taglist.list + raw_options[i].tag_type - 1; | |
1488 | src = mputprintf(src, | |
1489 | " bool negtest_confl_tag_%s = false;\n" | |
1490 | " if (idx_map[%lu] < 0) {\n" | |
1491 | " negtest_confl_tag_%s = true;\n" | |
1492 | " e_c.set_msg(\"Field '%s': \");\n" | |
1493 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1494 | " \"Conflicting negative testing attributes, TAG attribute will " | |
1495 | "be ignored\");\n" | |
1496 | " }\n", | |
1497 | sdef->elements[i].name, (unsigned long)i, sdef->elements[i].name, | |
1498 | sdef->elements[i].name); | |
1499 | src = mputprintf(src, " if (!negtest_confl_tag_%s && (", | |
1500 | sdef->elements[i].name); | |
1501 | if (sdef->elements[i].isOptional) { | |
1502 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); | |
1503 | } | |
1504 | src = genRawFieldChecker(src, cur_choice, FALSE); | |
1505 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); | |
1506 | src = mputstr(src,")) {\n"); | |
1507 | src = genRawTagChecker(src, cur_choice); | |
1508 | src = mputstr(src," }\n"); | |
1509 | } | |
1510 | if (sdef->elements[i].hasRaw && sdef->elements[i].raw.presence.nElements) { | |
1511 | /* Presence attribute for fields. */ | |
1512 | int taglist_idx, field_idx; | |
1513 | /* The optional field itself. */ | |
1514 | src = mputprintf(src, | |
1515 | " bool negtest_confl_presence_%s = false;\n" | |
1516 | " if (idx_map[%lu] < 0) {\n" | |
1517 | " negtest_confl_presence_%s = true;\n" | |
1518 | " e_c.set_msg(\"Field '%s': \");\n" | |
1519 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1520 | " \"Conflicting negative testing attributes, PRESENCE attribute " | |
1521 | "will be ignored\");\n" | |
1522 | " }\n", | |
1523 | sdef->elements[i].name, (unsigned long)i, sdef->elements[i].name, | |
1524 | sdef->elements[i].name); | |
1525 | /* Check the referenced fields. */ | |
1526 | for (taglist_idx = 0; | |
1527 | taglist_idx < sdef->elements[i].raw.presence.nElements; ++taglist_idx) { | |
1528 | rawAST_coding_field_list *fields = | |
1529 | sdef->elements[i].raw.presence.fields + taglist_idx; | |
1530 | for (field_idx = 0; field_idx < fields->nElements; ++field_idx) { | |
1531 | /* The top level field is enough. >0 index is for subrefs. */ | |
1532 | if (field_idx == 0) { | |
1533 | rawAST_coding_fields *field = fields->fields + field_idx; | |
1534 | src = mputprintf(src, | |
1535 | " if (idx_map[%d] < 0) {\n" | |
1536 | " negtest_confl_presence_%s = true;\n" | |
1537 | " e_c.set_msg(\"Field '%s': \");\n" | |
1538 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1539 | " \"Conflicting negative testing attributes, PRESENCE attribute " | |
1540 | "will be ignored\");\n" | |
1541 | " }\n", | |
1542 | field->nthfield, sdef->elements[i].name, field->nthfieldname); | |
1543 | } else { | |
1544 | /* Subrefs. */ | |
1545 | break; | |
1546 | } | |
1547 | } | |
1548 | } | |
1549 | src = mputprintf(src, " if (!negtest_confl_presence_%s && (", | |
1550 | sdef->elements[i].name); | |
1551 | if (sdef->elements[i].isOptional) { | |
1552 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); | |
1553 | } | |
1554 | src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, FALSE); | |
1555 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); | |
1556 | src = mputstr(src, ")) {\n"); | |
1557 | src = genRawTagChecker(src, &sdef->elements[i].raw.presence); | |
1558 | src = mputstr(src, " }\n"); | |
1559 | } | |
1560 | if (sdef->elements[i].hasRaw && | |
1561 | sdef->elements[i].raw.crosstaglist.nElements) { | |
1562 | /* crosstag */ | |
1563 | int a; | |
1564 | /* The union field itself. */ | |
1565 | src = mputprintf(src, | |
1566 | " if (idx_map[%lu] < 0) {\n" | |
1567 | " e_c.set_msg(\"Field '%s': \");\n" | |
1568 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1569 | " \"Conflicting negative testing attributes, CROSSTAG attribute " | |
1570 | "will be ignored\");\n" | |
1571 | " } else {\n", | |
1572 | (unsigned long)i, sdef->elements[i].name); | |
1573 | if (sdef->elements[i].isOptional) { | |
1574 | src = mputprintf(src, | |
1575 | " if (field_%s.ispresent()) {\n", | |
1576 | sdef->elements[i].name); | |
1577 | } | |
1578 | src = mputprintf(src, | |
1579 | " switch (field_%s%s.get_selection()) {\n", | |
1580 | sdef->elements[i].name,sdef->elements[i].isOptional ? "()" : ""); | |
1581 | for (a = 0; a < sdef->elements[i].raw.crosstaglist.nElements; a++) { | |
1582 | rawAST_coding_taglist *cur_choice = | |
1583 | sdef->elements[i].raw.crosstaglist.list + a; | |
1584 | if (cur_choice->nElements > 0) { | |
1585 | int taglist_idx, field_idx; | |
1586 | src = mputprintf(src, | |
1587 | " case %s%s%s: {\n" | |
1588 | " bool negtest_confl_crosstag = false;\n", | |
1589 | sdef->elements[i].type, "::ALT_", | |
1590 | cur_choice->fieldName); | |
1591 | for (taglist_idx = 0; | |
1592 | taglist_idx < cur_choice->nElements; ++taglist_idx) { | |
1593 | rawAST_coding_field_list *fields = cur_choice->fields + taglist_idx; | |
1594 | for (field_idx = 0; field_idx < fields->nElements; ++field_idx) { | |
1595 | rawAST_coding_fields *field = fields->fields + field_idx; | |
1596 | if (field_idx == 0) { | |
1597 | src = mputprintf(src, | |
1598 | " if (idx_map[%d] < 0) {\n" | |
1599 | " negtest_confl_crosstag = true;\n" | |
1600 | " e_c.set_msg(\"Field '%s': \");\n" | |
1601 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1602 | " \"Conflicting negative testing attributes, CROSSTAG attribute " | |
1603 | "will be ignored\");\n" | |
1604 | " }\n", | |
1605 | field->nthfield, field->nthfieldname); | |
1606 | } else { | |
1607 | break; | |
1608 | } | |
1609 | } | |
1610 | } | |
1611 | src = mputstr(src, " if (!negtest_confl_crosstag && ("); | |
1612 | src = genRawFieldChecker(src, cur_choice, FALSE); | |
1613 | src = mputstr(src, ")) {\n"); | |
1614 | if (!strcmp(cur_choice->fields[0].value, "OMIT_VALUE")) { | |
1615 | if (cur_choice->fields[0].nElements != 1) | |
1616 | NOTSUPP("omit value with multiple fields in CROSSTAG"); | |
1617 | /* eliminating the corresponding encoded leaf, which will have | |
1618 | the same effect as if the referred field had been omit */ | |
1619 | src = mputprintf(src, | |
1620 | " encoded_length -= myleaf.body.node.nodes[%d]->length;\n" | |
1621 | " delete myleaf.body.node.nodes[%d];\n" | |
1622 | " myleaf.body.node.nodes[%d] = NULL;\n", | |
1623 | cur_choice->fields[0].fields[0].nthfield, | |
1624 | cur_choice->fields[0].fields[0].nthfield, | |
1625 | cur_choice->fields[0].fields[0].nthfield); | |
1626 | } else { | |
1627 | int ll; | |
1628 | src = mputprintf(src, | |
1629 | " RAW_enc_tr_pos pr_pos;\n" | |
1630 | " pr_pos.level = myleaf.curr_pos.level + %d;\n" | |
1631 | " int new_pos[] = { ", | |
1632 | cur_choice->fields[0].nElements); | |
1633 | for (ll = 0; ll < cur_choice->fields[0].nElements; ll++) { | |
1634 | if (ll > 0) src = mputstr(src, ", "); | |
1635 | src = mputprintf(src, "%d", | |
1636 | cur_choice->fields[0].fields[ll].nthfield); | |
1637 | } | |
1638 | src = mputprintf(src, " };\n" | |
1639 | " pr_pos.pos = init_new_tree_pos(myleaf.curr_pos, %d, " | |
1640 | "new_pos);\n", | |
1641 | cur_choice->fields[0].nElements); | |
1642 | if (cur_choice->fields[0].value[0] == ' ') { | |
1643 | /* the value is a string literal (the encoder can be called | |
1644 | on that object directly */ | |
1645 | src = mputprintf(src, | |
1646 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" | |
1647 | " if (temp_leaf != NULL)\n" | |
1648 | " %s.RAW_encode(%s_descr_, *temp_leaf);\n" | |
1649 | " else\n" | |
1650 | " TTCN_EncDec_ErrorContext::error\n" | |
1651 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged, " | |
1652 | "but omitted value.\");\n", | |
1653 | cur_choice->fields[0].value, | |
1654 | cur_choice->fields[0].fields[ | |
1655 | cur_choice->fields[0].nElements - 1].typedescr); | |
1656 | } else { | |
1657 | /* a temporary object needs to be created for encoding */ | |
1658 | src = mputprintf(src, | |
1659 | " %s new_val(%s);\n" | |
1660 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" | |
1661 | " if (temp_leaf != NULL)\n" | |
1662 | " new_val.RAW_encode(%s_descr_, *temp_leaf);\n" | |
1663 | " else\n" | |
1664 | " TTCN_EncDec_ErrorContext::error\n" | |
1665 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged, " | |
1666 | "but omitted value.\");\n", | |
1667 | cur_choice->fields[0].fields[ | |
1668 | cur_choice->fields[0].nElements - 1].type, | |
1669 | cur_choice->fields[0].value, | |
1670 | cur_choice->fields[0].fields[ | |
1671 | cur_choice->fields[0].nElements - 1].typedescr); | |
1672 | } | |
1673 | src = mputstr(src, " free_tree_pos(pr_pos.pos);\n"); | |
1674 | } | |
1675 | src = mputstr(src, " }\n" | |
1676 | " break; }\n"); | |
1677 | } | |
1678 | } | |
1679 | src = mputstr(src, " default:;\n" | |
1680 | " }\n"); | |
1681 | if (sdef->elements[i].isOptional) src = mputstr(src, " }\n"); | |
1682 | src = mputstr(src, " }\n"); | |
1683 | } | |
1684 | } | |
1685 | src = mputprintf(src, | |
1686 | " node_pos = 0;\n" | |
1687 | " next_optional_idx = 0;\n" | |
1688 | " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n" | |
1689 | " boolean is_optional_field = my_optional_indexes &&\n" | |
1690 | " (my_optional_indexes[next_optional_idx] == field_idx);\n" | |
1691 | " if ((p_err_descr->omit_before != -1) &&\n" | |
1692 | " (field_idx < p_err_descr->omit_before)) {\n" | |
1693 | " if (is_optional_field) ++next_optional_idx;\n" | |
1694 | " continue;\n" | |
1695 | " }\n" | |
1696 | " const Erroneous_values_t *err_vals = p_err_descr->get_field_err_values(field_idx);\n" | |
1697 | " const Erroneous_descriptor_t *emb_descr = p_err_descr->get_field_emb_descr(field_idx);\n" | |
1698 | " if (err_vals && err_vals->before) {\n" | |
1699 | " if (err_vals->before->errval == NULL)\n" | |
1700 | " TTCN_error(\"internal error: erroneous before value missing\");\n" | |
1701 | " if (err_vals->before->raw) {\n" | |
1702 | " encoded_length += err_vals->before->errval->" | |
1703 | "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n" | |
1704 | " } else {\n" | |
1705 | " if (err_vals->before->type_descr == NULL)\n" | |
1706 | " TTCN_error(\"internal error: erroneous before typedescriptor missing\");\n" | |
1707 | " encoded_length += err_vals->before->errval->RAW_encode(*(err_vals->before->type_descr),\n" | |
1708 | " *myleaf.body.node.nodes[node_pos++]);\n" | |
1709 | " }\n" | |
1710 | " }\n" | |
1711 | " if (err_vals && err_vals->value) {\n" | |
1712 | " if (err_vals->value->errval) {\n" | |
1713 | " e_c.set_msg(\"'%%s'(erroneous value): \", fld_name(field_idx));\n" | |
1714 | " if (err_vals->value->raw) {\n" | |
1715 | " encoded_length += err_vals->value->errval->" | |
1716 | "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n" | |
1717 | " } else {\n" | |
1718 | " if (err_vals->value->type_descr == NULL)\n" | |
1719 | " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n" | |
1720 | " encoded_length += err_vals->value->errval->" | |
1721 | "RAW_encode(*(err_vals->value->type_descr), *myleaf.body.node.nodes[node_pos++]);\n" | |
1722 | " }\n" | |
1723 | " }\n" | |
1724 | " } else {\n" | |
1725 | " e_c.set_msg(\"'%%s': \", fld_name(field_idx));\n" | |
1726 | " if (!is_optional_field || get_at(field_idx)->ispresent()) {\n" | |
1727 | " const Base_Type *curr_field = is_optional_field " | |
1728 | "? get_at(field_idx)->get_opt_value() : get_at(field_idx);\n" | |
1729 | " if (emb_descr) {\n" | |
1730 | " encoded_length += curr_field\n" | |
1731 | " ->RAW_encode_negtest(emb_descr, *fld_descr(field_idx),\n" | |
1732 | " *myleaf.body.node.nodes[node_pos]);\n" | |
1733 | " }\n" | |
1734 | " } else {\n" | |
1735 | " // `omitted' field.\n" | |
1736 | " myleaf.body.node.nodes[node_pos] = NULL;\n" | |
1737 | " }\n" | |
1738 | " ++node_pos;\n" | |
1739 | " }\n" | |
1740 | " if (err_vals && err_vals->after) {\n" | |
1741 | " if (err_vals->after->errval == NULL)\n" | |
1742 | " TTCN_error(\"internal error: erroneous before value missing\");\n" | |
1743 | " if (err_vals->after->raw) {\n" | |
1744 | " encoded_length += err_vals->after->errval->" | |
1745 | "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n" | |
1746 | " } else {\n" | |
1747 | " if (err_vals->after->type_descr == NULL)\n" | |
1748 | " TTCN_error(\"internal error: erroneous after typedescriptor missing\");\n" | |
1749 | " encoded_length += err_vals->after->errval->" | |
1750 | "RAW_encode(*(err_vals->after->type_descr), *myleaf.body.node.nodes[node_pos++]);\n" | |
1751 | " }\n" | |
1752 | " }\n" | |
1753 | " if (is_optional_field) ++next_optional_idx;\n" | |
1754 | " if ((p_err_descr->omit_after != -1) &&\n" | |
1755 | " (field_idx >= p_err_descr->omit_after))\n" | |
1756 | " break;\n" | |
1757 | " }\n"); | |
1758 | /* Presence for the whole record. */ | |
1759 | if (sdef->hasRaw && sdef->raw.presence.nElements > 0) { | |
1760 | /* Check the referenced fields. */ | |
1761 | int taglist_idx, field_idx; | |
1762 | src = mputstr(src, " bool negtest_confl_presence = false;\n"); | |
1763 | for (taglist_idx = 0; taglist_idx < sdef->raw.presence.nElements; ++taglist_idx) { | |
1764 | rawAST_coding_field_list *fields = | |
1765 | sdef->raw.presence.fields + taglist_idx; | |
1766 | for (field_idx = 0; field_idx < fields->nElements; ++field_idx) { | |
1767 | if (field_idx == 0) { | |
1768 | rawAST_coding_fields *field = fields->fields + field_idx; | |
1769 | src = mputprintf(src, | |
1770 | " if (idx_map[%d] < 0) {\n" | |
1771 | " negtest_confl_presence = true;\n" | |
1772 | " e_c.set_msg(\"Field '%s': \");\n" | |
1773 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" | |
1774 | " \"Conflicting negative testing attributes, PRESENCE attribute " | |
1775 | "will be ignored\");\n" | |
1776 | " }\n", | |
1777 | field->nthfield, field->nthfieldname); | |
1778 | } else { | |
1779 | break; | |
1780 | } | |
1781 | } | |
1782 | } | |
1783 | src = mputstr(src, " if (!negtest_confl_presence && ("); | |
1784 | src = genRawFieldChecker(src, &sdef->raw.presence, FALSE); | |
1785 | src = mputstr(src,")) {\n"); | |
1786 | src = genRawTagChecker(src, &sdef->raw.presence); | |
1787 | src = mputstr(src," }\n"); | |
1788 | } | |
1789 | src = mputstr(src, | |
1790 | " return myleaf.length = encoded_length;\n" | |
1791 | "}\n\n"); | |
1792 | return src; | |
1793 | } | |
1794 | ||
1795 | void gen_xer(const struct_def *sdef, char **pdef, char **psrc) | |
1796 | { /* XERSTUFF codegen for record/SEQUENCE */ | |
1797 | size_t i; | |
1798 | char *def = *pdef, *src = *psrc; | |
1799 | const char * const name = sdef->name; | |
1800 | ||
1801 | /* | |
1802 | * NOTE! Decisions based on the coding instructions of the components | |
1803 | * (e.g. number of attributes) can be made at compile time. | |
1804 | * Decisions on coding instructions of the record itself (e.g. D-F-E, | |
1805 | * EMBED-VALUES, USE-NIL, USE-ORDER) __must__ be postponed to run-time, | |
1806 | * because these can be applied to type references, | |
1807 | * which will not be visible when the code is generated. | |
1808 | */ | |
1809 | ||
1810 | /* Number of fields with ATTRIBUTE, includes ANY-ATTRIBUTES */ | |
1811 | size_t num_attributes = 0; | |
1812 | ||
1813 | /* index of USE-ORDER member, which may be bumped into second place by EMBED-VALUES */ | |
1814 | size_t uo = (sdef->xerEmbedValuesPossible !=0); | |
1815 | ||
1816 | /* start_at is the index of the first "real" member of the record */ | |
1817 | size_t start_at = uo + (sdef->xerUseOrderPossible != 0); | |
1818 | ||
970ed795 EL |
1819 | /* Number of optional non-attributes */ |
1820 | size_t n_opt_elements = 0; | |
1821 | ||
1822 | const boolean want_namespaces = !sdef->isASN1 /* TODO remove this when ASN.1 gets EXER */; | |
1823 | ||
1824 | int aa_index = -1; | |
1825 | /* Find the number of attributes (compile time) */ | |
1826 | for (i = 0; i < sdef->nElements; ++i) { | |
1827 | if (sdef->elements[i].xerAttribute) { | |
1828 | ++num_attributes; | |
1829 | } | |
1830 | else if (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT) { | |
1831 | ++num_attributes; /* ANY-ATTRIBUTES also included with attributes */ | |
1832 | aa_index = i; | |
1833 | /* If the first member is ANY-ATTRIBUTES, then xerEmbedValuesPossible | |
1834 | * is merely an illusion and USE-ORDER is not possible. */ | |
1835 | if (i==0) { | |
1836 | start_at = uo = 0; | |
1837 | } | |
1838 | } | |
1839 | else /* not attribute */ if (sdef->elements[i].isOptional) { | |
1840 | ++n_opt_elements; | |
1841 | } | |
1842 | } | |
970ed795 EL |
1843 | |
1844 | /* Write some helper functions */ | |
1845 | def = mputstr(def, | |
1846 | "char **collect_ns(const XERdescriptor_t& p_td, size_t& num_ns, bool& def_ns) const;\n"); | |
1847 | ||
1848 | src = mputprintf(src, | |
1849 | "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num_ns, bool& def_ns) const {\n" | |
1850 | " size_t num_collected;\n" | |
1851 | " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n" | |
1852 | /* The above might throw but then nothing was allocated. */ | |
1853 | , name); | |
1854 | ||
1855 | /* Collect namespaces from the "non-special" members (incl. attributes) */ | |
1856 | if (start_at < sdef->nElements) src = mputstr(src, | |
1857 | " try {\n" | |
1858 | " char **new_ns;\n" | |
1859 | " size_t num_new;\n" | |
1860 | " bool def_ns_1 = false;\n"); | |
1861 | for (i = start_at; i < sdef->nElements; ++i) { | |
1862 | src = mputprintf(src, | |
1863 | " new_ns = field_%s.collect_ns(%s_xer_, num_new, def_ns);\n" | |
1864 | " merge_ns(collected_ns, num_collected, new_ns, num_new);\n" | |
1865 | " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */ | |
1866 | , sdef->elements[i].name, sdef->elements[i].typegen | |
1867 | ); | |
1868 | } | |
1869 | if (sdef->xerUseNilPossible) { | |
1870 | src = mputprintf(src, | |
1871 | " if((p_td.xer_bits & USE_NIL) && !field_%s.ispresent()) {\n" /* "nil" attribute to be written*/ | |
1872 | " collected_ns = (char**)Realloc(collected_ns, sizeof(char*) * ++num_collected);\n" | |
1873 | " const namespace_t *c_ns = p_td.my_module->get_controlns();\n" | |
1874 | " collected_ns[num_collected-1] = mprintf(\" xmlns:%%s='%%s'\", c_ns->px, c_ns->ns);\n" | |
1875 | " }\n" | |
1876 | , sdef->elements[sdef->nElements-1].name | |
1877 | ); | |
1878 | } | |
1879 | if (start_at < sdef->nElements) src = mputstr(src, | |
1880 | " }\n" | |
1881 | " catch (...) {\n" | |
1882 | /* Probably a TC_Error thrown from field_%s->collect_ns() if e.g. | |
1883 | * encoding an unbound value. */ | |
1884 | " while (num_collected > 0) Free(collected_ns[--num_collected]);\n" | |
1885 | " Free(collected_ns);\n" | |
1886 | " throw;\n" | |
1887 | " }\n" | |
1888 | ); | |
1889 | ||
1890 | src = mputstr(src, | |
1891 | " num_ns = num_collected;\n" | |
1892 | " return collected_ns;\n" | |
1893 | "}\n\n" | |
1894 | ); | |
1895 | ||
1896 | src = mputprintf(src, | |
1897 | "boolean %s::can_start(const char *name, const char *uri, const XERdescriptor_t& xd, unsigned int flavor) {\n" | |
1898 | " boolean e_xer = is_exer(flavor &= ~XER_RECOF);\n" | |
1899 | " if (!e_xer || !((xd.xer_bits & UNTAGGED) || (flavor & (USE_NIL|XER_RECOF)))) return check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n" | |
1900 | , name | |
1901 | ); | |
1902 | for (i = start_at; i < sdef->nElements; ++i) { | |
1903 | src = mputprintf(src, | |
1904 | " else if (%s::can_start(name, uri, %s_xer_, flavor)) return true;\n" | |
1905 | /* Here we know for sure it's exer */ | |
1906 | , sdef->elements[i].type | |
1907 | , sdef->elements[i].typegen | |
1908 | ); | |
1909 | if (!sdef->elements[i].isOptional) break; | |
1910 | /* The last component with which it can begin is the first non-optional. | |
1911 | * Does that sentence makes sense to you ? */ | |
1912 | } | |
1913 | src = mputstr(src, " return false;\n}\n\n"); | |
1914 | ||
1915 | /* * * * * * * * * * XER_encode * * * * * * * * * * * * * * */ | |
1916 | src = mputprintf(src, | |
1917 | "int %s::XER_encode(const XERdescriptor_t& p_td, " | |
af710487 | 1918 | "TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n" |
970ed795 EL |
1919 | "{\n" |
1920 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
1921 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
1922 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" | |
1923 | " TTCN_EncDec_ErrorContext ec_1;\n" | |
1924 | " int encoded_length=(int)p_buf.get_len();\n" | |
1925 | " int e_xer = is_exer(p_flavor);\n" | |
1926 | " const boolean omit_tag = e_xer && p_indent " | |
1927 | "&& ((p_td.xer_bits & (UNTAGGED|XER_ATTRIBUTE)) || (p_flavor & (USE_NIL|USE_TYPE_ATTR)));\n" | |
1928 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) p_flavor |= XER_CANONICAL;\n" | |
1929 | " int is_indented = !is_canonical(p_flavor);\n" | |
1930 | , name); | |
1931 | ||
1932 | if (want_namespaces && !(num_attributes|sdef->xerUseQName)) src = mputstr(src, | |
1933 | " const boolean need_control_ns = (p_td.xer_bits & (USE_NIL));\n"); | |
1934 | ||
3f84031e | 1935 | if (want_namespaces && (start_at < sdef->nElements)) { /* there _are_ non-special members */ |
970ed795 EL |
1936 | src = mputstr(src, |
1937 | " size_t num_collected = 0;\n" | |
1938 | " char **collected_ns = NULL;\n" | |
1939 | " bool def_ns = false;\n" | |
1940 | " if (e_xer) {\n" | |
1941 | " if (p_indent == 0) {\n" /* top-level */ | |
1942 | " collected_ns = collect_ns(p_td, num_collected, def_ns);\n" /* our own ns */ | |
1943 | " }\n" | |
1944 | " else if ((p_flavor & DEF_NS_SQUASHED) && p_td.my_module && p_td.ns_index != -1){\n" | |
1945 | " const namespace_t * ns = p_td.my_module->get_ns(p_td.ns_index);\n" | |
1946 | " if (*ns->px == '\\0') {\n" | |
1947 | " collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n" | |
1948 | " }\n" | |
1949 | " }\n" | |
1950 | " }\n" | |
1951 | ); | |
1952 | } | |
1953 | ||
1954 | if (want_namespaces) { | |
1955 | src = mputstr(src, | |
1956 | " const boolean empty_ns_hack = e_xer && !omit_tag && (p_indent > 0)\n" | |
1957 | " && (p_td.xer_bits & FORM_UNQUALIFIED)\n" | |
1958 | " && p_td.my_module && p_td.ns_index != -1\n" | |
1959 | " && *p_td.my_module->get_ns(p_td.ns_index)->px == '\\0';\n" | |
1960 | ); | |
1961 | ||
51fa56b9 | 1962 | src = mputstr(src, " boolean delay_close = e_xer"); |
970ed795 EL |
1963 | if (!(num_attributes | sdef->xerUseQName)) { |
1964 | src = mputprintf(src, " && (need_control_ns%s || empty_ns_hack)", | |
1965 | (start_at < sdef->nElements) ? " || num_collected" : ""); | |
1966 | } | |
1967 | src = mputstr(src, ";\n"); | |
1968 | } | |
1969 | ||
1970 | ||
1971 | { /* write start tag */ | |
1972 | /* From "name>\n": | |
1973 | * lose the \n if : not indenting or (single untagged(*) or attributes (*)) AND e_xer | |
1974 | * lose the > if attributes are present (*) AND e_xer | |
1975 | */ | |
1976 | src = mputprintf(src, | |
1977 | " size_t chopped_chars = 0;\n" | |
1978 | " if (!omit_tag) {\n" | |
1979 | " if (is_indented) do_indent(p_buf, p_indent);\n" | |
1980 | " p_buf.put_c('<');\n" | |
1981 | " if (e_xer) write_ns_prefix(p_td, p_buf);\n" | |
1982 | " p_buf.put_s((size_t)p_td.namelens[e_xer]%s-(!is_indented%s), " | |
1983 | "(cbyte*)p_td.names[e_xer]);\n" | |
1984 | " }\n" | |
feade998 | 1985 | " else if (p_flavor & (USE_NIL|USE_TYPE_ATTR)) {\n" |
970ed795 EL |
1986 | " size_t buf_len = p_buf.get_len();\n" |
1987 | " const unsigned char * const buf_data = p_buf.get_data();\n" | |
1988 | " if (buf_data[buf_len-1-chopped_chars] == '\\n') ++chopped_chars;\n" | |
1989 | " if (buf_data[buf_len-1-chopped_chars] == '>' ) ++chopped_chars;\n" | |
1990 | " if (chopped_chars) {\n" | |
1991 | " p_buf.increase_length(-chopped_chars);\n" | |
1992 | " }\n" | |
51fa56b9 | 1993 | "%s" |
970ed795 EL |
1994 | " }\n" |
1995 | , (want_namespaces ? "-(delay_close || (e_xer && (p_td.xer_bits & HAS_1UNTAGGED)))" : "") | |
51fa56b9 | 1996 | , (want_namespaces ? " || delay_close" : "") |
1997 | , (want_namespaces ? " delay_close = TRUE;\n" : "")); | |
970ed795 EL |
1998 | } |
1999 | ||
2000 | src = mputprintf(src, | |
2001 | " int sub_len=0%s;\n" | |
2002 | " p_flavor &= XER_MASK;\n", | |
2003 | num_attributes ? ", tmp_len; (void)tmp_len" : ""); | |
2004 | ||
2005 | if (sdef->xerUseQName) { | |
2006 | src = mputprintf(src, | |
2007 | " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n" | |
2008 | " if (field_%s.is_value()) {\n" | |
2009 | " p_buf.put_s(11, (cbyte*)\" xmlns:b0='\");\n" | |
af710487 | 2010 | " field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1, 0);\n" |
970ed795 EL |
2011 | " p_buf.put_c('\\'');\n" |
2012 | " }\n" | |
2013 | " if (p_td.xer_bits & XER_ATTRIBUTE) begin_attribute(p_td, p_buf);\n" | |
2014 | " else p_buf.put_c('>');\n" | |
2015 | " if (field_%s.is_value()) {\n" | |
2016 | " p_buf.put_s(3, (cbyte*)\"b0:\");\n" | |
2017 | " sub_len += 3;\n" | |
2018 | " }\n" | |
af710487 | 2019 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1, 0);\n" |
970ed795 EL |
2020 | " if (p_td.xer_bits & XER_ATTRIBUTE) p_buf.put_c('\\'');\n" |
2021 | " } else" /* no newline */ | |
2022 | , sdef->elements[0].name | |
2023 | , sdef->elements[0].name, sdef->elements[0].typegen | |
2024 | , sdef->elements[0].name | |
2025 | , sdef->elements[1].name, sdef->elements[1].typegen | |
2026 | ); | |
2027 | } | |
2028 | src = mputstr(src, " { // !QN\n"); | |
3f84031e | 2029 | |
2030 | /* First, the EMBED-VALUES member as an ordinary member if not doing EXER */ | |
970ed795 EL |
2031 | if (sdef->xerEmbedValuesPossible) { |
2032 | src = mputprintf(src, | |
970ed795 EL |
2033 | " if (!e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" |
2034 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2035 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
970ed795 | 2036 | " }\n" |
970ed795 EL |
2037 | , sdef->elements[0].dispname |
2038 | , sdef->elements[0].name, sdef->elements[0].typegen | |
2039 | ); | |
2040 | } | |
2041 | /* Then, the USE-ORDER member as an ordinary member when !EXER */ | |
2042 | if (sdef->xerUseOrderPossible) { | |
2043 | src = mputprintf(src, | |
2044 | " if (!e_xer && (p_td.xer_bits & USE_ORDER)) {\n" | |
af710487 | 2045 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
970ed795 EL |
2046 | " }\n" |
2047 | , sdef->elements[uo].name, sdef->elements[uo].typegen | |
2048 | ); | |
2049 | } | |
2050 | ||
2051 | if (start_at+num_attributes > sdef->nElements) FATAL_ERROR("defRecordClass1"); | |
2052 | ||
2053 | if (want_namespaces && (start_at < sdef->nElements)) { | |
2054 | src = mputstr(src, | |
2055 | " if (e_xer && num_collected) {\n" | |
2056 | " size_t num_ns;\n" | |
2057 | " for (num_ns = 0; num_ns < num_collected; ++num_ns) {\n" | |
2058 | " p_buf.put_s(strlen(collected_ns[num_ns]), (cbyte*)collected_ns[num_ns]);\n" | |
2059 | " Free(collected_ns[num_ns]);\n" | |
2060 | " }\n" | |
2061 | " Free(collected_ns);\n" | |
2062 | " }\n\n" | |
2063 | " if (def_ns) {\n" | |
2064 | " p_flavor &= ~DEF_NS_SQUASHED;\n" | |
2065 | " p_flavor |= DEF_NS_PRESENT;\n" | |
2066 | " }\n" | |
2067 | " else if (empty_ns_hack) {\n" | |
2068 | " p_buf.put_s(9, (cbyte*)\" xmlns=''\");\n" | |
2069 | " p_flavor &= ~DEF_NS_PRESENT;\n" | |
2070 | " p_flavor |= DEF_NS_SQUASHED;\n" | |
2071 | " }\n"); | |
2072 | } | |
2073 | ||
2074 | /* Then, all the attributes (not added to sub_len) */ | |
2075 | for ( i = start_at; i < start_at + num_attributes; ++i ) { | |
2076 | /* If the first component is a record-of with ANY-ATTRIBUTES, | |
2077 | * it has been taken care of because it looked like an EMBED-VALUES */ | |
2078 | if (i==0 && sdef->xerEmbedValuesPossible && (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) continue ; | |
2079 | src = mputprintf(src, | |
2080 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2081 | " tmp_len = field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
970ed795 EL |
2082 | " %ssub_len += tmp_len;\n" /* do not add if attribute and EXER */ |
2083 | , sdef->elements[i].dispname | |
2084 | , sdef->elements[i].name, sdef->elements[i].typegen | |
3f84031e | 2085 | , sdef->elements[i].xerAttribute || (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT) ? "if (!e_xer) " : "" |
970ed795 EL |
2086 | ); |
2087 | } | |
2088 | ||
2089 | if (sdef->xerUseNilPossible) { | |
2090 | src = mputprintf(src, | |
2091 | " bool nil_attribute = e_xer && (p_td.xer_bits & USE_NIL) && !field_%s.ispresent();\n" | |
2092 | " if (nil_attribute) {\n" | |
2093 | " const namespace_t *control_ns = p_td.my_module->get_controlns();\n" | |
2094 | " p_buf.put_c(' ');\n" | |
2095 | " p_buf.put_s(strlen(control_ns->px), (cbyte*)control_ns->px);\n" | |
2096 | " p_buf.put_c(':');\n" | |
2097 | " p_buf.put_s(10, (cbyte*)\"nil='true'\");\n" | |
2098 | " }\n" | |
2099 | , sdef->elements[sdef->nElements-1].name | |
2100 | ); | |
2101 | } | |
feade998 | 2102 | |
970ed795 EL |
2103 | if (want_namespaces) { |
2104 | /* there were some attributes. close the start tag left open */ | |
2105 | src = mputprintf(src, | |
2106 | " if (delay_close && (!omit_tag || chopped_chars)) p_buf.put_s(1%s, (cbyte*)\">\\n\");\n", /* close the start tag */ | |
2107 | (sdef->xerUntaggedOne /*|| sdef->xerUseNil*/) ? "" : "+is_indented" | |
2108 | ); | |
2109 | } | |
2110 | ||
2111 | if (sdef->xerEmbedValuesPossible) { | |
970ed795 EL |
2112 | src = mputprintf(src, |
2113 | " ec_1.set_msg(\"%s': \");\n" | |
2114 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" | |
970ed795 | 2115 | /* write the first string (must come AFTER the attributes) */ |
3f84031e | 2116 | " if (%s%s%s field_%s%s.size_of() > 0) {\n" |
2117 | " sub_len += field_%s%s[0].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" | |
af710487 | 2118 | " }\n" |
970ed795 | 2119 | " }\n" |
3f84031e | 2120 | , sdef->elements[0].dispname |
2121 | , sdef->elements[0].isOptional ? "field_" : "" | |
2122 | , sdef->elements[0].isOptional ? sdef->elements[0].name : "" | |
2123 | , sdef->elements[0].isOptional ? ".ispresent() &&" : "" | |
2124 | , sdef->elements[0].name | |
2125 | , sdef->elements[0].isOptional ? "()" : "", sdef->elements[0].name | |
2126 | , sdef->elements[0].isOptional ? "()" : ""); | |
970ed795 EL |
2127 | if (want_namespaces) { /* here's another chance */ |
2128 | src = mputprintf(src, | |
2129 | " else if ( !(p_td.xer_bits & EMBED_VALUES)) {\n" | |
af710487 | 2130 | " %sfield_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
970ed795 EL |
2131 | " }\n" |
2132 | , ((sdef->elements[0].xerAnyKind & ANY_ATTRIB_BIT) ? "" : "sub_len += " ) | |
2133 | , sdef->elements[0].name, sdef->elements[0].typegen | |
2134 | ); | |
2135 | } | |
2136 | } | |
2137 | ||
2138 | /* Then, all the non-attributes. Structuring the code like this depends on | |
2139 | * all attributes appearing before all non-attributes (excluding | |
2140 | * special members for EMBED-VALUES, USE-ORDER, etc.) */ | |
af710487 | 2141 | if (sdef->xerEmbedValuesPossible) { |
2142 | src = mputprintf(src, | |
2143 | " embed_values_enc_struct_t* emb_val = 0;\n" | |
3f84031e | 2144 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && " |
2145 | " %s%s%s field_%s%s.size_of() > 1) {\n" | |
af710487 | 2146 | " emb_val = new embed_values_enc_struct_t;\n" |
a38c6d4c | 2147 | /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated |
2148 | * record of universal charstring, so it needs a cast to avoid a compilation error */ | |
3f84031e | 2149 | " emb_val->embval_array%s = (const PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s%s;\n" |
a38c6d4c | 2150 | " emb_val->embval_array%s = NULL;\n" |
af710487 | 2151 | " emb_val->embval_index = 1;\n" |
a38c6d4c | 2152 | " }\n" |
3f84031e | 2153 | , sdef->elements[0].isOptional ? "field_" : "" |
2154 | , sdef->elements[0].isOptional ? sdef->elements[0].name : "" | |
2155 | , sdef->elements[0].isOptional ? ".ispresent() &&" : "" | |
a38c6d4c | 2156 | , sdef->elements[0].name |
3f84031e | 2157 | , sdef->elements[0].isOptional ? "()" : "" |
a38c6d4c | 2158 | , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg" |
2159 | , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : "" | |
2160 | , sdef->elements[0].name | |
3f84031e | 2161 | , sdef->elements[0].isOptional ? "()" : "" |
a38c6d4c | 2162 | , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt"); |
af710487 | 2163 | } |
2164 | ||
970ed795 EL |
2165 | if (sdef->xerUseOrderPossible) { |
2166 | int max_ordered = sdef->nElements - start_at - num_attributes; | |
2167 | int min_ordered = max_ordered - n_opt_elements; | |
2168 | size_t offset = 0; | |
2169 | size_t base = i; | |
2170 | size_t limit = sdef->nElements; | |
2171 | /* base and limit are indexes into sdef->elements[] */ | |
2172 | src = mputprintf(src, | |
2173 | " int dis_order = e_xer && (p_td.xer_bits & USE_ORDER);\n" | |
2174 | " int to_send = field_%s.lengthof();\n" | |
2175 | " int uo_limit = dis_order ? to_send : %lu;\n" | |
2176 | , sdef->elements[start_at-1].name | |
2177 | , (unsigned long)(limit - base) | |
2178 | ); | |
2179 | if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */ | |
2180 | base = sdef->nElements; | |
2181 | limit = sdef->totalElements; | |
2182 | min_ordered = max_ordered = limit - base; | |
2183 | src = mputprintf(src, | |
2184 | " if (!nil_attribute) {\n" | |
2185 | "%s" | |
af710487 | 2186 | " if (!e_xer) sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, 0);\n" |
970ed795 EL |
2187 | " else" /* no newline */ |
2188 | , (sdef->xerUseNilPossible ? " if (!(p_td.xer_bits & USE_ORDER)) p_flavor |= (p_td.xer_bits & USE_NIL);\n" : "") | |
2189 | /* If USE-ORDER is on, the tag-removing effect of USE-NIL has been | |
2190 | * performed by calling the sub-fields directly. */ | |
2191 | , sdef->elements[sdef->nElements-1].name | |
2192 | , sdef->elements[sdef->nElements-1].typegen | |
2193 | ); | |
2194 | } | |
2195 | ||
2196 | /* check incorrect data */ | |
2197 | src = mputprintf(src, | |
2198 | " {\n" | |
2199 | " if (to_send < %d || to_send > %d) {\n" | |
2200 | " ec_1.set_msg(\"%s': \");\n" | |
2201 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, " | |
2202 | "\"Wrong number of USE-ORDER, %%d instead of %d..%d\", to_send);\n" | |
2203 | " uo_limit = -1;\n" /* squash the loop */ | |
2204 | " }\n" | |
2205 | " else {\n" /* check duplicates */ | |
2206 | " int *seen = new int [to_send];\n" | |
2207 | " int num_seen = 0;\n" | |
2208 | " for (int ei = 0; ei < to_send; ++ei) {\n" | |
2209 | " int val = field_%s[ei];\n" | |
2210 | " for (int x = 0; x < num_seen; ++x) {\n" | |
2211 | " if (val == seen[x]) { // complain\n" | |
2212 | " ec_1.set_msg(\"%s': \");\n" | |
2213 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n" | |
2214 | " \"Duplicate value for USE-ORDER\");\n" | |
2215 | " uo_limit = -1; // don't bother sending anything\n" | |
2216 | " goto trouble;\n" | |
2217 | " }\n" | |
2218 | " }\n" | |
2219 | " seen[num_seen++] = val;\n" | |
2220 | " }\n" | |
2221 | "trouble:\n" | |
2222 | " delete [] seen;" | |
2223 | " }\n" | |
2224 | " " | |
2225 | , min_ordered, max_ordered | |
2226 | , sdef->elements[start_at-1].dispname | |
2227 | , min_ordered, max_ordered | |
2228 | , sdef->elements[start_at-1].name | |
2229 | , sdef->elements[start_at-1].dispname | |
2230 | ); | |
2231 | ||
2232 | src = mputprintf(src, | |
2233 | " for (int i = 0; i < uo_limit; ++i) {\n" | |
2234 | " switch (dis_order ? (int)field_%s[i] : i) {\n" | |
2235 | , sdef->elements[start_at-1].name | |
2236 | ); | |
2237 | for ( i = base; i < limit; ++i ) { | |
2238 | src = mputprintf(src, | |
2239 | " case %lu:\n" | |
2240 | " ec_1.set_msg(\"%s': \");\n" | |
af710487 | 2241 | " sub_len += field_%s%s%s%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, %s);\n" |
970ed795 EL |
2242 | |
2243 | , (unsigned long)offset++ | |
2244 | , sdef->elements[i].dispname | |
2245 | , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name : sdef->elements[i].name) | |
2246 | , (sdef->xerUseNilPossible ? "()." : "") | |
2247 | , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") | |
2248 | , (sdef->xerUseNilPossible ? "()" : "") | |
2249 | , sdef->elements[i].typegen | |
af710487 | 2250 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0" |
970ed795 EL |
2251 | ); |
2252 | ||
2253 | src = mputstr(src, " break;\n"); | |
2254 | } /* next element */ | |
2255 | src = mputstr(src, | |
2256 | " default:\n" | |
2257 | " TTCN_error(\"Runaway value while encoding USE-ORDER\");\n" | |
2258 | " break;\n" /* cannot happen, complain */ | |
2259 | " }\n"); | |
2260 | ||
2261 | if (sdef->xerEmbedValuesPossible) { | |
2262 | src = mputprintf(src, | |
af710487 | 2263 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n" |
3f84031e | 2264 | " %s%s%s emb_val->embval_index < field_%s%s.size_of()) { // embed-val\n" |
2265 | " field_%s%s[emb_val->embval_index].XER_encode(\n" | |
af710487 | 2266 | " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" |
2267 | " ++emb_val->embval_index;\n" | |
970ed795 | 2268 | " }\n" |
3f84031e | 2269 | , sdef->elements[0].isOptional ? "field_" : "" |
2270 | , sdef->elements[0].isOptional ? sdef->elements[0].name : "" | |
2271 | , sdef->elements[0].isOptional ? ".ispresent() &&" : "" | |
2272 | , sdef->elements[0].name | |
2273 | , sdef->elements[0].isOptional ? "()" : "", sdef->elements[0].name | |
2274 | , sdef->elements[0].isOptional ? "()" : ""); | |
970ed795 EL |
2275 | } |
2276 | ||
2277 | ||
2278 | src = mputstr(src, | |
2279 | " }\n" /* end of loop */ | |
2280 | " } // exer\n"); | |
2281 | if (sdef->xerUseNilPossible) { | |
2282 | src = mputstr(src, " } // nil_attr\n"); | |
2283 | } | |
2284 | } | |
2285 | else /* not USE-ORDER */ | |
2286 | for ( /* continue with i */; i < sdef->nElements; ++i ) { | |
2287 | src = mputprintf(src, | |
2288 | " ec_1.set_msg(\"%s': \");\n" | |
2289 | , sdef->elements[i].dispname | |
2290 | ); | |
2291 | src = mputprintf(src, | |
af710487 | 2292 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor%s, p_indent+!omit_tag, %s);\n" |
970ed795 EL |
2293 | , sdef->elements[i].name, sdef->elements[i].typegen |
2294 | , sdef->xerUseNilPossible ? "| (p_td.xer_bits & USE_NIL)" : "" | |
af710487 | 2295 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0" |
970ed795 EL |
2296 | ); |
2297 | ||
2298 | if (sdef->xerEmbedValuesPossible) { | |
970ed795 | 2299 | src = mputprintf(src, |
af710487 | 2300 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n" |
3f84031e | 2301 | " %s%s%s emb_val->embval_index < field_%s%s.size_of()) {\n" |
2302 | " field_%s%s[emb_val->embval_index].XER_encode(\n" | |
af710487 | 2303 | " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" |
2304 | " ++emb_val->embval_index;\n" | |
970ed795 | 2305 | " }\n" |
3f84031e | 2306 | , sdef->elements[0].isOptional ? "field_" : "" |
2307 | , sdef->elements[0].isOptional ? sdef->elements[0].name : "" | |
2308 | , sdef->elements[0].isOptional ? ".ispresent() &&" : "" | |
2309 | , sdef->elements[0].name | |
2310 | , sdef->elements[0].isOptional ? "()" : "", sdef->elements[0].name | |
2311 | , sdef->elements[0].isOptional ? "()" : ""); | |
970ed795 EL |
2312 | } |
2313 | } /* next field when not USE-ORDER */ | |
2314 | ||
af710487 | 2315 | if (sdef->xerEmbedValuesPossible) { |
2316 | src = mputprintf(src, | |
2317 | " if (0 != emb_val) {\n" | |
3f84031e | 2318 | " if (%s%s%s emb_val->embval_index < field_%s%s.size_of()) {\n" |
af710487 | 2319 | " ec_1.set_msg(\"%s': \");\n" |
2320 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n" | |
2321 | " \"Too many EMBED-VALUEs specified: %%d (expected %%d or less)\",\n" | |
3f84031e | 2322 | " field_%s%s.size_of(), emb_val->embval_index);\n" |
af710487 | 2323 | " }\n" |
2324 | " delete emb_val;\n" | |
2325 | " }\n" | |
3f84031e | 2326 | , sdef->elements[0].isOptional ? "field_" : "" |
2327 | , sdef->elements[0].isOptional ? sdef->elements[0].name : "" | |
2328 | , sdef->elements[0].isOptional ? ".ispresent() &&" : "" | |
2329 | , sdef->elements[0].name, sdef->elements[0].isOptional ? "()" : "" | |
2330 | , sdef->elements[0].name, sdef->elements[0].name | |
2331 | , sdef->elements[0].isOptional ? "()" : ""); | |
af710487 | 2332 | } |
2333 | ||
970ed795 EL |
2334 | src = mputstr(src, " } // QN?\n"); |
2335 | ||
2336 | { | |
2337 | src = mputprintf(src, | |
2338 | " if (!omit_tag) {\n" | |
2339 | " if (sub_len) {\n" /* something was written, now an end tag */ | |
2340 | " if (is_indented && !(e_xer && (p_td.xer_bits & (HAS_1UNTAGGED | USE_QNAME)))) {\n" | |
2341 | " switch ((int)(e_xer && (p_td.xer_bits & USE_NIL))) {\n" | |
2342 | " case 1: {\n" | |
2343 | " const unsigned char *buf_end = p_buf.get_data() + (p_buf.get_len()-1);\n" | |
2344 | " if (buf_end[-1] != '>' || *buf_end != '\\n') break;\n" | |
2345 | /* else fall through */ | |
2346 | " }\n" | |
2347 | " case 0:\n" | |
2348 | " do_indent(p_buf, p_indent);\n" | |
2349 | " break;\n" | |
2350 | " }\n" | |
2351 | " }\n" | |
2352 | " p_buf.put_c('<');\n" | |
2353 | " p_buf.put_c('/');\n" | |
2354 | " if (e_xer) write_ns_prefix(p_td, p_buf);\n" | |
2355 | " p_buf.put_s((size_t)p_td.namelens[e_xer]-!is_indented, (cbyte*)p_td.names[e_xer]);\n" | |
2356 | " } else {\n" /* need to generate an empty element tag */ | |
2357 | " p_buf.increase_length(%s-1);\n" /* decrease length */ | |
2358 | " p_buf.put_s((size_t)2+is_indented, (cbyte*)\"/>\\n\");\n" | |
2359 | " }}\n" | |
2360 | , (sdef->xerUntaggedOne /*|| sdef->xerUseNil*/) ? "" : "-is_indented" | |
2361 | ); | |
2362 | } | |
2363 | src = mputstr(src, | |
2364 | " return (int)p_buf.get_len() - encoded_length;\n" | |
2365 | "}\n\n"); | |
2366 | ||
2367 | #ifndef NDEBUG | |
2368 | src = mputprintf(src, "// %s has%s%s%s%s%s%s%s%s%s\n" | |
2369 | "// written by %s in " __FILE__ " at %d\n" | |
2370 | , name | |
2371 | , (sdef->xerUntagged ? " UNTAGGED" : "") | |
2372 | , (sdef->xerUntaggedOne ? "1" : "") | |
2373 | , (sdef->xerUseNilPossible ? " USE_NIL?" : "") | |
2374 | , (sdef->xerUseOrderPossible ? " USE_ORDER?" : "") | |
2375 | , (sdef->xerUseQName ? " USE_QNAME" : "") | |
2376 | , (sdef->xerUseTypeAttr ? " USE_TYPE_ATTR" : "") | |
2377 | , (sdef->xerUseUnion ? " USE-UNION" : "") | |
2378 | , (sdef->xerHasNamespaces ? " namespace" : "") | |
2379 | , (sdef->xerEmbedValuesPossible ? " EMBED?" : "") | |
2380 | , __FUNCTION__, __LINE__ | |
2381 | ); | |
2382 | #endif | |
2383 | ||
2384 | src = mputprintf(src, /* XERSTUFF decodegen for record/SEQUENCE*/ | |
2385 | "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader," | |
feade998 | 2386 | " unsigned int p_flavor, unsigned int p_flavor2, embed_values_dec_struct_t*)\n" |
970ed795 | 2387 | "{\n" |
970ed795 EL |
2388 | /* Remove XER_LIST, XER_RECOF from p_flavor. This is not required |
2389 | * for is_exer (which tests another bit), but for subsequent code. */ | |
2390 | " int e_xer = is_exer(p_flavor);\n" | |
2391 | " int xerbits = p_td.xer_bits;\n" | |
2392 | " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n" | |
2393 | " const boolean omit_tag = e_xer && ((xerbits & (UNTAGGED|XER_ATTRIBUTE)) " | |
2394 | "|| (p_flavor & (USE_NIL|USE_TYPE_ATTR)));\n" | |
2395 | "%s" | |
feade998 | 2396 | " const boolean parent_tag = e_xer && ((p_flavor & USE_TYPE_ATTR)|| (p_flavor2 & USE_NIL_PARENT_TAG));\n" |
970ed795 EL |
2397 | " (void)parent_tag;\n" |
2398 | " p_flavor &= XER_MASK;\n" /* also removes "toplevel" bit */ | |
feade998 | 2399 | " p_flavor2 = XER_NONE;\n" /* Remove only bit: USE_NIL_PARENT_TAG (for now) */ |
970ed795 EL |
2400 | " int rd_ok, xml_depth=-1, type;\n" |
2401 | " {\n" /* scope for the error contexts */ | |
2402 | , name | |
2403 | , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0) | |
2404 | ? " boolean tag_closed = (p_flavor & PARENT_CLOSED) != 0;\n" : "") | |
2405 | /* tag_closed needed for non-attribute normal members only, | |
2406 | * or if EMBED-VALUES is possible, but isn't. */ | |
2407 | ); | |
2408 | ||
feade998 | 2409 | if (sdef->xerUseNilPossible) { src = mputstr(src, |
2410 | " boolean nil_attribute = FALSE;\n" | |
2411 | " boolean already_processed = FALSE;\n"); | |
2412 | } | |
970ed795 EL |
2413 | |
2414 | src = mputprintf(src, | |
2415 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" | |
2416 | " TTCN_EncDec_ErrorContext ec_1;\n" | |
2417 | " if (!omit_tag) for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" | |
2418 | " type = p_reader.NodeType();\n" | |
2419 | " if (type==XML_READER_TYPE_ELEMENT) {\n" | |
2420 | " verify_name(p_reader, p_td, e_xer);\n" | |
2421 | " xml_depth = p_reader.Depth();\n" | |
2422 | "%s" | |
2423 | " break;\n" | |
2424 | " }\n" | |
2425 | " }\n" | |
2426 | , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0) | |
2427 | ? " tag_closed = p_reader.IsEmptyElement();\n": "") | |
2428 | ); | |
2429 | ||
2430 | ||
2431 | if (sdef->xerUseQName) { | |
2432 | src = mputprintf(src, | |
2433 | " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n" | |
2434 | " if (p_td.xer_bits & XER_ATTRIBUTE) rd_ok = 1;\n" | |
2435 | " else for (rd_ok = p_reader.Read(); rd_ok == 1; rd_ok = p_reader.Read()) {\n" | |
2436 | " type = p_reader.NodeType();\n" | |
2437 | " if (type == XML_READER_TYPE_TEXT) break;\n" | |
2438 | " }\n" | |
2439 | " if (rd_ok==1) {\n" | |
2440 | " xmlChar *new_val = p_reader.NewValue();\n" | |
2441 | " xmlChar *v_npfx = (xmlChar*)strchr((char*)new_val, ':');\n" | |
2442 | " xmlChar *v_pfx;\n" | |
2443 | " if (v_npfx != NULL) {\n" | |
2444 | " *v_npfx++ = '\\0';\n" | |
2445 | " v_pfx = new_val;\n" | |
2446 | " }\n" | |
2447 | " else {\n" | |
2448 | " v_npfx = new_val;\n" | |
2449 | " v_pfx = NULL;\n" | |
2450 | " }\n" | |
2451 | " xmlChar *q_ns = p_reader.LookupNamespace(v_pfx);\n" | |
2452 | " if (q_ns) field_%s = (const char*)q_ns;\n" | |
2453 | " else field_%s = OMIT_VALUE;\n" | |
2454 | " field_%s = (const char*)v_npfx;\n" | |
2455 | " xmlFree(q_ns);\n" | |
2456 | " xmlFree(new_val);\n" | |
2457 | " }\n" | |
2458 | " } else {\n" | |
2459 | , sdef->elements[0].name | |
2460 | , sdef->elements[0].name | |
2461 | , sdef->elements[1].name | |
2462 | ); | |
2463 | } /* QName */ | |
2464 | ||
2465 | if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { | |
2466 | src = mputstr(src, "if (e_xer) {\n"); | |
2467 | } | |
2468 | ||
2469 | /* ******************************************************************** | |
2470 | * ATTRIBUTES | |
feade998 | 2471 | ***************************/ |
970ed795 EL |
2472 | if (num_attributes || sdef->xerUseNilPossible /* maybe QNAME too ? */) { |
2473 | size_t aaa; | |
970ed795 | 2474 | |
feade998 | 2475 | /* Prepare for attributes not present in the XML. |
970ed795 EL |
2476 | * Set all attributes with defaultForEmpty to the D-F-E value. |
2477 | * Set all optional components with ATTRIBUTE to omit. | |
2478 | * | |
2479 | * If EMBED-VALUES is possible, the first component can't be optional. | |
2480 | * The same is true for the USE-ORDER component. Hence start_at. */ | |
2481 | for (aaa = start_at; aaa < start_at + num_attributes; ++aaa) { | |
2482 | if (sdef->elements[aaa].xerAttribute) { /* "proper" ATTRIBUTE */ | |
2483 | src = mputprintf(src, | |
2484 | " if (%s_xer_.dfeValue) field_%s = " | |
2485 | "*static_cast<const %s*>(%s_xer_.dfeValue);\n" | |
2486 | , sdef->elements[aaa].typegen, sdef->elements[aaa].name | |
2487 | , sdef->elements[aaa].type , sdef->elements[aaa].typegen); | |
2488 | if (sdef->elements[aaa].isOptional) src = mputprintf(src, | |
2489 | " else field_%s = OMIT_VALUE;\n", sdef->elements[aaa].name); | |
2490 | } | |
2491 | else { /* must be the ANY-ATTRIBUTES */ | |
2492 | src = mputprintf(src, | |
af710487 | 2493 | " field_%s%s;\n" |
2494 | , sdef->elements[aaa].name | |
2495 | , sdef->elements[aaa].isOptional ? " = OMIT_VALUE" : ".set_size(0)"); | |
970ed795 EL |
2496 | } |
2497 | } | |
feade998 | 2498 | |
2499 | src = mputstr(src, " if (!omit_tag || parent_tag) {\n"); | |
970ed795 EL |
2500 | |
2501 | if (num_attributes==0 /* therefore sdef->xerUseNilPossible is true */ ) { | |
2502 | /* Only the "nil" attribute may be present. If there is no USE-NIL, | |
2503 | * then there can be no attributes at all. */ | |
2504 | src = mputstr(src, | |
2505 | " if (e_xer && (p_td.xer_bits & (USE_NIL|USE_TYPE_ATTR))) {\n"); | |
2506 | } | |
2507 | ||
2508 | if (aa_index > -1) src = mputstr(src, " size_t num_aa = 0;\n"); | |
2509 | if (sdef->xerUseNilPossible) { | |
2510 | src = mputstr(src, | |
2511 | " static const namespace_t *control_ns = p_td.my_module->get_controlns();\n"); | |
2512 | } | |
2513 | ||
2514 | src = mputstr(src, | |
feade998 | 2515 | " if(parent_tag && p_reader.NodeType() == XML_READER_TYPE_ATTRIBUTE) {\n" |
2516 | " rd_ok = p_reader.Ok();\n" | |
2517 | " } else {\n" | |
2518 | " rd_ok = p_reader.MoveToFirstAttribute();\n" | |
2519 | " }\n" | |
2520 | " for (; rd_ok==1 && " | |
970ed795 EL |
2521 | "p_reader.NodeType()==XML_READER_TYPE_ATTRIBUTE; " |
2522 | "rd_ok = p_reader.AdvanceAttribute()) {\n" | |
2523 | " if (p_reader.IsNamespaceDecl()) continue;\n"); | |
2524 | /* if the only attribute is ANY-ATTRIBUTE, it doesn't need attr_name */ | |
2525 | if (num_attributes==1 && aa_index!=-1 /*&& !sdef->xerUseNilPossible*/) {} | |
2526 | else { | |
2527 | src = mputstr(src, | |
2528 | " const char *attr_name = (const char*)p_reader.LocalName();\n" | |
2529 | " const char *ns_uri = (const char*)p_reader.NamespaceUri();\n"); | |
2530 | } | |
2531 | ||
2532 | if (sdef->xerUseNilPossible) { | |
2533 | src = mputprintf(src, | |
2534 | " const char *prefix = (const char*)p_reader.Prefix();\n" | |
2535 | /* prefix may be NULL, control_ns->px is never NULL or empty */ | |
2536 | " if (prefix && !strcmp(prefix, control_ns->px)\n" | |
2537 | " && !strcmp((const char*)p_reader.LocalName(), \"nil\")){\n" | |
2538 | " const char *value = (const char*)p_reader.Value();\n" | |
2539 | " if (!strcmp(value, \"1\") || !strcmp(value, \"true\")) {\n" | |
2540 | " field_%s = OMIT_VALUE;\n" | |
2541 | " nil_attribute = TRUE;\n" | |
2542 | /* found the "nil" attribute */ | |
2543 | " }\n" | |
2544 | " } else" | |
2545 | , sdef->elements[sdef->nElements-1].name); | |
2546 | } | |
2547 | ||
2548 | for (i = start_at; i < start_at + num_attributes; ++i) { | |
2549 | if (i == aa_index) continue; /* ANY_ATTR. is handled below */ | |
2550 | src = mputprintf(src, | |
2551 | " if (check_name(attr_name, %s_xer_, 1) && check_namespace(ns_uri, %s_xer_)) {\n" | |
2552 | " ec_1.set_msg(\"%s': \");\n" | |
feade998 | 2553 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), p_flavor2, 0);\n" |
970ed795 EL |
2554 | " } else" |
2555 | , sdef->elements[i].typegen, sdef->elements[i].typegen | |
2556 | , sdef->elements[i].dispname /* set_msg */ | |
2557 | , sdef->elements[i].name, sdef->elements[i].typegen | |
2558 | ); | |
2559 | } | |
feade998 | 2560 | |
2561 | if(sdef->xerUseNilPossible) { | |
2562 | src = mputprintf(src, | |
2563 | " if(p_td.xer_bits & USE_NIL) {\n" | |
2564 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | USE_NIL, p_flavor2 | USE_NIL_PARENT_TAG, 0);\n" | |
2565 | " already_processed = TRUE;\n" | |
d44e3c4f | 2566 | " break;\n" |
feade998 | 2567 | " } else" |
2568 | , sdef->elements[sdef->nElements-1].name | |
2569 | , sdef->elements[sdef->nElements-1].typegen | |
2570 | ); | |
2571 | } | |
970ed795 EL |
2572 | |
2573 | if (sdef->control_ns_prefix && !(num_attributes==1 && aa_index!=-1)) { | |
2574 | src = mputprintf(src, | |
2575 | " if (parent_tag && !strcmp(attr_name, \"type\") " | |
2576 | "&& !strcmp((const char*)p_reader.Prefix(), \"%s\")) {} else\n" | |
2577 | , sdef->control_ns_prefix); | |
2578 | /* xsi:type; already processed by parent with USE-UNION or USE-TYPE */ | |
2579 | } | |
2580 | ||
2581 | ||
2582 | if (aa_index >= 0) { | |
2583 | /* we are at a dangling else */ | |
2584 | src = mputprintf(src, | |
2585 | " {\n" | |
af710487 | 2586 | " TTCN_EncDec_ErrorContext ec_0(\"Attribute %%d: \", (int)num_aa);\n" |
2587 | " UNIVERSAL_CHARSTRING& new_elem = field_%s%s[num_aa++];\n" | |
970ed795 EL |
2588 | /* Construct the AnyAttributeFormat (X.693amd1, 18.2.6) */ |
2589 | " TTCN_Buffer aabuf;\n" | |
2590 | " const xmlChar *x_name = p_reader.LocalName();\n" | |
2591 | " const xmlChar *x_val = p_reader.Value();\n" | |
2592 | " const xmlChar *x_uri = p_reader.NamespaceUri();\n" | |
2593 | " if (%s_xer_.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n" | |
2594 | " check_namespace_restrictions(%s_xer_, (const char*)x_uri);\n" | |
2595 | " }\n" | |
2596 | /* We don't care about p_reader.Prefix() */ | |
2597 | /* Using strlen to count bytes */ | |
2598 | " aabuf.put_s(x_uri ? strlen((const char*)x_uri) : 0, x_uri);\n" | |
2599 | " if (x_uri && *x_uri) aabuf.put_c(' ');\n" | |
2600 | " aabuf.put_s(x_name ? strlen((const char*)x_name) : 0, x_name);\n" | |
2601 | " aabuf.put_c('=');\n" | |
2602 | " aabuf.put_c('\"');\n" | |
2603 | " aabuf.put_s(x_val ? strlen((const char*)x_val) : 0, x_val);\n" | |
2604 | " aabuf.put_c('\"');\n" | |
2605 | " new_elem.decode_utf8(aabuf.get_len(), aabuf.get_data());\n" | |
2606 | " } \n" | |
2607 | , sdef->elements[aa_index].name | |
af710487 | 2608 | , sdef->elements[aa_index].isOptional ? "()" : "" |
970ed795 EL |
2609 | , sdef->elements[aa_index].typegen, sdef->elements[aa_index].typegen |
2610 | ); | |
2611 | } | |
2612 | else { | |
2613 | /* we are at a dangling else */ | |
2614 | src = mputstr(src, " {\n"); | |
2615 | if (sdef->control_ns_prefix) { | |
2616 | src = mputprintf(src, | |
2617 | // Lastly check for the xsi:schemaLocation attribute, this does not | |
2618 | // affect TTCN-3, but it shouldn't cause a DTE | |
2619 | " if (!p_reader.LocalName() || strcmp((const char*)p_reader.LocalName(), \"schemaLocation\") ||\n" | |
2620 | " !p_reader.Prefix() || strcmp((const char*)p_reader.Prefix(), \"%s\"))\n" | |
2621 | , sdef->control_ns_prefix); | |
2622 | } | |
2623 | src = mputstr(src, | |
2624 | " {\n" | |
2625 | " ec_0.set_msg(\" \"); ec_1.set_msg(\" \");\n" /* we have no component */ | |
2626 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, " | |
2627 | "\"Unexpected attribute '%s', ns '%s'\", attr_name, ns_uri ? ns_uri : \"\");\n" | |
2628 | " }\n" | |
2629 | " }\n"); | |
2630 | } | |
2631 | src = mputstr(src, " }\n"); /* for */ | |
2632 | ||
2633 | for (i = start_at; i < start_at + num_attributes; ++i) { | |
2634 | if (sdef->elements[i].isOptional) continue; /* allowed to be missing */ | |
2635 | src = mputprintf(src, " if (!field_%s.is_bound()) " | |
2636 | "TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, " | |
2637 | "\"Missing attribute '%s'\");\n" | |
2638 | , sdef->elements[i].name, sdef->elements[i].dispname); | |
2639 | } | |
2640 | ||
2641 | if (num_attributes==0) src = mputstr(src, " }\n"); /* if USE_NIL or USE_TYPE_ATTR */ | |
2642 | src = mputstr(src, " }\n"); /* process (attributes) in (own or parent) tag */ | |
2643 | } /* * * * * * * * * end if(attributes...) * * * * * * * * * * * * */ | |
2644 | ||
d44e3c4f | 2645 | src = mputprintf(src, |
2646 | " if ((!omit_tag || parent_tag) && !p_reader.IsEmptyElement()%s) " | |
2647 | "rd_ok = p_reader.Read();\n" | |
2648 | , sdef->xerUseNilPossible ? " && !already_processed" : ""); | |
970ed795 EL |
2649 | |
2650 | if (sdef->xerEmbedValuesPossible && num_attributes==0) { | |
2651 | /* EMBED-VALUES possible, but isn't: the first component is a non-special | |
2652 | * record of strings. This means there are no attributes, unless | |
2653 | * the first component is an ATTRIBUTE or ANY-ATTRIBUTES. */ | |
2654 | src = mputprintf(src, | |
2655 | " if (!(p_td.xer_bits & EMBED_VALUES)) {\n" | |
2656 | " ec_1.set_msg(\"%s': \");\n" | |
2657 | " field_%s.XER_decode(%s_xer_, p_reader, " | |
feade998 | 2658 | "p_flavor | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : XER_NONE), p_flavor2, 0);\n" |
970ed795 EL |
2659 | " }\n" |
2660 | , sdef->elements[0].dispname | |
2661 | , sdef->elements[0].name, sdef->elements[0].typegen | |
2662 | ); | |
2663 | } | |
2664 | ||
2665 | if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { | |
2666 | src = mputstr(src, | |
2667 | "} else {\n" /* now the non-EXER processing of (would-be) attributes */ | |
2668 | " if (!p_reader.IsEmptyElement()) p_reader.Read();\n" | |
2669 | ); | |
2670 | } | |
2671 | ||
2672 | if (sdef->xerUseOrderPossible) { | |
2673 | src = mputstr(src, | |
2674 | " if (e_xer && p_td.xer_bits & USE_ORDER) ; else {"); | |
2675 | } | |
2676 | ||
2677 | if (start_at + num_attributes > 0) | |
2678 | { | |
2679 | /* No attributes nor USE-NIL: | |
2680 | * Just decode the specials and would-be attributes. */ | |
2681 | ||
2682 | // FIXME: WTF is this? | |
2683 | //if (sdef->xerEmbedValuesPossible) { | |
2684 | // /* Only decode the first member if it really is EMBED-VALUES */ | |
2685 | // src = mputprintf(src, "if (p_td.xer_bits & EMBED_VALUES) "); | |
2686 | //} | |
2687 | for (i = 0; i < start_at + num_attributes; ++i) { | |
2688 | /* Decode the field */ | |
2689 | src = mputprintf(src, | |
2690 | " {\n" | |
2691 | " ec_1.set_msg(\"%s': \");\n" | |
feade998 | 2692 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), p_flavor2, 0);\n" |
970ed795 EL |
2693 | " }\n" |
2694 | , sdef->elements[i].dispname | |
2695 | , sdef->elements[i].name, sdef->elements[i].typegen | |
2696 | ); | |
2697 | } /* next field */ | |
2698 | ||
2699 | if (sdef->xerUseOrderPossible) { | |
2700 | src = mputstr(src, " }\n"); | |
2701 | } | |
2702 | } | |
2703 | ||
2704 | if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { | |
2705 | src = mputstr(src, "}\n"); | |
2706 | } | |
af710487 | 2707 | |
2708 | if (sdef->xerEmbedValuesPossible) { | |
2709 | src = mputprintf(src, | |
2710 | " embed_values_dec_struct_t* emb_val = 0;\n" | |
2711 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" | |
2712 | " emb_val = new embed_values_dec_struct_t;\n" | |
a38c6d4c | 2713 | /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated |
2714 | * record of universal charstring, so it needs a cast to avoid a compilation error */ | |
3f84031e | 2715 | " emb_val->embval_array%s = (PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s%s;\n" |
a38c6d4c | 2716 | " emb_val->embval_array%s = NULL;\n" |
af710487 | 2717 | " emb_val->embval_index = 0;\n" |
3f84031e | 2718 | " field_%s%s.set_size(0);\n" |
a38c6d4c | 2719 | " }\n" |
2720 | , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg" | |
2721 | , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : "" | |
2722 | , sdef->elements[0].name | |
3f84031e | 2723 | , sdef->elements[0].isOptional ? "()" : "" |
a38c6d4c | 2724 | , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt" |
3f84031e | 2725 | , sdef->elements[0].name |
2726 | , sdef->elements[0].isOptional ? "()" : ""); | |
af710487 | 2727 | } |
970ed795 EL |
2728 | |
2729 | if (sdef->xerUseOrderPossible) { | |
2730 | size_t begin = start_at + num_attributes; /* first non-attribute */ | |
2731 | size_t end = sdef->nElements; | |
2732 | size_t n_optionals = 0, n_embed; | |
2733 | int max_ordered = sdef->nElements - start_at - num_attributes; | |
2734 | int min_ordered = max_ordered - n_opt_elements; | |
2735 | if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */ | |
2736 | begin = sdef->nElements; | |
2737 | end = sdef->totalElements; | |
2738 | } | |
2739 | n_embed = end - begin; | |
2740 | ||
2741 | src = mputstr(src, | |
2742 | " if (e_xer && (p_td.xer_bits & USE_ORDER)) {\n" | |
2743 | ); | |
2744 | for (i = begin; i < end; ++i) { | |
2745 | if (sdef->elements[i].isOptional) { | |
2746 | src = mputprintf(src, " field_%s = OMIT_VALUE;\n", | |
2747 | sdef->elements[i].name); | |
2748 | ++n_optionals; | |
2749 | } | |
2750 | } | |
2751 | ||
970ed795 EL |
2752 | if (sdef->xerUseNilPossible) { /* USE-NIL and USE-ORDER */ |
2753 | src = mputprintf(src, | |
2754 | " if (nil_attribute) field_%s.set_size(0);\n else" | |
2755 | , sdef->elements[uo].name); | |
2756 | } | |
2757 | ||
2758 | src = mputprintf(src, | |
2759 | " {\n" | |
2760 | " field_%s.set_size(0);\n" | |
3abe9331 | 2761 | " if (!tag_closed) {\n" /* Nothing to order if there are no child elements */ |
970ed795 | 2762 | " int e_val, num_seen = 0, *seen_f = new int[%lu];\n" |
970ed795 EL |
2763 | , sdef->elements[uo].name |
2764 | , (unsigned long)(n_embed) | |
af710487 | 2765 | ); |
2766 | if (sdef->xerEmbedValuesPossible) { | |
2767 | // The index of the latest embedded value can change outside of this function | |
2768 | // (if the field is a untagged record of), in this case the next value should | |
2769 | // be ignored, as it's already been handled by the record of | |
2770 | src = mputstr(src, " int last_embval_index = 0;\n"); | |
2771 | } | |
2772 | src = mputprintf(src, | |
3abe9331 | 2773 | " bool early_exit = false;\n" |
af710487 | 2774 | " for (int i=0; i < %lu; ++i) {\n" |
2775 | " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" | |
970ed795 EL |
2776 | , (unsigned long)(n_embed)); |
2777 | ||
2778 | if (sdef->xerEmbedValuesPossible) { | |
2779 | /* read and store embedValues text if present */ | |
2780 | src = mputprintf(src, | |
af710487 | 2781 | " if (0 != emb_val && p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" |
970ed795 | 2782 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" |
3f84031e | 2783 | " field_%s%s[emb_val->embval_index] = emb_ustr;\n" |
970ed795 | 2784 | " }\n" |
3f84031e | 2785 | , sdef->elements[0].name |
2786 | , sdef->elements[0].isOptional ? "()" : ""); | |
970ed795 EL |
2787 | } |
2788 | ||
2789 | src = mputstr(src, | |
2790 | " type = p_reader.NodeType();\n" | |
2791 | " if (type==XML_READER_TYPE_ELEMENT) break;\n" | |
3abe9331 | 2792 | " if (type == XML_READER_TYPE_END_ELEMENT) {\n" |
2793 | " early_exit = true;\n" | |
2794 | " break;\n" | |
2795 | " }\n" | |
970ed795 | 2796 | " }\n" |
3abe9331 | 2797 | " if (rd_ok != 1 || early_exit) break;\n" |
970ed795 | 2798 | " const char * x_name = (const char*)p_reader.LocalName();\n" /* Name or LocalName ? */); |
af710487 | 2799 | |
2800 | if (sdef->xerEmbedValuesPossible) { | |
2801 | src = mputstr(src, | |
2802 | " if (0 != emb_val) {\n" | |
2803 | " if (last_embval_index == emb_val->embval_index) {\n" | |
2804 | " ++emb_val->embval_index;\n" | |
2805 | " }\n" | |
2806 | " last_embval_index = emb_val->embval_index;\n" | |
2807 | " }\n"); | |
2808 | } | |
970ed795 EL |
2809 | |
2810 | /* * * * * code for USE-ORDER * * * * */ | |
2811 | ||
2812 | for (i = begin; i < end; ++i) { | |
2813 | // Check non-anyElement fields first | |
2814 | if (!(sdef->elements[i].xerAnyKind & ANY_ELEM_BIT)) { | |
2815 | src = mputprintf(src, | |
2816 | " if (check_name(x_name, %s_xer_, 1)) {\n" | |
2817 | " ec_1.set_msg(\"%s': \");\n" | |
feade998 | 2818 | " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, p_flavor2, %s);\n" |
970ed795 EL |
2819 | , sdef->elements[i].typegen |
2820 | , sdef->elements[i].dispname | |
970ed795 EL |
2821 | , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name) |
2822 | , (sdef->xerUseNilPossible ? "()." : "") | |
2823 | , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") | |
2824 | , (sdef->xerUseNilPossible ? "()" : "") | |
2825 | , sdef->elements[i].typegen | |
af710487 | 2826 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0" |
970ed795 EL |
2827 | ); |
2828 | src = mputprintf(src, | |
af710487 | 2829 | " field_%s[i] = e_val = %s::of_type::%s;\n" |
2830 | , sdef->elements[uo].name | |
2831 | , sdef->elements[uo].typegen, sdef->elements[i].name); | |
970ed795 EL |
2832 | src = mputstr(src, " }\n else"); |
2833 | } | |
2834 | } | |
2835 | src = mputstr(src, | |
2836 | " {\n" | |
2837 | " boolean any_found = false;\n" | |
2838 | " if (!any_found)"); | |
2839 | for (i = begin; i < end; ++i) { | |
2840 | // Check anyElement fields after all other fields | |
2841 | if (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT) { | |
2842 | src = mputstr(src, " {\n"); | |
2843 | src = mputprintf(src, | |
2844 | " e_val = %s::of_type::%s;\n" | |
2845 | , sdef->elements[uo].typegen, sdef->elements[i].name); | |
2846 | src = mputprintf(src, | |
2847 | " boolean next_any = false;\n" | |
2848 | " for (int d_f = 0; d_f < num_seen; ++d_f) {\n" | |
2849 | " if (e_val == seen_f[d_f]) {\n" | |
2850 | " next_any = true;\n" | |
2851 | " }\n" | |
2852 | " }\n" | |
2853 | " if (!next_any) {\n" | |
2854 | " ec_1.set_msg(\"%s': \");\n" | |
feade998 | 2855 | " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, p_flavor2, 0);\n" |
970ed795 EL |
2856 | " field_%s[i] = e_val;\n" |
2857 | " any_found = true;\n" | |
2858 | " }\n" | |
2859 | " }\n" | |
2860 | " if (!any_found)" | |
2861 | , sdef->elements[i].dispname | |
2862 | , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name) | |
2863 | , (sdef->xerUseNilPossible ? "()." : "") | |
2864 | , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") | |
2865 | , (sdef->xerUseNilPossible ? "()" : "") | |
2866 | , sdef->elements[i].typegen, sdef->elements[uo].name | |
2867 | ); | |
2868 | } | |
2869 | } | |
2870 | ||
2871 | src = mputstr(src, | |
3abe9331 | 2872 | " {\n" /* take care of the dangling else */ |
2873 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n" | |
2874 | " \"Bad XML tag '%s' instead of a valid field\", x_name);\n" | |
2875 | " break;\n" | |
2876 | " }\n" | |
970ed795 EL |
2877 | " }\n" |
2878 | " for (int d_f = 0; d_f < num_seen; ++d_f)\n" | |
2879 | " if (e_val == seen_f[d_f])\n" | |
2880 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Duplicate field\");\n" | |
2881 | " seen_f[num_seen++] = e_val;\n" | |
2882 | " } // next i\n"); | |
2883 | ||
2884 | if (sdef->xerEmbedValuesPossible) { | |
2885 | /* read and store embedValues text if present */ | |
2886 | src = mputprintf(src, | |
af710487 | 2887 | " if (0 != emb_val) {\n" |
2888 | " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" | |
2889 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" | |
3f84031e | 2890 | " field_%s%s[emb_val->embval_index] = emb_ustr;\n" |
af710487 | 2891 | " }\n" |
2892 | " if (last_embval_index == emb_val->embval_index) {\n" | |
2893 | " ++emb_val->embval_index;\n" | |
2894 | " }\n" | |
970ed795 | 2895 | " }\n" |
3f84031e | 2896 | , sdef->elements[0].name |
2897 | , sdef->elements[0].isOptional ? "()" : ""); | |
970ed795 EL |
2898 | } |
2899 | ||
2900 | src = mputprintf(src, | |
2901 | " delete [] seen_f;\n" | |
2902 | " }\n" | |
2903 | " int n_collected = field_%s.size_of();\n" | |
2904 | " if (p_td.xer_bits & USE_NIL) {\n" | |
2905 | " ;\n" | |
2906 | " } else {\n" | |
2907 | " if (n_collected < %d || n_collected > %d) {\n" | |
2908 | " ec_0.set_msg(\" \");\n" | |
2909 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Wrong number of elements\");\n" | |
2910 | " }\n" | |
2911 | " }\n" | |
3abe9331 | 2912 | " } // !tag_closed\n" |
970ed795 EL |
2913 | " } else { // !uo\n" |
2914 | , sdef->elements[uo].dispname | |
2915 | , min_ordered, max_ordered | |
2916 | ); | |
2917 | } /* end if(UseOrder possible) */ | |
2918 | ||
2919 | /* * * * * non-UseOrder code always written, executed when * * * * | |
2920 | * * * * * UseOrder not possible or in the "else" clause * * * * */ | |
2921 | ||
2922 | if (sdef->xerUseNilPossible) { | |
2923 | /* value absent, nothing more to do */ | |
2924 | src = mputstr(src, | |
2925 | " if (nil_attribute) {\n" | |
2926 | " p_reader.MoveToElement();\n" | |
2927 | " } else {\n"); | |
2928 | } | |
af710487 | 2929 | if (sdef->xerEmbedValuesPossible) { |
2930 | // The index of the latest embedded value can change outside of this function | |
2931 | // (if the field is a untagged record of), in this case the next value should | |
2932 | // be ignored, as it's already been handled by the record of | |
2933 | // Omitted fields can also reset this value | |
2934 | src = mputstr(src, " int last_embval_index = 0;\n"); | |
2935 | } | |
970ed795 EL |
2936 | /* for all the non-attribute fields... */ |
2937 | for (i = start_at + num_attributes; i < sdef->nElements; ++i) { | |
2938 | if (sdef->xerEmbedValuesPossible) { | |
2939 | /* read and store embedValues text if present */ | |
2940 | src = mputprintf(src, | |
af710487 | 2941 | " if (0 != emb_val) {\n" |
2942 | " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" | |
2943 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" | |
3f84031e | 2944 | " field_%s%s[emb_val->embval_index] = emb_ustr;\n" |
af710487 | 2945 | " }\n" |
2946 | " if (last_embval_index == emb_val->embval_index) {\n" | |
2947 | " ++emb_val->embval_index;\n" | |
2948 | " }\n" | |
2949 | " last_embval_index = emb_val->embval_index;\n" | |
970ed795 | 2950 | " }\n" |
3f84031e | 2951 | , sdef->elements[0].name |
2952 | , sdef->elements[0].isOptional ? "()" : ""); | |
970ed795 EL |
2953 | } |
2954 | /* The DEFAULT-FOR-EMPTY member can not be involved with EMBED-VALUES, | |
2955 | * so we can use the same pattern: optional "if(...) else" before {} | |
2956 | * XXX check with single-element record where nElements-1 == 0 !! */ | |
2957 | if (sdef->kind == RECORD && i == sdef->nElements-1) { | |
2958 | src = mputprintf(src, | |
2959 | " if (e_xer && p_td.dfeValue && p_reader.IsEmptyElement()) {\n" | |
2960 | " field_%s = *static_cast<const %s*>(p_td.dfeValue);\n" | |
2961 | " }\n" | |
feade998 | 2962 | " else%s" |
2963 | , sdef->elements[i].name, sdef->elements[i].type | |
2964 | , sdef->xerUseNilPossible ? " if (!already_processed)" : ""); | |
970ed795 EL |
2965 | } |
2966 | /* Decode the field */ | |
2967 | src = mputprintf(src, | |
2968 | " {\n" | |
2969 | " ec_1.set_msg(\"%s': \");\n" | |
2970 | , sdef->elements[i].dispname); | |
2971 | ||
2972 | if ( (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT) | |
2973 | && !strcmp(sdef->elements[i].type,"UNIVERSAL_CHARSTRING") ) { | |
2974 | // In case the field is an optional anyElement -> check if it should be omitted | |
2975 | if (sdef->elements[i].isOptional) { | |
2976 | src = mputprintf(src, | |
2977 | " if (field_%s.XER_check_any_elem(p_reader, \"%s\", tag_closed))\n " | |
2978 | , sdef->elements[i].name | |
2979 | , (i == sdef->nElements - 1) ? "NULL" : sdef->elements[i + 1].name); | |
2980 | } else { | |
2981 | // If the record is emptyElement, there's no way it will have an anyElement field | |
2982 | src = mputstr(src, " if (tag_closed) p_reader.Read(); \n"); | |
2983 | } | |
2984 | } | |
2985 | ||
2986 | src = mputprintf(src, | |
2987 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor" | |
feade998 | 2988 | " | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : XER_NONE), p_flavor2, %s);\n" |
970ed795 | 2989 | " }\n" |
af710487 | 2990 | , sdef->elements[i].name, sdef->elements[i].typegen |
2991 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0"); | |
2992 | if (sdef->xerEmbedValuesPossible) { | |
2993 | src = mputprintf(src, | |
2994 | " if (!field_%s.is_present()) {\n" | |
2995 | // there was no new element, the last embedded value is for the next field | |
2996 | // (or the end of the record if this is the last field) | |
2997 | " last_embval_index = -1;\n" | |
2998 | " }\n" | |
2999 | , sdef->elements[i].name); | |
3000 | } | |
970ed795 EL |
3001 | } /* next field */ |
3002 | ||
970ed795 EL |
3003 | if (sdef->xerEmbedValuesPossible) { |
3004 | /* read and store embedValues text if present */ | |
3005 | src = mputprintf(src, | |
af710487 | 3006 | " if (0 != emb_val) {\n" |
3007 | " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" | |
3008 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" | |
3f84031e | 3009 | " field_%s%s[emb_val->embval_index] = emb_ustr;\n" |
af710487 | 3010 | " }\n" |
3011 | " if (last_embval_index == emb_val->embval_index) {\n" | |
3012 | " ++emb_val->embval_index;\n" | |
3013 | " }\n" | |
970ed795 | 3014 | " }\n" |
3f84031e | 3015 | , sdef->elements[0].name |
3016 | , sdef->elements[0].isOptional ? "()" : ""); | |
af710487 | 3017 | } |
3018 | ||
3019 | if (sdef->xerUseNilPossible) { | |
3020 | src = mputstr(src, " } // use_nil\n"); | |
970ed795 EL |
3021 | } |
3022 | ||
af710487 | 3023 | if (sdef->xerUseOrderPossible) { |
3024 | src = mputstr(src, " } // uo\n"); | |
3025 | } | |
3026 | ||
970ed795 | 3027 | if (sdef->xerEmbedValuesPossible) { |
970ed795 | 3028 | src = mputprintf(src, |
3f84031e | 3029 | "%s" |
af710487 | 3030 | " if (0 != emb_val) {\n" |
970ed795 | 3031 | " %s::of_type empty_string(\"\");\n" |
af710487 | 3032 | " for (int j_j = 0; j_j < emb_val->embval_index; ++j_j) {\n" |
3f84031e | 3033 | " if (!field_%s%s[j_j].is_bound()) {\n" |
3034 | " field_%s%s[j_j] = empty_string;\n" | |
3035 | " }%s%s%s%s" | |
970ed795 | 3036 | " }\n" |
af710487 | 3037 | " delete emb_val;\n" |
3038 | " }\n" | |
3f84031e | 3039 | , sdef->elements[0].isOptional ? " bool all_unbound = true;\n" : "" |
970ed795 EL |
3040 | , sdef->elements[0].type |
3041 | , sdef->elements[0].name | |
3f84031e | 3042 | , sdef->elements[0].isOptional ? "()" : "" |
970ed795 | 3043 | , sdef->elements[0].name |
3f84031e | 3044 | , sdef->elements[0].isOptional ? "()" : "" |
3045 | , sdef->elements[0].isOptional ? " else if(field_" : "\n" | |
3046 | , sdef->elements[0].isOptional ? sdef->elements[0].name : "" | |
3047 | , sdef->elements[0].isOptional ? "()" : "" | |
3048 | , sdef->elements[0].isOptional ? "[j_j] != empty_string) {\n all_unbound = false;\n }\n" : "" | |
970ed795 | 3049 | ); |
3f84031e | 3050 | |
3051 | if(sdef->elements[0].isOptional) { | |
3052 | src = mputprintf(src, | |
3053 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && all_unbound) {\n" | |
3054 | " field_%s = OMIT_VALUE;\n" | |
3055 | " }\n" | |
3056 | , sdef->elements[0].name | |
3057 | ); | |
3058 | } | |
970ed795 EL |
3059 | } |
3060 | ||
970ed795 EL |
3061 | if (sdef->xerUseQName) { |
3062 | src = mputstr(src, " } // qn\n"); | |
3063 | } | |
3064 | ||
3065 | src = mputstr(src, | |
3abe9331 | 3066 | " } // errorcontext\n"); /* End scope for error context objects */ |
3067 | ||
3068 | /* Check if every non-optional field has been set */ | |
3069 | for (i = 0; i < sdef->nElements; ++i) { | |
3070 | if (!sdef->elements[i].isOptional) { | |
3071 | src = mputprintf(src, | |
3072 | " if (!field_%s.is_bound()) {\n" | |
3073 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,\n" | |
3074 | " \"No data found for non-optional field '%s'\");\n" | |
3075 | " }\n" | |
3076 | , sdef->elements[i].name, sdef->elements[i].dispname); | |
3077 | } | |
3078 | } | |
3079 | src = mputstr(src, | |
970ed795 EL |
3080 | " if (!omit_tag) {\n" |
3081 | " int current_depth;\n" | |
3082 | " for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n" | |
3083 | " type = p_reader.NodeType();\n" | |
3084 | " if ((current_depth = p_reader.Depth()) > xml_depth) {\n" | |
3085 | " if (XML_READER_TYPE_ELEMENT == type) {\n" | |
3086 | /* An element deeper than our start tag has not been processed */ | |
3087 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG,\n" | |
3088 | " \"Unprocessed XML tag `%s'\", (const char *)p_reader.Name());\n" | |
3089 | " }\n" | |
3090 | " continue;\n" | |
3091 | " }\n" | |
3092 | " else if (current_depth == xml_depth) {\n" | |
3093 | " if (XML_READER_TYPE_ELEMENT == type) {\n" | |
3094 | " verify_name(p_reader, p_td, e_xer);\n" | |
3095 | " if (p_reader.IsEmptyElement()) {\n" | |
3096 | " p_reader.Read();\n" /* advance one more time */ | |
3097 | " break;\n" | |
3098 | " }\n" | |
3099 | " }\n" | |
3100 | " else if (XML_READER_TYPE_END_ELEMENT == type) {\n" | |
3101 | " verify_end(p_reader, p_td, xml_depth, e_xer);\n" | |
3102 | " rd_ok = p_reader.Read();\n" | |
3103 | " break;\n" | |
3104 | " }\n" | |
3105 | " }\n" | |
3106 | " else break;" /* depth is less, we are in trouble... */ | |
3107 | " }\n" | |
3108 | " }\n" | |
3109 | " return 1;\n}\n\n"); | |
3110 | ||
3111 | *pdef = def; | |
3112 | *psrc = src; | |
3113 | } | |
3114 | ||
3115 | void defRecordClass1(const struct_def *sdef, output_struct *output) | |
3116 | { | |
3117 | size_t i; | |
3118 | size_t mandatory_fields_count; | |
3119 | const char *name = sdef->name, *dispname = sdef->dispname; | |
3120 | const char* kind_str = sdef->kind == SET ? "set" : "record"; | |
3121 | char *def = NULL, *src = NULL; | |
3122 | boolean ber_needed = sdef->isASN1 && enable_ber(); | |
3123 | boolean raw_needed = sdef->hasRaw && enable_raw(); | |
3124 | boolean text_needed = sdef->hasText && enable_text(); | |
3125 | boolean xer_needed = sdef->hasXer && enable_xer(); | |
3126 | boolean json_needed = sdef->hasJson && enable_json(); | |
3127 | ||
3128 | /* class declaration code */ | |
3129 | output->header.class_decls = mputprintf(output->header.class_decls, | |
3130 | "class %s;\n", name); | |
3131 | ||
3132 | if (sdef->nElements <= 0) { | |
3133 | defEmptyRecordClass(sdef, output); | |
3134 | return; | |
3135 | } | |
3136 | ||
3137 | /* class definition and source code */ | |
3138 | if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) { | |
3139 | def=mputprintf | |
3140 | (def, | |
3141 | #ifndef NDEBUG | |
3142 | "// written by %s in " __FILE__ " at line %d\n" | |
3143 | #endif | |
3144 | "class %s : public Base_Type {\n" | |
3145 | #ifndef NDEBUG | |
3146 | , __FUNCTION__, __LINE__ | |
3147 | #endif | |
3148 | , name); | |
3149 | } else { | |
3150 | def=mputprintf(def, "class %s {\n", name); | |
3151 | } | |
3152 | ||
970ed795 EL |
3153 | for (i = 0; i < sdef->nElements; i++) { |
3154 | if(sdef->elements[i].isOptional) | |
3155 | def = mputprintf(def, " OPTIONAL<%s> field_%s;\n", | |
3156 | sdef->elements[i].type, | |
3157 | sdef->elements[i].name); | |
3158 | else | |
3159 | def = mputprintf(def, " %s field_%s;\n", | |
3160 | sdef->elements[i].type, sdef->elements[i].name); | |
3161 | } | |
970ed795 EL |
3162 | |
3163 | /* default constructor */ | |
3164 | def = mputprintf(def, "public:\n" | |
3165 | " %s();\n", name); | |
3166 | src = mputprintf(src, "%s::%s()\n" | |
3167 | "{\n" | |
970ed795 EL |
3168 | "}\n\n", name, name); |
3169 | ||
3170 | /* constructor by fields */ | |
3171 | def = mputprintf(def, " %s(", name); | |
3172 | src = mputprintf(src, "%s::%s(", name, name); | |
3173 | ||
3174 | for (i = 0; i < sdef->nElements; i++) { | |
3175 | char *tmp = NULL; | |
3176 | if (i > 0) tmp = mputstr(tmp, ",\n "); | |
3177 | if (sdef->elements[i].isOptional) | |
3178 | tmp = mputprintf | |
3179 | (tmp, | |
3180 | "const OPTIONAL<%s>& par_%s", | |
3181 | sdef->elements[i].type, sdef->elements[i].name); | |
3182 | else | |
3183 | tmp = mputprintf | |
3184 | (tmp, | |
3185 | "const %s& par_%s", | |
3186 | sdef->elements[i].type, sdef->elements[i].name); | |
3187 | def = mputstr(def, tmp); | |
3188 | src = mputstr(src, tmp); | |
3189 | Free(tmp); | |
3190 | } | |
3191 | def = mputstr(def, ");\n"); | |
3192 | src = mputstr(src, ")\n" | |
3193 | " : "); | |
3194 | for (i = 0; i < sdef->nElements; i++) { | |
3195 | if (i > 0) src = mputstr(src, ",\n"); | |
3196 | src = mputprintf(src, " field_%s(par_%s)", sdef->elements[i].name, | |
3197 | sdef->elements[i].name); | |
3198 | } | |
3199 | src = mputstr(src, "\n" | |
3200 | "{\n" | |
970ed795 EL |
3201 | "}\n\n"); |
3202 | ||
3203 | /* copy constructor */ | |
3204 | def = mputprintf(def, " %s(const %s& other_value);\n", name, name); | |
3205 | src = mputprintf(src, "%s::%s(const %s& other_value)\n" | |
3206 | "{\n" | |
3207 | "if(!other_value.is_bound()) " | |
feade998 | 3208 | "TTCN_error(\"Copying an unbound value of type %s.\");\n", |
970ed795 EL |
3209 | name, name, name, dispname); |
3210 | for (i = 0; i < sdef->nElements; i++) { | |
3211 | src = mputprintf(src, | |
3212 | "if (other_value.%s().is_bound()) field_%s = other_value.%s();\n" | |
3213 | "else field_%s.clean_up();\n", | |
3214 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name, | |
3215 | sdef->elements[i].name); | |
3216 | } | |
3217 | src = mputstr(src, "}\n\n"); | |
3218 | ||
3219 | /* not a component */ | |
3220 | def = mputstr(def, " inline boolean is_component() { return FALSE; }\n"); | |
3221 | ||
3222 | /* clean_up */ | |
3223 | def = mputstr(def, " void clean_up();\n"); | |
3224 | src = mputprintf(src, "void %s::clean_up()\n" | |
3225 | "{\n", name); | |
3226 | for (i = 0; i < sdef->nElements; i++) { | |
3227 | src = mputprintf(src, | |
3228 | "field_%s.clean_up();\n", sdef->elements[i].name); | |
3229 | } | |
3230 | src = mputstr(src, | |
970ed795 EL |
3231 | "}\n\n"); |
3232 | ||
3233 | /* = operator */ | |
3234 | def = mputprintf(def, " %s& operator=(const %s& other_value);\n", name, name); | |
3235 | src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n" | |
3236 | "{\n" | |
3237 | "if (this != &other_value) {\n" | |
3238 | " if(!other_value.is_bound()) " | |
feade998 | 3239 | "TTCN_error(\"Assignment of an unbound value of type %s.\");\n", |
970ed795 EL |
3240 | name, name, name, dispname); |
3241 | for (i = 0; i < sdef->nElements; i++) { | |
3242 | src = mputprintf(src, | |
3243 | " if (other_value.%s().is_bound()) field_%s = other_value.%s();\n" | |
3244 | " else field_%s.clean_up();\n", | |
3245 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name, | |
3246 | sdef->elements[i].name); | |
3247 | } | |
3248 | src = mputstr(src, | |
3249 | "}\n" | |
3250 | "return *this;\n" | |
3251 | "}\n\n"); | |
3252 | ||
3253 | /* == operator */ | |
3254 | def = mputprintf(def, " boolean operator==(const %s& other_value) " | |
3255 | "const;\n", name); | |
3256 | src = mputprintf(src, | |
3257 | "boolean %s::operator==(const %s& other_value) const\n" | |
3258 | "{\n" | |
970ed795 EL |
3259 | "return ", name, name); |
3260 | for (i = 0; i < sdef->nElements; i++) { | |
3261 | if (i > 0) src = mputstr(src, "\n && "); | |
3262 | src = mputprintf(src, "field_%s==other_value.field_%s", | |
3263 | sdef->elements[i].name, sdef->elements[i].name); | |
3264 | } | |
3265 | src = mputstr(src, ";\n}\n\n"); | |
3266 | ||
3267 | /* != and () operator */ | |
3268 | def = mputprintf(def, | |
3269 | " inline boolean operator!=(const %s& other_value) const\n" | |
3270 | " { return !(*this == other_value); }\n\n", name); | |
3271 | ||
3272 | /* is_bound */ | |
3273 | def = mputprintf(def, | |
3274 | " boolean is_bound() const;\n\n"); | |
3275 | src = mputprintf(src, | |
3276 | "boolean %s::is_bound() const\n" | |
feade998 | 3277 | "{\n", name); |
970ed795 EL |
3278 | for(i=0; i < sdef->nElements; i++) { |
3279 | if(sdef->elements[i].isOptional) { | |
3280 | src = mputprintf(src, | |
3281 | "if(OPTIONAL_OMIT == field_%s.get_selection() || field_%s.is_bound()) return TRUE;\n", | |
3282 | sdef->elements[i].name, sdef->elements[i].name); | |
3283 | } else { | |
3284 | src = mputprintf(src, | |
3285 | "if(field_%s.is_bound()) return TRUE;\n", | |
3286 | sdef->elements[i].name); | |
3287 | } | |
3288 | } | |
3289 | src = mputprintf(src, | |
3290 | "return FALSE;\n" | |
3291 | "}\n"); | |
3292 | ||
3293 | /* is_present */ | |
3294 | def = mputstr(def, | |
3295 | "inline boolean is_present() const { return is_bound(); }\n"); | |
3296 | ||
3297 | /* is_value */ | |
3298 | def = mputprintf(def, | |
3299 | " boolean is_value() const;\n\n"); | |
3300 | src = mputprintf(src, | |
3301 | "boolean %s::is_value() const\n" | |
feade998 | 3302 | "{\n", name); |
970ed795 EL |
3303 | for(i=0; i < sdef->nElements; i++) { |
3304 | if(sdef->elements[i].isOptional) { | |
3305 | src = mputprintf(src, | |
3306 | "if(OPTIONAL_OMIT != field_%s.get_selection() && !field_%s.is_value()) return FALSE;\n", | |
3307 | sdef->elements[i].name, sdef->elements[i].name); | |
3308 | } else { | |
3309 | src = mputprintf(src, | |
3310 | "if(!field_%s.is_value()) return FALSE;\n", | |
3311 | sdef->elements[i].name); | |
3312 | } | |
3313 | } | |
3314 | src = mputprintf(src, | |
3315 | "return TRUE;\n}\n"); | |
3316 | ||
3317 | /* field accessor methods */ | |
3318 | for (i = 0; i < sdef->nElements; i++) { | |
3319 | if(sdef->elements[i].isOptional) | |
3320 | def = mputprintf | |
3321 | (def, | |
3322 | " inline OPTIONAL<%s>& %s()\n" | |
3323 | " {return field_%s;}\n" | |
3324 | " inline const OPTIONAL<%s>& %s() const\n" | |
3325 | " {return field_%s;}\n", | |
3326 | sdef->elements[i].type, sdef->elements[i].name, | |
3327 | sdef->elements[i].name, | |
3328 | sdef->elements[i].type, sdef->elements[i].name, | |
3329 | sdef->elements[i].name); | |
3330 | else def = mputprintf | |
3331 | (def, | |
3332 | " inline %s& %s()\n" | |
3333 | " {return field_%s;}\n" | |
3334 | " inline const %s& %s() const\n" | |
3335 | " {return field_%s;}\n", | |
3336 | sdef->elements[i].type, sdef->elements[i].name, | |
3337 | sdef->elements[i].name, sdef->elements[i].type, | |
3338 | sdef->elements[i].name, sdef->elements[i].name); | |
3339 | ||
3340 | } | |
3341 | ||
3342 | /* sizeof operation */ | |
3343 | mandatory_fields_count = 0; | |
3344 | for (i = 0; i < sdef->nElements; i++) | |
3345 | if (!sdef->elements[i].isOptional) mandatory_fields_count++; | |
feade998 | 3346 | |
3347 | if(sdef->nElements == mandatory_fields_count){ | |
3348 | def = mputprintf(def, | |
3349 | " inline int size_of() const\n" | |
3350 | " {return %lu;}\n", (unsigned long) mandatory_fields_count); | |
3351 | }else{ | |
3352 | def = mputstr(def, " int size_of() const;\n"); | |
3353 | src = mputprintf(src, | |
3354 | "int %s::size_of() const\n" | |
3355 | "{\n", | |
3356 | name); | |
970ed795 EL |
3357 | src = mputprintf(src, " int ret_val = %lu;\n", |
3358 | (unsigned long) mandatory_fields_count); | |
3359 | for (i = 0; i < sdef->nElements; i++) | |
3360 | if (sdef->elements[i].isOptional) | |
3361 | src = mputprintf(src, | |
3362 | " if (field_%s.ispresent()) ret_val++;\n", | |
3363 | sdef->elements[i].name); | |
feade998 | 3364 | src = mputstr(src, |
3365 | " return ret_val;\n" | |
3366 | "}\n\n"); | |
970ed795 | 3367 | } |
970ed795 EL |
3368 | |
3369 | /* log function */ | |
3370 | def = mputstr(def, " void log() const;\n"); | |
3371 | src = mputprintf(src, | |
3372 | "void %s::log() const\n{\n" | |
3373 | "if (!is_bound()) {\n" | |
3374 | "TTCN_Logger::log_event_unbound();\n" | |
3375 | "return;\n" | |
3376 | "}\n", name); | |
3377 | for (i = 0; i < sdef->nElements; i++) { | |
3378 | src = mputstr(src, "TTCN_Logger::log_event_str(\""); | |
3379 | if (i == 0) src = mputc(src, '{'); | |
3380 | else src = mputc(src, ','); | |
3381 | src = mputprintf(src, " %s := \");\n" | |
3382 | "field_%s.log();\n", | |
3383 | sdef->elements[i].dispname, sdef->elements[i].name); | |
3384 | } | |
3385 | src = mputstr(src, "TTCN_Logger::log_event_str(\" }\");\n}\n\n"); | |
3386 | ||
3387 | /* set param function */ | |
3388 | def = mputstr(def, " void set_param(Module_Param& param);\n"); | |
3389 | src = mputprintf | |
3390 | (src, | |
3391 | "void %s::set_param(Module_Param& param)\n{\n" | |
970ed795 EL |
3392 | " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n" |
3393 | " param.get_id()->next_name()) {\n" | |
3394 | // Haven't reached the end of the module parameter name | |
3395 | // => the name refers to one of the fields, not to the whole record | |
3396 | " char* param_field = param.get_id()->get_current_name();\n" | |
3397 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" | |
3398 | " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n" | |
3399 | " \" name for %s type `%s'\");\n" | |
3400 | " }\n" | |
3401 | " ", name, kind_str, dispname); | |
3402 | for (i = 0; i < sdef->nElements; i++) { | |
3403 | src = mputprintf(src, | |
3404 | "if (strcmp(\"%s\", param_field) == 0) {\n" | |
3405 | " %s().set_param(param);\n" | |
3406 | " return;\n" | |
3407 | " } else ", | |
3408 | sdef->elements[i].dispname, sdef->elements[i].name); | |
3409 | } | |
3410 | src = mputprintf(src, | |
3411 | "param.error(\"Field `%%s' not found in %s type `%s'\", param_field);\n" | |
3412 | " }\n" | |
3413 | " param.basic_check(Module_Param::BC_VALUE, \"%s value\");\n" | |
3f84031e | 3414 | " Module_Param_Ptr m_p = ¶m;\n" |
3abe9331 | 3415 | " if (param.get_type() == Module_Param::MP_Reference) {\n" |
3f84031e | 3416 | " m_p = param.get_referenced_param();\n" |
3abe9331 | 3417 | " }\n" |
3f84031e | 3418 | " switch (m_p->get_type()) {\n" |
970ed795 | 3419 | " case Module_Param::MP_Value_List:\n" |
3f84031e | 3420 | " if (%lu<m_p->get_size()) {\n" |
3421 | " param.error(\"%s value of type %s has %lu fields but list value has %%d fields\", (int)m_p->get_size());\n" | |
970ed795 EL |
3422 | " }\n", |
3423 | kind_str, dispname, kind_str, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements); | |
3424 | ||
3425 | for (i = 0; i < sdef->nElements; ++i) { | |
3426 | src = mputprintf(src, | |
3f84031e | 3427 | " if (m_p->get_size()>%lu && m_p->get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*m_p->get_elem(%lu));\n", |
970ed795 EL |
3428 | (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i); |
3429 | } | |
3430 | src = mputstr(src, | |
3431 | " break;\n" | |
3432 | " case Module_Param::MP_Assignment_List: {\n" | |
3f84031e | 3433 | " Vector<bool> value_used(m_p->get_size());\n" |
3434 | " value_used.resize(m_p->get_size(), false);\n"); | |
970ed795 EL |
3435 | for (i = 0; i < sdef->nElements; ++i) { |
3436 | src = mputprintf(src, | |
3f84031e | 3437 | " for (size_t val_idx=0; val_idx<m_p->get_size(); val_idx++) {\n" |
3438 | " Module_Param* const curr_param = m_p->get_elem(val_idx);\n" | |
970ed795 EL |
3439 | " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n" |
3440 | " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n" | |
3441 | " %s().set_param(*curr_param);\n" | |
3442 | " }\n" | |
3443 | " value_used[val_idx]=true;\n" | |
3444 | " }\n" | |
3445 | " }\n" | |
3446 | , sdef->elements[i].dispname, sdef->elements[i].name); | |
3447 | } | |
3448 | src = mputprintf(src, | |
3f84031e | 3449 | " for (size_t val_idx=0; val_idx<m_p->get_size(); val_idx++) if (!value_used[val_idx]) {\n" |
3450 | " m_p->get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", m_p->get_elem(val_idx)->get_id()->get_name());\n" | |
970ed795 EL |
3451 | " break;\n" |
3452 | " }\n" | |
3453 | " } break;\n" | |
3454 | " default:\n" | |
3455 | " param.type_error(\"%s value\", \"%s\");\n" | |
3456 | " }\n" | |
3457 | "}\n\n", dispname, kind_str, dispname); | |
3abe9331 | 3458 | |
3459 | /* get param function */ | |
3460 | def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); | |
3461 | src = mputprintf(src, | |
3462 | "Module_Param* %s::get_param(Module_Param_Name& param_name) const\n" | |
3463 | "{\n" | |
3464 | " if (!is_bound()) {\n" | |
3465 | " return new Module_Param_Unbound();\n" | |
3466 | " }\n" | |
3467 | " if (param_name.next_name()) {\n" | |
3468 | // Haven't reached the end of the module parameter name | |
3469 | // => the name refers to one of the fields, not to the whole record | |
3470 | " char* param_field = param_name.get_current_name();\n" | |
3471 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" | |
3472 | " TTCN_error(\"Unexpected array index in module parameter reference, \"\n" | |
3473 | " \"expected a valid field name for %s type `%s'\");\n" | |
3474 | " }\n" | |
3475 | " ", name, kind_str, dispname); | |
3476 | for (i = 0; i < sdef->nElements; i++) { | |
3477 | src = mputprintf(src, | |
3478 | "if (strcmp(\"%s\", param_field) == 0) {\n" | |
3479 | " return %s().get_param(param_name);\n" | |
3480 | " } else ", | |
3481 | sdef->elements[i].dispname, sdef->elements[i].name); | |
3482 | } | |
3483 | src = mputprintf(src, | |
3484 | "TTCN_error(\"Field `%%s' not found in %s type `%s'\", param_field);\n" | |
3485 | " }\n" | |
3f84031e | 3486 | " Module_Param_Assignment_List* m_p = new Module_Param_Assignment_List();\n" |
3abe9331 | 3487 | , kind_str, dispname); |
3488 | for (i = 0; i < sdef->nElements; i++) { | |
3489 | src = mputprintf(src, | |
3490 | " Module_Param* mp_field_%s = field_%s.get_param(param_name);\n" | |
3491 | " mp_field_%s->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n" | |
3f84031e | 3492 | " m_p->add_elem(mp_field_%s);\n" |
3abe9331 | 3493 | , sdef->elements[i].name, sdef->elements[i].name |
3494 | , sdef->elements[i].name, sdef->elements[i].dispname | |
3495 | , sdef->elements[i].name); | |
3496 | } | |
3497 | src = mputstr(src, | |
3f84031e | 3498 | " return m_p;\n" |
3abe9331 | 3499 | " }\n\n"); |
970ed795 EL |
3500 | |
3501 | /* set implicit omit function, recursive */ | |
3502 | def = mputstr(def, " void set_implicit_omit();\n"); | |
3503 | src = mputprintf(src, "void %s::set_implicit_omit()\n{\n", name); | |
3504 | for (i = 0; i < sdef->nElements; i++) { | |
3505 | if (sdef->elements[i].isOptional) { | |
3506 | src = mputprintf(src, | |
3507 | "if (!%s().is_bound()) %s() = OMIT_VALUE;\n" | |
3508 | "else %s().set_implicit_omit();\n", | |
3509 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); | |
3510 | } else { | |
3511 | src = mputprintf(src, | |
3512 | "if (%s().is_bound()) %s().set_implicit_omit();\n", | |
3513 | sdef->elements[i].name, sdef->elements[i].name); | |
3514 | } | |
3515 | } | |
3516 | src = mputstr(src, "}\n\n"); | |
3517 | ||
3518 | /* text encoder function */ | |
3519 | def = mputstr(def, " void encode_text(Text_Buf& text_buf) const;\n"); | |
feade998 | 3520 | src = mputprintf(src,"void %s::encode_text(Text_Buf& text_buf) const\n{\n", |
3521 | name); | |
970ed795 EL |
3522 | for (i = 0; i < sdef->nElements; i++) { |
3523 | src = mputprintf(src, "field_%s.encode_text(text_buf);\n", | |
3524 | sdef->elements[i].name); | |
3525 | } | |
3526 | src = mputstr(src, "}\n\n"); | |
3527 | ||
3528 | /* text decoder function */ | |
3529 | def = mputstr(def, " void decode_text(Text_Buf& text_buf);\n"); | |
feade998 | 3530 | src = mputprintf(src, "void %s::decode_text(Text_Buf& text_buf)\n{\n", |
3531 | name); | |
970ed795 EL |
3532 | for (i = 0; i < sdef->nElements; i++) { |
3533 | src = mputprintf(src, "field_%s.decode_text(text_buf);\n", | |
3534 | sdef->elements[i].name); | |
3535 | } | |
3536 | src = mputstr(src, "}\n\n"); | |
3537 | ||
3538 | /* The common "classname::encode()" and "classname::decode()" functions */ | |
3539 | if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) | |
3540 | def_encdec(name, &def, &src, ber_needed, raw_needed, | |
3541 | text_needed, xer_needed, json_needed, FALSE); | |
3542 | ||
3543 | /* BER functions */ | |
3544 | if(ber_needed) { | |
3545 | /* BER_encode_TLV() */ | |
3546 | src=mputprintf | |
3547 | (src, | |
3548 | "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td," | |
3549 | " unsigned p_coding) const\n" | |
3550 | "{\n" | |
3551 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
3552 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
3553 | " BER_chk_descr(p_td);\n" | |
3554 | " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n" | |
3555 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" | |
3556 | " TTCN_EncDec_ErrorContext ec_1;\n" | |
3557 | , name | |
3558 | ); | |
3559 | for(i=0; i<sdef->nElements; i++) { | |
3560 | if(!default_as_optional && sdef->elements[i].isDefault) { /* is DEFAULT */ | |
3561 | src=mputprintf | |
3562 | (src, | |
3563 | " if(field_%s!=%s) {\n" | |
3564 | " ec_1.set_msg(\"%s': \");\n" | |
3565 | " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_," | |
3566 | " p_coding));\n" | |
3567 | " }\n" | |
3568 | , sdef->elements[i].name, sdef->elements[i].defvalname | |
3569 | , sdef->elements[i].dispname | |
3570 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3571 | ); | |
3572 | } | |
3573 | else { /* is not DEFAULT */ | |
3574 | src=mputprintf | |
3575 | (src, | |
3576 | " ec_1.set_msg(\"%s': \");\n" | |
3577 | " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_," | |
3578 | " p_coding));\n" | |
3579 | , sdef->elements[i].dispname | |
3580 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3581 | ); | |
3582 | } /* !isDefault */ | |
3583 | } /* for i */ | |
3584 | if(sdef->kind==SET) { | |
3585 | src=mputstr | |
3586 | (src, | |
3587 | " if(p_coding==BER_ENCODE_DER)\n" | |
3588 | " new_tlv->sort_tlvs_tag();\n" | |
3589 | ); | |
3590 | } | |
3591 | src=mputstr | |
3592 | (src, | |
3593 | " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n" | |
3594 | " return new_tlv;\n" | |
3595 | "}\n" | |
3596 | "\n" | |
3597 | ); | |
3598 | ||
3599 | /* BER_decode_TLV() */ | |
3600 | src=mputprintf | |
3601 | (src, | |
3602 | "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td," | |
3603 | " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n" | |
3604 | "{\n" | |
970ed795 EL |
3605 | " BER_chk_descr(p_td);\n" |
3606 | " ASN_BER_TLV_t stripped_tlv;\n" | |
3607 | " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n" | |
3608 | " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n" | |
3609 | " stripped_tlv.chk_constructed_flag(TRUE);\n" | |
3610 | " size_t V_pos=0;\n" | |
3611 | " ASN_BER_TLV_t tmp_tlv;\n" | |
3612 | , name, sdef->dispname | |
3613 | ); | |
3614 | ||
3615 | if(sdef->kind==RECORD) | |
3616 | { /* SEQUENCE decoding */ | |
3617 | src=mputstr | |
3618 | (src, | |
3619 | " boolean tlv_present=FALSE;\n" | |
3620 | " {\n" | |
3621 | " TTCN_EncDec_ErrorContext ec_1(\"Component '\");\n" | |
3622 | " TTCN_EncDec_ErrorContext ec_2;\n" | |
3623 | ); | |
3624 | for(i=0; i<sdef->nElements; i++) { | |
3625 | src=mputprintf | |
3626 | (src, | |
3627 | " ec_2.set_msg(\"%s': \");\n" | |
3628 | " if(!tlv_present) tlv_present=BER_decode_constdTLV_next" | |
3629 | "(stripped_tlv, V_pos, L_form, tmp_tlv);\n" | |
3630 | , sdef->elements[i].dispname | |
3631 | ); | |
3632 | if(sdef->elements[i].isDefault) { /* is DEFAULT */ | |
3633 | src=mputprintf | |
3634 | (src, | |
3635 | " if(!tlv_present || !field_%s.BER_decode_isMyMsg(%s_descr_," | |
3636 | " tmp_tlv))\n" | |
3637 | " field_%s=%s;\n" | |
3638 | " else {\n" | |
3639 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv," | |
3640 | " L_form);\n" | |
3641 | " tlv_present=FALSE;\n" | |
3642 | " }\n" | |
3643 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3644 | , sdef->elements[i].name, sdef->elements[i].defvalname | |
3645 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3646 | ); | |
3647 | } | |
3648 | else if(sdef->elements[i].isOptional) { /* is OPTIONAL */ | |
3649 | src=mputprintf | |
3650 | (src, | |
3651 | " if(!tlv_present) field_%s=OMIT_VALUE;\n" | |
3652 | " else {\n" | |
3653 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n" | |
3654 | " if(field_%s.ispresent()) tlv_present=FALSE;\n" | |
3655 | " }\n" | |
3656 | , sdef->elements[i].name | |
3657 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3658 | , sdef->elements[i].name | |
3659 | ); | |
3660 | } | |
3661 | else { /* is not DEFAULT OPTIONAL */ | |
3662 | src=mputprintf | |
3663 | (src, | |
3664 | " if(!tlv_present){\n" | |
3665 | " ec_2.error(TTCN_EncDec::ET_INCOMPL_MSG,\"Invalid or incomplete message was received.\");\n" | |
3666 | " return FALSE;\n" | |
3667 | " }\n" | |
3668 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n" | |
3669 | " tlv_present=FALSE;\n" | |
3670 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3671 | ); | |
3672 | } /* !isDefault */ | |
3673 | } /* for i */ | |
3674 | src=mputstr | |
3675 | (src, | |
3676 | " }\n" | |
3677 | " BER_decode_constdTLV_end(stripped_tlv, V_pos, L_form, tmp_tlv," | |
3678 | " tlv_present);\n" | |
3679 | ); | |
3680 | } /* SEQUENCE decoding */ | |
3681 | else { /* SET decoding */ | |
3682 | src=mputprintf | |
3683 | (src, | |
3684 | " const char *fld_name[%lu]={" | |
3685 | , (unsigned long) sdef->nElements | |
3686 | ); | |
3687 | for(i=0; i<sdef->nElements; i++) | |
3688 | src=mputprintf | |
3689 | (src, | |
3690 | "%s\"%s\"" | |
3691 | , i?", ":"" | |
3692 | , sdef->elements[i].dispname | |
3693 | ); | |
3694 | /* field indicator: | |
3695 | * 0x01: value arrived | |
3696 | * 0x02: is optional / not used :) | |
3697 | * 0x04: has default / not used :) | |
3698 | */ | |
3699 | src=mputprintf | |
3700 | (src, | |
3701 | "};\n" | |
3702 | " unsigned char fld_indctr[%lu]={" | |
3703 | , (unsigned long) sdef->nElements | |
3704 | ); | |
3705 | for(i=0; i<sdef->nElements; i++) | |
3706 | src=mputprintf | |
3707 | (src, | |
3708 | "%s0" | |
3709 | , i?", ":"" | |
3710 | ); | |
3711 | src=mputstr | |
3712 | (src, | |
3713 | "};\n" | |
3714 | " size_t fld_curr;\n" | |
3715 | " while(BER_decode_constdTLV_next(stripped_tlv, V_pos," | |
3716 | " L_form, tmp_tlv)) {\n" | |
3717 | ); | |
3718 | for(i=0; i<sdef->nElements; i++) | |
3719 | src=mputprintf | |
3720 | (src, | |
3721 | " %sif(field_%s.BER_decode_isMyMsg(%s_descr_, tmp_tlv)) {\n" | |
3722 | " fld_curr=%lu;\n" | |
3723 | " TTCN_EncDec_ErrorContext ec_1(\"Component '%%s': \"," | |
3724 | " fld_name[%lu]);\n" | |
3725 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n" | |
3726 | " }\n" | |
3727 | , i?"else ":"" | |
3728 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3729 | , (unsigned long) i, (unsigned long) i | |
3730 | , sdef->elements[i].name, sdef->elements[i].typedescrname | |
3731 | ); | |
3732 | src=mputprintf | |
3733 | (src, | |
3734 | " else {\n" | |
3735 | " /* ellipsis or error... */\n" | |
3736 | " fld_curr=static_cast<size_t>(-1);\n" | |
3737 | " }\n" | |
3738 | " if(fld_curr!=static_cast<size_t>(-1)) {\n" | |
3739 | " if(fld_indctr[fld_curr])\n" | |
3740 | " ec_0.error(TTCN_EncDec::ET_DEC_DUPFLD, \"Duplicated" | |
3741 | " value for component '%%s'.\", fld_name[fld_curr]);\n" | |
3742 | " fld_indctr[fld_curr]=1;\n" | |
3743 | " }\n" /* if != -1 */ | |
3744 | " }\n" /* while */ | |
3745 | " for(fld_curr=0; fld_curr<%lu; fld_curr++) {\n" | |
3746 | " if(fld_indctr[fld_curr]) continue;\n" | |
3747 | " switch(fld_curr) {\n" | |
3748 | , (unsigned long) sdef->nElements | |
3749 | ); | |
3750 | for(i=0; i<sdef->nElements; i++) { | |
3751 | if(sdef->elements[i].isDefault) | |
3752 | src=mputprintf | |
3753 | (src, | |
3754 | " case %lu:\n" | |
3755 | " field_%s=%s;\n" | |
3756 | " break;\n" | |
3757 | , (unsigned long) i | |
3758 | , sdef->elements[i].name, sdef->elements[i].defvalname | |
3759 | ); | |
3760 | else if(sdef->elements[i].isOptional) | |
3761 | src=mputprintf | |
3762 | (src, | |
3763 | " case %lu:\n" | |
3764 | " field_%s=OMIT_VALUE;\n" | |
3765 | " break;\n" | |
3766 | , (unsigned long) i | |
3767 | , sdef->elements[i].name | |
3768 | ); | |
3769 | } /* for i */ | |
3770 | src=mputstr | |
3771 | (src, | |
3772 | " default:\n" | |
3773 | " ec_0.error(TTCN_EncDec::ET_DEC_MISSFLD, \"Missing" | |
3774 | " value for component '%s'.\", fld_name[fld_curr]);\n" | |
3775 | " }\n" /* switch */ | |
3776 | " }\n" /* for fld_curr */ | |
3777 | ); | |
3778 | } /* SET decoding */ | |
3779 | ||
3780 | if(sdef->opentype_outermost) { | |
3781 | src=mputstr | |
3782 | (src, | |
3783 | " TTCN_EncDec_ErrorContext ec_1(\"While decoding opentypes: \");\n" | |
3784 | " TTCN_Type_list p_typelist;\n" | |
3785 | " BER_decode_opentypes(p_typelist, L_form);\n" | |
3786 | ); | |
3787 | } /* if sdef->opentype_outermost */ | |
3788 | src=mputstr | |
3789 | (src, | |
3790 | " return TRUE;\n" | |
3791 | "}\n" | |
3792 | "\n" | |
3793 | ); | |
3794 | ||
3795 | if(sdef->has_opentypes) { | |
3796 | /* BER_decode_opentypes() */ | |
3797 | def=mputstr | |
3798 | (def, | |
3799 | "void BER_decode_opentypes(TTCN_Type_list& p_typelist," | |
3800 | " unsigned L_form);\n"); | |
3801 | src=mputprintf | |
3802 | (src, | |
3803 | "void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist," | |
3804 | " unsigned L_form)\n" | |
3805 | "{\n" | |
970ed795 EL |
3806 | " p_typelist.push(this);\n" |
3807 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" | |
3808 | " TTCN_EncDec_ErrorContext ec_1;\n" | |
3809 | , name | |
3810 | ); | |
3811 | for(i=0; i<sdef->nElements; i++) { | |
3812 | src=mputprintf | |
3813 | (src, | |
3814 | " ec_1.set_msg(\"%s': \");\n" | |
3815 | " field_%s.BER_decode_opentypes(p_typelist, L_form);\n" | |
3816 | , sdef->elements[i].dispname | |
3817 | , sdef->elements[i].name | |
3818 | ); | |
3819 | } /* for i */ | |
3820 | src=mputstr | |
3821 | (src, | |
3822 | " p_typelist.pop();\n" | |
3823 | "}\n" | |
3824 | "\n" | |
3825 | ); | |
3826 | } /* if sdef->has_opentypes */ | |
3827 | ||
3828 | } /* if ber_needed */ | |
3829 | ||
3830 | if(text_needed){ | |
3831 | int man_num=0; | |
3832 | int opt_number=0; | |
3833 | int seof=0; | |
3834 | size_t last_man_index=0; | |
3835 | for(i=0;i<sdef->nElements;i++){ | |
3836 | if(sdef->elements[i].isOptional) opt_number++; | |
3837 | else {man_num++;last_man_index=i+1;} | |
3838 | if(sdef->elements[i].of_type) seof++; | |
3839 | } | |
3840 | ||
3841 | src=mputprintf(src, | |
3842 | "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td," | |
3843 | " TTCN_Buffer& p_buf) const{\n" | |
3844 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" | |
3845 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
3846 | " bool need_separator=false;\n" | |
3847 | " int encoded_length=0;\n" | |
3848 | " if(p_td.text->begin_encode){\n" | |
3849 | " p_buf.put_cs(*p_td.text->begin_encode);\n" | |
3850 | " encoded_length+=p_td.text->begin_encode->lengthof();\n" | |
3851 | " }\n" | |
3852 | ,name | |
3853 | ); | |
3854 | ||
3855 | for(i=0;i<sdef->nElements;i++){ | |
3856 | if(sdef->elements[i].isOptional){ | |
3857 | src=mputprintf(src, | |
3858 | " if(field_%s.ispresent()){\n" | |
3859 | ,sdef->elements[i].name | |
3860 | ); | |
3861 | } | |
3862 | src=mputprintf(src, | |
3863 | " if(need_separator && p_td.text->separator_encode){\n" | |
3864 | " p_buf.put_cs(*p_td.text->separator_encode);\n" | |
3865 | " encoded_length+=p_td.text->separator_encode->lengthof();\n" | |
3866 | " }\n" | |
3867 | " encoded_length+=field_%s%s.TEXT_encode(%s_descr_,p_buf);\n" | |
3868 | " need_separator=true;\n" | |
3869 | ,sdef->elements[i].name | |
3870 | ,sdef->elements[i].isOptional?"()":"",sdef->elements[i].typedescrname | |
3871 | ); | |
3872 | if(sdef->elements[i].isOptional){ | |
3873 | src=mputstr(src, | |
3874 | " }\n" | |
3875 | ); | |
3876 | } | |
3877 | } | |
3878 | ||
3879 | src=mputstr(src, | |
3880 | " if(p_td.text->end_encode){\n" | |
3881 | " p_buf.put_cs(*p_td.text->end_encode);\n" | |
3882 | " encoded_length+=p_td.text->end_encode->lengthof();\n" | |
3883 | " }\n" | |
3884 | " return encoded_length;\n" | |
3885 | "}\n" | |
3886 | ); | |
3887 | ||
3888 | if(sdef->kind==SET){ /* set decoder start*/ | |
3889 | src = mputprintf(src, | |
3890 | "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td," | |
3891 | " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n" | |
970ed795 EL |
3892 | " int decoded_length=0;\n" |
3893 | " int decoded_field_length=0;\n" | |
3894 | " size_t pos=p_buf.get_pos();\n" | |
3895 | " boolean sep_found=FALSE;\n" | |
3896 | " int ml=0;\n" | |
3897 | " int sep_length=0;\n" | |
3898 | " int mand_field_num=%d;\n" | |
3899 | " int opt_field_num=%d;\n" | |
3900 | " int loop_detector=1;\n" | |
3901 | " int last_field_num=-1;\n" | |
3902 | " int field_map[%lu];\n" | |
3903 | " memset(field_map, 0, sizeof(field_map));\n" | |
3904 | " if(p_td.text->begin_decode){\n" | |
3905 | " int tl;\n" | |
3906 | " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n" | |
3907 | " if(no_err)return -1;\n" | |
3908 | " TTCN_EncDec_ErrorContext::error\n" | |
3909 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
3910 | " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)" | |
3911 | ", p_td.name);\n" | |
3912 | " return 0;\n" | |
3913 | " }\n" | |
3914 | " decoded_length+=tl;\n" | |
3915 | " p_buf.increase_pos(tl);\n" | |
3916 | " }\n" | |
3917 | " if(p_td.text->end_decode){\n" | |
3918 | " limit.add_token(p_td.text->end_decode);\n" | |
3919 | " ml++;\n" | |
3920 | " }\n" | |
3921 | " if(p_td.text->separator_decode){\n" | |
3922 | " limit.add_token(p_td.text->separator_decode);\n" | |
3923 | " ml++;\n" | |
3924 | " }\n" | |
3925 | ,name,man_num,opt_number,(unsigned long) sdef->nElements | |
3926 | ); | |
3927 | ||
3928 | if(seof){ | |
3929 | int first=0; | |
3930 | src=mputstr(src, | |
3931 | " int has_repeatable=0;\n" | |
3932 | " if(" | |
3933 | ); | |
3934 | for(i=0;i<sdef->nElements;i++){ | |
3935 | if(sdef->elements[i].of_type){ | |
3936 | src=mputprintf(src, | |
3937 | "%s%s_descr_.text->val.parameters->decoding_params.repeatable" | |
3938 | ,first?" && ":"" | |
3939 | ,sdef->elements[i].typedescrname | |
3940 | ); | |
3941 | first=1; | |
3942 | } | |
3943 | } | |
3944 | src=mputstr(src, | |
3945 | ") has_repeatable=1;\n" | |
3946 | ); | |
3947 | ||
3948 | } | |
3949 | for(i=0;i<sdef->nElements;i++){ | |
3950 | if(sdef->elements[i].isOptional){ | |
3951 | src=mputprintf(src, | |
3952 | " field_%s=OMIT_VALUE;\n" | |
3953 | ,sdef->elements[i].name | |
3954 | ); | |
3955 | } | |
3956 | } | |
3957 | src = mputprintf(src, | |
3958 | " while(mand_field_num+opt_field_num%s){\n" | |
3959 | " loop_detector=1;\n" | |
3960 | " while(TRUE){\n" | |
3961 | ,seof?"+has_repeatable":"" | |
3962 | ); | |
3963 | ||
3964 | for(i=0;i<sdef->nElements;i++){ | |
3965 | if(sdef->elements[i].of_type){ | |
3966 | src=mputprintf(src, | |
3967 | " if( (%s_descr_.text->val.parameters->decoding_params.repeatable" | |
3968 | " && field_map[%lu]<3) || !field_map[%lu]){\n" | |
3969 | " pos=p_buf.get_pos();\n" | |
3970 | " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf," | |
3971 | "limit,true,!field_map[%lu]);\n" | |
3972 | " if(decoded_field_length<0){\n" | |
3973 | " p_buf.set_pos(pos);\n" | |
3974 | ,sdef->elements[i].typedescrname,(unsigned long) i,(unsigned long) i | |
3975 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
3976 | ,sdef->elements[i].typedescrname | |
3977 | ,(unsigned long) i | |
3978 | ); | |
3979 | ||
3980 | if(sdef->elements[i].isOptional){ | |
3981 | src=mputprintf(src, | |
3982 | " if(!field_map[%lu]) field_%s=OMIT_VALUE;\n" | |
3983 | ,(unsigned long) i | |
3984 | ,sdef->elements[i].name | |
3985 | ); | |
3986 | } | |
3987 | src=mputprintf(src, | |
3988 | " }else{\n" | |
3989 | " loop_detector=0;\n" | |
3990 | " if(!field_map[%lu]) {%s--;field_map[%lu]=1;}\n" | |
3991 | " else field_map[%lu]=2;\n" | |
3992 | " last_field_num=%lu;\n" | |
3993 | " break;\n" | |
3994 | " }\n" | |
3995 | " }\n" | |
3996 | ,(unsigned long) i | |
3997 | ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num" | |
3998 | ,(unsigned long) i,(unsigned long) i,(unsigned long) i | |
3999 | ); | |
4000 | } else { | |
4001 | src=mputprintf(src, | |
4002 | " if(!field_map[%lu]){\n" | |
4003 | " pos=p_buf.get_pos();\n" | |
4004 | " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf," | |
4005 | "limit,true);\n" | |
4006 | " if(decoded_field_length<0){\n" | |
4007 | " p_buf.set_pos(pos);\n" | |
4008 | "%s%s%s" | |
4009 | " }else{\n" | |
4010 | " loop_detector=0;\n" | |
4011 | " field_map[%lu]=1;\n" | |
4012 | " %s--;\n" | |
4013 | " last_field_num=%lu;\n" | |
4014 | " break;\n" | |
4015 | " }\n" | |
4016 | " }\n" | |
4017 | ,(unsigned long) i | |
4018 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4019 | ,sdef->elements[i].typedescrname | |
4020 | ,sdef->elements[i].isOptional?" field_":"" | |
4021 | ,sdef->elements[i].isOptional?sdef->elements[i].name:"" | |
4022 | ,sdef->elements[i].isOptional?"=OMIT_VALUE;\n":"",(unsigned long) i | |
4023 | ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num" | |
4024 | ,(unsigned long) i | |
4025 | ); | |
4026 | } | |
4027 | } | |
4028 | ||
4029 | src = mputstr(src, | |
4030 | " break;\n" | |
4031 | " }\n" | |
4032 | " if(loop_detector) break;\n" | |
4033 | " if(p_td.text->separator_decode){\n" | |
4034 | " int tl;\n" | |
4035 | " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n" | |
4036 | " if(p_td.text->end_decode){\n" | |
4037 | " int tl;\n" | |
4038 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" | |
4039 | " sep_found=FALSE;\n" | |
4040 | " break;\n" | |
4041 | " }\n" | |
4042 | " } else if(limit.has_token(ml)){\n" | |
4043 | " int tl;\n" | |
4044 | " if((tl=limit.match(p_buf,ml))==0){\n" | |
4045 | " sep_found=FALSE;\n" | |
4046 | " break;\n" | |
4047 | " }\n" | |
4048 | " } else break;\n" | |
4049 | " p_buf.set_pos(pos);\n" | |
4050 | " decoded_length-=decoded_field_length;\n" | |
4051 | " field_map[last_field_num]+=2;\n" | |
4052 | ); | |
4053 | ||
4054 | if(opt_number){ | |
4055 | src=mputstr(src, | |
4056 | "switch(last_field_num){\n" | |
4057 | ); | |
4058 | for(i=0;i<sdef->nElements;i++){ | |
4059 | if(sdef->elements[i].of_type){ | |
4060 | if(sdef->elements[i].isOptional){ | |
4061 | src=mputprintf(src, | |
4062 | " case %lu:\n" | |
4063 | " if(field_map[%lu]==3){\n" | |
4064 | " field_%s=OMIT_VALUE;\n" | |
4065 | " opt_field_num++;\n" | |
4066 | " }\n" | |
4067 | " break;\n" | |
4068 | ,(unsigned long) i,(unsigned long) i,sdef->elements[i].name | |
4069 | ); | |
4070 | } else { | |
4071 | src=mputprintf(src, | |
4072 | " case %lu:\n" | |
4073 | " if(field_map[%lu]==3){\n" | |
4074 | " mand_field_num++;\n" | |
4075 | " }\n" | |
4076 | " break;\n" | |
4077 | ,(unsigned long) i,(unsigned long) i | |
4078 | ); | |
4079 | } | |
4080 | } else if(sdef->elements[i].isOptional){ | |
4081 | src=mputprintf(src, | |
4082 | " case %lu:\n" | |
4083 | " field_%s=OMIT_VALUE;\n" | |
4084 | " opt_field_num++;\n" | |
4085 | " break;\n" | |
4086 | ,(unsigned long) i,sdef->elements[i].name | |
4087 | ); | |
4088 | } | |
4089 | } | |
4090 | src=mputstr(src, | |
4091 | " default:\n" | |
4092 | " mand_field_num++;\n" | |
4093 | " break;\n" | |
4094 | "}\n" | |
4095 | ); | |
4096 | } | |
4097 | ||
4098 | src = mputprintf(src, | |
4099 | " } else {\n" | |
4100 | " sep_length=tl;\n" | |
4101 | " decoded_length+=tl;\n" | |
4102 | " p_buf.increase_pos(tl);\n" | |
4103 | " for(int a=0;a<%lu;a++) if(field_map[a]>2) field_map[a]-=3;\n" | |
4104 | " sep_found=TRUE;}\n" | |
4105 | " } else if(p_td.text->end_decode){\n" | |
4106 | " int tl;\n" | |
4107 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" | |
4108 | " decoded_length+=tl;\n" | |
4109 | " p_buf.increase_pos(tl);\n" | |
4110 | " limit.remove_tokens(ml);\n" | |
4111 | " if(mand_field_num) return -1;\n" | |
4112 | " return decoded_length;\n" | |
4113 | " }\n" | |
4114 | " } else if(limit.has_token(ml)){\n" | |
4115 | " int tl;\n" | |
4116 | " if((tl=limit.match(p_buf,ml))==0){\n" | |
4117 | " sep_found=FALSE;\n" | |
4118 | " break;\n" | |
4119 | " }\n" | |
4120 | " }\n" | |
4121 | " }\n" | |
4122 | " limit.remove_tokens(ml);\n" | |
4123 | " if(sep_found){\n" | |
4124 | " if(mand_field_num){\n" | |
4125 | " if(no_err)return -1;\n" | |
4126 | " TTCN_EncDec_ErrorContext::error" | |
4127 | "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding '%%s': \"," | |
4128 | "p_td.name);\n" | |
4129 | " return decoded_length;\n" | |
4130 | " } else {\n" | |
4131 | " decoded_length-=sep_length;\n" | |
4132 | " p_buf.set_pos(p_buf.get_pos()-sep_length);\n" | |
4133 | " }\n" | |
4134 | " }\n" | |
4135 | " if(p_td.text->end_decode){\n" | |
4136 | " int tl;\n" | |
4137 | " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" | |
4138 | " if(no_err)return -1;\n" | |
4139 | " TTCN_EncDec_ErrorContext::error" | |
4140 | "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
4141 | " not found for '%%s': \",(const char*)*(p_td.text->end_decode)" | |
4142 | ",p_td.name);\n" | |
4143 | " return decoded_length;\n" | |
4144 | " }\n" | |
4145 | " decoded_length+=tl;\n" | |
4146 | " p_buf.increase_pos(tl);\n" | |
4147 | " }\n" | |
4148 | " if(mand_field_num) return -1;\n" | |
4149 | " return decoded_length;\n" | |
4150 | "}\n" | |
4151 | ,(unsigned long) sdef->nElements | |
4152 | ); | |
4153 | } else { /* record decoder start */ | |
4154 | src = mputprintf(src, | |
4155 | "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td," | |
4156 | " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n" | |
970ed795 EL |
4157 | " int decoded_length=0;\n" |
4158 | " int decoded_field_length=0;\n" | |
4159 | "%s" | |
4160 | " boolean sep_found=FALSE;\n" | |
4161 | " int sep_length=0;\n" | |
4162 | " int ml=0;\n" | |
4163 | " if(p_td.text->begin_decode){\n" | |
4164 | " int tl;\n" | |
4165 | " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n" | |
4166 | " if(no_err)return -1;\n" | |
4167 | " TTCN_EncDec_ErrorContext::error\n" | |
4168 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
4169 | " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)" | |
4170 | ", p_td.name);\n" | |
4171 | " return 0;\n" | |
4172 | " }\n" | |
4173 | " decoded_length+=tl;\n" | |
4174 | " p_buf.increase_pos(tl);\n" | |
4175 | " }\n" | |
4176 | " if(p_td.text->end_decode){\n" | |
4177 | " limit.add_token(p_td.text->end_decode);\n" | |
4178 | " ml++;\n" | |
4179 | " }\n" | |
4180 | " if(p_td.text->separator_decode){\n" | |
4181 | " limit.add_token(p_td.text->separator_decode);\n" | |
4182 | " ml++;\n" | |
4183 | " }\n" | |
4184 | ,name,opt_number?" size_t pos=p_buf.get_pos();\n":"" | |
4185 | ); | |
4186 | for(i=0;i<sdef->nElements;i++){ | |
4187 | if(sdef->elements[i].isOptional){ | |
4188 | src=mputprintf(src, | |
4189 | " field_%s=OMIT_VALUE;\n" | |
4190 | ,sdef->elements[i].name | |
4191 | ); | |
4192 | } } | |
4193 | src=mputstr(src, | |
4194 | " while(TRUE){\n" | |
4195 | ); | |
4196 | for(i=0;i<sdef->nElements;i++){ | |
4197 | if(sdef->elements[i].isOptional){ | |
4198 | src=mputstr(src, | |
4199 | " pos=p_buf.get_pos();\n" | |
4200 | ); | |
4201 | } | |
4202 | src=mputprintf(src, | |
4203 | " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf" | |
4204 | ",limit,TRUE);\n" | |
4205 | " if(decoded_field_length<0){\n" | |
4206 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4207 | ,sdef->elements[i].typedescrname | |
4208 | ); | |
4209 | if(sdef->elements[i].isOptional){ | |
4210 | src=mputprintf(src, | |
4211 | " field_%s=OMIT_VALUE;\n" | |
4212 | " p_buf.set_pos(pos);\n" | |
4213 | " } else {\n" | |
4214 | ,sdef->elements[i].name | |
4215 | ); | |
4216 | } else { | |
4217 | src=mputprintf(src, | |
4218 | " limit.remove_tokens(ml);\n" | |
4219 | " if(no_err)return -1;\n" | |
4220 | " TTCN_EncDec_ErrorContext::error" | |
4221 | "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding " | |
4222 | "field '%s' for '%%s': \", p_td.name);\n" | |
4223 | " return decoded_length;\n" | |
4224 | " } else {\n" | |
4225 | ,sdef->elements[i].name | |
4226 | ); | |
4227 | } | |
4228 | src=mputstr(src, | |
4229 | " decoded_length+=decoded_field_length;\n" | |
4230 | ); | |
4231 | if(last_man_index>(i+1)){ | |
4232 | src=mputstr(src, | |
4233 | " if(p_td.text->separator_decode){\n" | |
4234 | " int tl;\n" | |
4235 | " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n" | |
4236 | ); | |
4237 | ||
4238 | if(sdef->elements[i].isOptional){ | |
4239 | src=mputprintf(src, | |
4240 | " field_%s=OMIT_VALUE;\n" | |
4241 | " p_buf.set_pos(pos);\n" | |
4242 | " decoded_length-=decoded_field_length;\n" | |
4243 | ,sdef->elements[i].name | |
4244 | ); | |
4245 | } else { | |
4246 | src=mputstr(src, | |
4247 | " limit.remove_tokens(ml);\n" | |
4248 | " if(no_err)return -1;\n" | |
4249 | " TTCN_EncDec_ErrorContext::error" | |
4250 | "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'" | |
4251 | " not found for '%s': \",(const char*)*(p_td.text->" | |
4252 | "separator_decode),p_td.name);\n" | |
4253 | " return decoded_length;\n" | |
4254 | ); | |
4255 | } | |
4256 | ||
4257 | src=mputstr(src, | |
4258 | " } else {\n" | |
4259 | " decoded_length+=tl;\n" | |
4260 | " p_buf.increase_pos(tl);\n" | |
4261 | " sep_length=tl;\n" | |
4262 | " sep_found=TRUE;}\n" | |
4263 | " } else sep_found=FALSE;\n" | |
4264 | ); | |
4265 | } else if(i==(sdef->nElements-1)){ | |
4266 | src=mputstr(src, | |
4267 | " sep_found=FALSE;\n" | |
4268 | ); | |
4269 | } else { | |
4270 | src=mputstr(src, | |
4271 | " if(p_td.text->separator_decode){\n" | |
4272 | " int tl;\n" | |
4273 | " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n" | |
4274 | ); | |
4275 | if(sdef->elements[i].isOptional){ | |
4276 | src=mputprintf(src, | |
4277 | " if(p_td.text->end_decode){\n" | |
4278 | " int tl;\n" | |
4279 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" | |
4280 | " decoded_length+=tl;\n" | |
4281 | " p_buf.increase_pos(tl);\n" | |
4282 | " limit.remove_tokens(ml);\n" | |
4283 | " return decoded_length;\n" | |
4284 | " }\n" | |
4285 | " } else if(limit.has_token(ml)){\n" | |
4286 | " if((tl=limit.match(p_buf,ml))==0){\n" | |
4287 | " sep_found=FALSE;\n" | |
4288 | " break;\n" | |
4289 | " }\n" | |
4290 | " } else break;\n" | |
4291 | " field_%s=OMIT_VALUE;\n" | |
4292 | " p_buf.set_pos(pos);\n" | |
4293 | " decoded_length-=decoded_field_length;\n" | |
4294 | ,sdef->elements[i].name | |
4295 | ); | |
4296 | } else { | |
4297 | src=mputstr(src, | |
4298 | " sep_found=FALSE;\n" | |
4299 | " break;\n" | |
4300 | ); | |
4301 | } | |
4302 | src=mputstr(src, | |
4303 | " } else {\n" | |
4304 | " decoded_length+=tl;\n" | |
4305 | " p_buf.increase_pos(tl);\n" | |
4306 | " sep_length=tl;\n" | |
4307 | " sep_found=TRUE;}\n" | |
4308 | " } else {\n" | |
4309 | " sep_found=FALSE;\n" | |
4310 | " if(p_td.text->end_decode){\n" | |
4311 | " int tl;\n" | |
4312 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" | |
4313 | " decoded_length+=tl;\n" | |
4314 | " p_buf.increase_pos(tl);\n" | |
4315 | " limit.remove_tokens(ml);\n" | |
4316 | " return decoded_length;\n" | |
4317 | " }\n" | |
4318 | " } else if(limit.has_token(ml)){\n" | |
4319 | " int tl;\n" | |
4320 | " if((tl=limit.match(p_buf,ml))==0){\n" | |
4321 | " sep_found=FALSE;\n" | |
4322 | " break;\n" | |
4323 | " }\n" | |
4324 | " }\n" | |
4325 | " }\n" | |
4326 | ); | |
4327 | } | |
4328 | src=mputstr(src, | |
4329 | " }\n" | |
4330 | ); | |
4331 | } | |
4332 | ||
4333 | src = mputstr(src, | |
4334 | " break;\n" | |
4335 | " }\n" | |
4336 | " limit.remove_tokens(ml);\n" | |
4337 | " if(sep_found){\n" | |
4338 | " p_buf.set_pos(p_buf.get_pos()-sep_length);\n" | |
4339 | " decoded_length-=sep_length;\n" | |
4340 | " }\n" | |
4341 | " if(p_td.text->end_decode){\n" | |
4342 | " int tl;\n" | |
4343 | " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" | |
4344 | " if(no_err)return -1;\n" | |
4345 | " TTCN_EncDec_ErrorContext::error" | |
4346 | "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'" | |
4347 | " not found for '%s': \",(const char*)*(p_td.text->end_decode)" | |
4348 | ",p_td.name);\n" | |
4349 | " return decoded_length;\n" | |
4350 | " }\n" | |
4351 | " decoded_length+=tl;\n" | |
4352 | " p_buf.increase_pos(tl);\n" | |
4353 | " }\n" | |
4354 | " return decoded_length;\n" | |
4355 | "}\n" | |
4356 | ); | |
4357 | } | |
4358 | } /* text_needed */ | |
4359 | ||
4360 | /* RAW functions */ | |
4361 | if(raw_needed){ | |
4362 | struct raw_option_struct *raw_options; | |
4363 | boolean haslengthto, haspointer, hascrosstag, has_ext_bit; | |
4364 | raw_options = (struct raw_option_struct*) | |
4365 | Malloc(sdef->nElements * sizeof(*raw_options)); | |
4366 | ||
4367 | set_raw_options(sdef, raw_options, &haslengthto, | |
4368 | &haspointer, &hascrosstag, &has_ext_bit); | |
4369 | ||
4370 | src = generate_raw_coding(src, sdef, raw_options, haspointer, hascrosstag, | |
4371 | has_ext_bit); | |
4372 | ||
4373 | for (i = 0; i < sdef->nElements; i++) { | |
4374 | Free(raw_options[i].lengthoffield); | |
4375 | Free(raw_options[i].dependent_fields); | |
4376 | } | |
4377 | Free(raw_options); | |
4378 | } /* if raw_needed */ | |
4379 | ||
4380 | if (xer_needed) gen_xer(sdef, &def, &src); | |
4381 | ||
4382 | if (json_needed) { | |
4383 | // JSON encode, RT1 | |
4384 | src = mputprintf(src, | |
4385 | "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n" | |
4386 | "{\n" | |
4387 | " if (!is_bound()) {\n" | |
4388 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" | |
4389 | " \"Encoding an unbound value of type %s.\");\n" | |
4390 | " return -1;\n" | |
4391 | " }\n\n" | |
4392 | " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n" | |
4393 | , name, dispname); | |
4394 | for (i = 0; i < sdef->nElements; ++i) { | |
3abe9331 | 4395 | if (sdef->elements[i].isOptional && !sdef->elements[i].jsonOmitAsNull && |
4396 | !sdef->elements[i].jsonMetainfoUnbound) { | |
970ed795 EL |
4397 | src = mputprintf(src, |
4398 | " if (field_%s.is_present())\n" | |
4399 | , sdef->elements[i].name); | |
4400 | } | |
3abe9331 | 4401 | src = mputprintf(src, |
970ed795 | 4402 | " {\n" |
3abe9331 | 4403 | " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n " |
4404 | , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname); | |
4405 | if (sdef->elements[i].jsonMetainfoUnbound) { | |
4406 | src = mputprintf(src, | |
4407 | "if (!field_%s.is_bound()) {\n" | |
4408 | " enc_len += p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL);\n" | |
4409 | " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"metainfo %s\");\n" | |
4410 | " enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, \"\\\"unbound\\\"\");\n" | |
4411 | " }\n" | |
4412 | " else " | |
4413 | , sdef->elements[i].name | |
4414 | , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname); | |
4415 | } | |
4416 | src = mputprintf(src, | |
4417 | "enc_len += field_%s.JSON_encode(%s_descr_, p_tok);\n" | |
970ed795 | 4418 | " }\n\n" |
970ed795 EL |
4419 | , sdef->elements[i].name, sdef->elements[i].typedescrname); |
4420 | } | |
4421 | src = mputstr(src, | |
4422 | " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n" | |
4423 | " return enc_len;\n" | |
4424 | "}\n\n"); | |
4425 | ||
4426 | // JSON decode, RT1 | |
4427 | src = mputprintf(src, | |
4428 | "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n" | |
4429 | "{\n" | |
509718e0 | 4430 | " json_token_t j_token = JSON_TOKEN_NONE;\n" |
4431 | " int dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n" | |
4432 | " if (JSON_TOKEN_ERROR == j_token) {\n" | |
970ed795 EL |
4433 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n" |
4434 | " return JSON_ERROR_FATAL;\n" | |
4435 | " }\n" | |
509718e0 | 4436 | " else if (JSON_TOKEN_OBJECT_START != j_token) {\n" |
970ed795 EL |
4437 | " return JSON_ERROR_INVALID_TOKEN;\n" |
4438 | " }\n" | |
3abe9331 | 4439 | , name); |
4440 | boolean has_metainfo_enabled = FALSE; | |
4441 | for (i = 0; i < sdef->nElements; ++i) { | |
feade998 | 4442 | src = mputprintf(src, " boolean %s_found = FALSE;\n", sdef->elements[i].name); |
3abe9331 | 4443 | if (sdef->elements[i].jsonMetainfoUnbound) { |
4444 | // initialize meta info states | |
4445 | src = mputprintf(src, | |
4446 | " int metainfo_%s = JSON_METAINFO_NONE;\n" | |
4447 | , sdef->elements[i].name); | |
4448 | has_metainfo_enabled = TRUE; | |
4449 | } | |
4450 | } | |
4451 | src = mputstr(src, | |
4452 | // Read name - value token pairs until we reach some other token | |
4453 | "\n while (true) {\n" | |
509718e0 | 4454 | " char* fld_name = 0;\n" |
970ed795 EL |
4455 | " size_t name_len = 0;\n" |
4456 | " size_t buf_pos = p_tok.get_buf_pos();\n" | |
509718e0 | 4457 | " dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n" |
4458 | " if (JSON_TOKEN_ERROR == j_token) {\n" | |
970ed795 EL |
4459 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n" |
4460 | " return JSON_ERROR_FATAL;\n" | |
4461 | " }\n" | |
4462 | // undo the last action on the buffer | |
509718e0 | 4463 | " else if (JSON_TOKEN_NAME != j_token) {\n" |
970ed795 EL |
4464 | " p_tok.set_buf_pos(buf_pos);\n" |
4465 | " break;\n" | |
4466 | " }\n" | |
3abe9331 | 4467 | " else {\n "); |
4468 | if (has_metainfo_enabled) { | |
4469 | // check for meta info | |
4470 | src = mputstr(src, | |
4471 | "boolean is_metainfo = FALSE;\n" | |
4472 | " if (name_len > 9 && 0 == strncmp(fld_name, \"metainfo \", 9)) {\n" | |
4473 | " fld_name += 9;\n" | |
4474 | " name_len -= 9;\n" | |
4475 | " is_metainfo = TRUE;\n" | |
4476 | " }\n "); | |
4477 | } | |
970ed795 EL |
4478 | for (i = 0; i < sdef->nElements; ++i) { |
4479 | src = mputprintf(src, | |
4480 | // check field name | |
509718e0 | 4481 | "if (%d == name_len && 0 == strncmp(fld_name, \"%s\", name_len)) {\n" |
feade998 | 4482 | " %s_found = TRUE;\n" |
970ed795 | 4483 | , (int)strlen(sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname) |
feade998 | 4484 | , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname |
4485 | , sdef->elements[i].name); | |
3abe9331 | 4486 | if (has_metainfo_enabled) { |
4487 | src = mputstr(src, " if (is_metainfo) {\n"); | |
4488 | if (sdef->elements[i].jsonMetainfoUnbound) { | |
4489 | src = mputprintf(src, | |
4490 | // check meta info | |
4491 | " char* info_value = 0;\n" | |
4492 | " size_t info_len = 0;\n" | |
4493 | " dec_len += p_tok.get_next_token(&j_token, &info_value, &info_len);\n" | |
4494 | " if (JSON_TOKEN_STRING == j_token && 9 == info_len &&\n" | |
4495 | " 0 == strncmp(info_value, \"\\\"unbound\\\"\", 9)) {\n" | |
4496 | " metainfo_%s = JSON_METAINFO_UNBOUND;\n" | |
4497 | " }\n" | |
4498 | " else {\n" | |
4499 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_VALUE_ERROR, \"%s\");\n" | |
4500 | " return JSON_ERROR_FATAL;\n" | |
4501 | " }\n" | |
4502 | , sdef->elements[i].name, sdef->elements[i].dispname); | |
4503 | } | |
4504 | else { | |
4505 | src = mputprintf(src, | |
4506 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_NOT_APPLICABLE, \"%s\");\n" | |
4507 | " return JSON_ERROR_FATAL;\n" | |
4508 | , sdef->elements[i].dispname); | |
4509 | } | |
4510 | src = mputstr(src, | |
4511 | " }\n" | |
4512 | " else {\n"); | |
4513 | if (sdef->elements[i].jsonMetainfoUnbound) { | |
4514 | src = mputstr(src, " buf_pos = p_tok.get_buf_pos();\n"); | |
4515 | } | |
4516 | } | |
4517 | src = mputprintf(src, | |
4518 | " int ret_val = field_%s.JSON_decode(%s_descr_, p_tok, p_silent);\n" | |
4519 | " if (0 > ret_val) {\n" | |
4520 | " if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n" | |
4521 | , sdef->elements[i].name, sdef->elements[i].typedescrname); | |
4522 | if (sdef->elements[i].jsonMetainfoUnbound) { | |
4523 | src = mputprintf(src, | |
4524 | // undo the last action on the buffer, check if the invalid token was a null token | |
4525 | " p_tok.set_buf_pos(buf_pos);\n" | |
4526 | " p_tok.get_next_token(&j_token, NULL, NULL);\n" | |
4527 | " if (JSON_TOKEN_LITERAL_NULL == j_token) {\n" | |
4528 | " if (JSON_METAINFO_NONE == metainfo_%s) {\n" | |
4529 | // delay reporting an error for now, there might be meta info later | |
4530 | " metainfo_%s = JSON_METAINFO_NEEDED;\n" | |
4531 | " continue;\n" | |
4532 | " }\n" | |
4533 | " else if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n" | |
4534 | // meta info already found | |
4535 | " continue;\n" | |
4536 | " }\n" | |
4537 | " }\n" | |
4538 | , sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); | |
4539 | } | |
4540 | src = mputprintf(src, | |
4541 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n" | |
4542 | " }\n" | |
4543 | " return JSON_ERROR_FATAL;\n" | |
4544 | " }\n" | |
4545 | " dec_len += ret_val;\n" | |
970ed795 | 4546 | , sdef->elements[i].dispname); |
3abe9331 | 4547 | if (has_metainfo_enabled) { |
4548 | src = mputstr(src, " }\n"); | |
4549 | } | |
4550 | src = mputstr(src, | |
4551 | " }\n" | |
4552 | " else "); | |
970ed795 | 4553 | } |
3abe9331 | 4554 | src = mputprintf(src, |
970ed795 EL |
4555 | "{\n" |
4556 | // invalid field name | |
509718e0 | 4557 | " char* fld_name2 = mcopystrn(fld_name, name_len);\n" |
3abe9331 | 4558 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, %sJSON_DEC_INVALID_NAME_ERROR, fld_name2);\n" |
970ed795 | 4559 | // if this is set to a warning, skip the value of the field |
509718e0 | 4560 | " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n" |
4561 | " if (JSON_TOKEN_NUMBER != j_token && JSON_TOKEN_STRING != j_token &&\n" | |
4562 | " JSON_TOKEN_LITERAL_TRUE != j_token && JSON_TOKEN_LITERAL_FALSE != j_token &&\n" | |
4563 | " JSON_TOKEN_LITERAL_NULL != j_token) {\n" | |
4564 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name2);\n" | |
4565 | " Free(fld_name2);\n" | |
970ed795 EL |
4566 | " return JSON_ERROR_FATAL;\n" |
4567 | " }\n" | |
509718e0 | 4568 | " Free(fld_name2);\n" |
970ed795 EL |
4569 | " }\n" |
4570 | " }\n" | |
4571 | " }\n\n" | |
509718e0 | 4572 | " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n" |
4573 | " if (JSON_TOKEN_OBJECT_END != j_token) {\n" | |
970ed795 EL |
4574 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_OBJECT_END_TOKEN_ERROR, \"\");\n" |
4575 | " return JSON_ERROR_FATAL;\n" | |
3abe9331 | 4576 | " }\n\n " |
4577 | , has_metainfo_enabled ? "is_metainfo ?\n JSON_DEC_METAINFO_NAME_ERROR : " : ""); | |
4578 | // Check if every field has been set and handle meta info | |
970ed795 | 4579 | for (i = 0; i < sdef->nElements; ++i) { |
3abe9331 | 4580 | if (sdef->elements[i].jsonMetainfoUnbound) { |
4581 | src = mputprintf(src, | |
4582 | "if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n" | |
4583 | " field_%s.clean_up();\n" | |
4584 | " }\n" | |
4585 | " else if (JSON_METAINFO_NEEDED == metainfo_%s) {\n" | |
4586 | // no meta info was found for this field, report the delayed error | |
4587 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n" | |
4588 | " }\n" | |
4589 | " else " | |
4590 | , sdef->elements[i].name, sdef->elements[i].name | |
4591 | , sdef->elements[i].name, sdef->elements[i].dispname); | |
4592 | } | |
970ed795 | 4593 | src = mputprintf(src, |
1c3eb2ec | 4594 | " if (!%s_found) {\n" |
970ed795 EL |
4595 | , sdef->elements[i].name); |
4596 | if (sdef->elements[i].jsonDefaultValue) { | |
4597 | src = mputprintf(src, | |
4598 | " field_%s.JSON_decode(%s_descr_, DUMMY_BUFFER, p_silent);\n" | |
4599 | , sdef->elements[i].name, sdef->elements[i].typedescrname); | |
4600 | } | |
4601 | else if (sdef->elements[i].isOptional) { | |
4602 | src = mputprintf(src, | |
4603 | " field_%s = OMIT_VALUE;\n" | |
4604 | , sdef->elements[i].name); | |
4605 | } else { | |
4606 | src = mputprintf(src, | |
4607 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_MISSING_FIELD_ERROR, \"%s\");\n" | |
4608 | " return JSON_ERROR_FATAL;\n" | |
4609 | , sdef->elements[i].dispname); | |
4610 | } | |
4611 | src = mputstr(src, | |
4612 | " }\n"); | |
4613 | } | |
4614 | src = mputstr(src, | |
509718e0 | 4615 | "\n return dec_len;\n" |
970ed795 EL |
4616 | "}\n\n"); |
4617 | } | |
4618 | ||
4619 | /* end of class definition */ | |
4620 | def = mputstr(def, "};\n\n"); | |
4621 | ||
4622 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
4623 | Free(def); | |
4624 | ||
4625 | output->source.methods = mputstr(output->source.methods, src); | |
4626 | Free(src); | |
4627 | } | |
4628 | ||
4629 | ||
4630 | static char *genRawFieldDecodeLimit(char *src, const struct_def *sdef, | |
4631 | int i, const struct raw_option_struct *raw_options) | |
4632 | { | |
4633 | /* number of arguments passed to min_of_ints() */ | |
4634 | int nof_args = 1; | |
4635 | int j; | |
4636 | for (j = 0; j < raw_options[i].lengthof; j++) { | |
4637 | int field_index = raw_options[i].lengthoffield[j]; | |
4638 | if (i > field_index && sdef->elements[field_index].raw.unit!=-1) | |
4639 | nof_args++; | |
4640 | } | |
4641 | if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[ | |
4642 | raw_options[i].extbitgroup-1].ext_bit != XDEFNO) nof_args++; | |
4643 | if (nof_args > 1) { | |
4644 | src = mputprintf(src, "min_of_ints(%d, limit", nof_args); | |
4645 | for (j = 0; j < raw_options[i].lengthof; j++) { | |
4646 | int field_index = raw_options[i].lengthoffield[j]; | |
4647 | if (i > field_index && sdef->elements[field_index].raw.unit != -1) | |
4648 | src = mputprintf(src, ", value_of_length_field%d", field_index); | |
4649 | } | |
4650 | if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[ | |
4651 | raw_options[i].extbitgroup-1].ext_bit != XDEFNO) | |
4652 | src = mputstr(src, ", group_limit"); | |
4653 | src = mputc(src, ')'); | |
4654 | } else { | |
4655 | src = mputstr(src, "limit"); | |
4656 | } | |
4657 | return src; | |
4658 | } | |
4659 | ||
4660 | static char *genRawDecodeRecordField(char *src, const struct_def *sdef, | |
4661 | int i, const struct raw_option_struct *raw_options, boolean delayed_decode, | |
4662 | int *prev_ext_group) | |
4663 | { | |
4664 | int a; | |
4665 | if(raw_options[i].ptrbase) | |
4666 | src=mputprintf(src, | |
4667 | " start_pos_of_field%d=p_buf.get_pos_bit();\n" | |
4668 | ,i | |
4669 | ); | |
4670 | if (*prev_ext_group != raw_options[i].extbitgroup) { | |
4671 | *prev_ext_group = raw_options[i].extbitgroup; | |
4672 | if(prev_ext_group && | |
4673 | sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){ | |
4674 | if(raw_options[i].pointerof) /* pointed field */ | |
4675 | src=mputprintf(src, | |
4676 | " {size_t old_pos=p_buf.get_pos_bit();\n" | |
4677 | " if(start_of_field%d!=-1 && start_pos_of_field%d!=-1){\n" | |
4678 | " start_of_field%d=start_pos_of_field%d" | |
4679 | "+(int)field_%s%s*%d+%d;\n" | |
4680 | " p_buf.set_pos_bit(start_of_field%d);\n" | |
4681 | " limit=end_of_available_data-start_of_field%d;\n" | |
4682 | ,i | |
4683 | ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase | |
4684 | ,i | |
4685 | ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase | |
4686 | ,sdef->elements[raw_options[i].pointerof-1].name | |
4687 | ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":"" | |
4688 | ,sdef->elements[raw_options[i].pointerof-1].raw.unit | |
4689 | ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset | |
4690 | ,i,i | |
4691 | ); | |
4692 | src=mputprintf(src, | |
4693 | " {\n" | |
4694 | " cbyte* data=p_buf.get_read_data();\n" | |
4695 | " int count=1;\n" | |
4696 | " int rot=local_top_order==ORDER_LSB?0:7;\n" | |
4697 | " while(((data[count-1]>>rot)&0x01)==%d && count*8<" | |
4698 | "(int)limit) count++;\n" | |
4699 | " if(limit) group_limit=count*8;\n" | |
4700 | " }\n" | |
4701 | ,sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit== | |
4702 | XDEFYES?0:1 | |
4703 | ); | |
4704 | if(raw_options[i].pointerof) /* pointed field */ | |
4705 | src=mputstr(src, | |
4706 | " } else group_limit=0;\n" | |
4707 | " p_buf.set_pos_bit(old_pos);\n" | |
4708 | " limit=end_of_available_data-old_pos;}\n" | |
4709 | ); | |
4710 | } | |
4711 | } | |
4712 | if(sdef->elements[i].hasRaw && /* check the crosstag */ | |
4713 | sdef->elements[i].raw.crosstaglist.nElements){ | |
4714 | /* field index of the otherwise rule */ | |
4715 | int other = -1; | |
4716 | boolean first_value = TRUE; | |
4717 | int j; | |
4718 | for (j = 0; j < sdef->elements[i].raw.crosstaglist.nElements; j++) { | |
4719 | rawAST_coding_taglist* cur_choice = | |
4720 | sdef->elements[i].raw.crosstaglist.list + j; | |
4721 | if (cur_choice->nElements > 0) { | |
4722 | /* this is a normal rule */ | |
4723 | if (first_value) { | |
4724 | src = mputstr(src, " if ("); | |
4725 | first_value = FALSE; | |
4726 | } else src = mputstr(src, " else if ("); | |
4727 | src = genRawFieldChecker(src, cur_choice, TRUE); | |
4728 | /* set selected_field in the if's body */ | |
4729 | src = mputprintf(src, ") selected_field = %d;\n", | |
4730 | cur_choice->fieldnum); | |
4731 | } else { | |
4732 | /* this is an otherwise rule */ | |
4733 | other = cur_choice->fieldnum; | |
4734 | } | |
4735 | } | |
4736 | /* set selected_field to the field index of the otherwise rule or -1 */ | |
4737 | src = mputprintf(src, " else selected_field = %d;\n", other); | |
4738 | } | |
4739 | /* check the presence of optional field*/ | |
4740 | if(sdef->elements[i].isOptional){ | |
4741 | /* check if enough bits to decode the field*/ | |
4742 | src = mputstr(src, " if (limit > 0"); | |
4743 | for (a = 0; a < raw_options[i].lengthof; a++){ | |
4744 | int field_index = raw_options[i].lengthoffield[a]; | |
4745 | if (i > field_index) src = mputprintf(src, | |
4746 | " && value_of_length_field%d > 0", field_index); | |
4747 | } | |
4748 | if (raw_options[i].extbitgroup && | |
4749 | sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){ | |
4750 | src = mputstr(src, " && group_limit > 0"); | |
4751 | } | |
4752 | if(raw_options[i].pointerof){ /* valid pointer?*/ | |
4753 | src=mputprintf(src, | |
4754 | " && start_of_field%d!=-1 && start_pos_of_field%d!=-1" | |
4755 | ,i,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase | |
4756 | ); | |
4757 | } | |
4758 | if(sdef->elements[i].hasRaw && | |
4759 | sdef->elements[i].raw.presence.nElements) | |
4760 | { | |
4761 | src = mputstr(src, " && "); | |
4762 | if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, '('); | |
4763 | src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, TRUE); | |
4764 | if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, ')'); | |
4765 | } | |
4766 | if(sdef->elements[i].hasRaw && | |
4767 | sdef->elements[i].raw.crosstaglist.nElements) | |
4768 | { | |
4769 | src=mputstr(src, | |
4770 | "&& selected_field!=-1" | |
4771 | ); | |
4772 | } | |
4773 | src=mputstr(src, | |
4774 | "){\n" | |
4775 | ); | |
4776 | } | |
4777 | if(raw_options[i].pointerof){ /* pointed field */ | |
4778 | src=mputprintf(src, | |
4779 | " start_of_field%d=start_pos_of_field%d" | |
4780 | "+(int)field_%s%s*%d+%d;\n" | |
4781 | ,i | |
4782 | ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase | |
4783 | ,sdef->elements[raw_options[i].pointerof-1].name | |
4784 | ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":"" | |
4785 | ,sdef->elements[raw_options[i].pointerof-1].raw.unit | |
4786 | ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset | |
4787 | ); | |
4788 | src=mputprintf(src, | |
4789 | " p_buf.set_pos_bit(start_of_field%d);\n" | |
4790 | " limit=end_of_available_data-start_of_field%d;\n" | |
4791 | ,i,i | |
4792 | ); | |
4793 | } | |
4794 | /* decoding of normal field */ | |
4795 | if (sdef->elements[i].isOptional) src = mputstr(src, | |
4796 | " size_t fl_start_pos = p_buf.get_pos_bit();\n"); | |
4797 | src = mputprintf(src, | |
4798 | " decoded_field_length = field_%s%s.RAW_decode(%s_descr_, p_buf, ", | |
4799 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", | |
4800 | sdef->elements[i].typedescrname); | |
4801 | if (delayed_decode) { | |
4802 | /* the fixed field length is used as limit in case of delayed decoding */ | |
4803 | src = mputprintf(src, "%d", sdef->elements[i].raw.length); | |
4804 | } else { | |
4805 | src = genRawFieldDecodeLimit(src, sdef, i, raw_options); | |
4806 | } | |
4807 | src = mputprintf(src, ", local_top_order, %s", | |
4808 | sdef->elements[i].isOptional ? "TRUE" : "no_err"); | |
4809 | if (sdef->elements[i].hasRaw && | |
4810 | sdef->elements[i].raw.crosstaglist.nElements > 0) | |
4811 | src = mputstr(src, ", selected_field"); | |
4812 | for (a = 0; a < raw_options[i].lengthof; a++) { | |
4813 | int field_index = raw_options[i].lengthoffield[a]; | |
4814 | /* number of elements in 'record of' or 'set of' */ | |
4815 | if (sdef->elements[field_index].raw.unit == -1) { | |
4816 | src = mputprintf(src, ", value_of_length_field%d", field_index); | |
4817 | break; | |
4818 | } | |
4819 | } | |
4820 | src = mputstr(src, ");\n"); | |
4821 | if (delayed_decode) { | |
4822 | src = mputprintf(src, " if (decoded_field_length != %d) return -1;\n", | |
4823 | sdef->elements[i].raw.length); | |
4824 | } else if (sdef->elements[i].isOptional) { | |
4825 | src = mputprintf(src, " if (decoded_field_length < 1) {\n" | |
4826 | " field_%s = OMIT_VALUE;\n" /* transform errors into omit */ | |
4827 | " p_buf.set_pos_bit(fl_start_pos);\n" | |
4828 | " } else {\n", sdef->elements[i].name); | |
4829 | } else { | |
4830 | src = mputstr(src, " if (decoded_field_length < 0) return decoded_field_length;\n"); | |
4831 | } | |
4832 | if(raw_options[i].tag_type && sdef->raw.taglist.list[raw_options[i].tag_type-1].nElements){ | |
4833 | rawAST_coding_taglist* cur_choice= | |
4834 | sdef->raw.taglist.list+raw_options[i].tag_type-1; | |
4835 | src=mputstr(src, | |
4836 | " if("); | |
4837 | src=genRawFieldChecker(src,cur_choice,FALSE); | |
4838 | src=mputstr(src, | |
4839 | ")"); | |
4840 | if(sdef->elements[i].isOptional){ | |
4841 | src=mputprintf(src, | |
4842 | "{\n field_%s=OMIT_VALUE;\n" | |
4843 | " p_buf.set_pos_bit(fl_start_pos);\n }\n" | |
4844 | " else {\n" | |
4845 | ,sdef->elements[i].name | |
4846 | ); | |
4847 | }else src=mputstr(src, " return -1;\n"); | |
4848 | } | |
4849 | if (!delayed_decode) { | |
4850 | src=mputstr(src, | |
4851 | " decoded_length+=decoded_field_length;\n" | |
4852 | " limit-=decoded_field_length;\n" | |
4853 | " last_decoded_pos=bigger(last_decoded_pos, p_buf.get_pos_bit());\n" | |
4854 | ); | |
4855 | } | |
4856 | if(raw_options[i].extbitgroup && | |
4857 | sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){ | |
4858 | src=mputstr(src, | |
4859 | "group_limit-=decoded_field_length;\n" | |
4860 | ); | |
4861 | } | |
4862 | if(raw_options[i].lengthto){ /* if the field is lengthto store the value*/ | |
4863 | if(sdef->elements[i].raw.lengthindex){ | |
4864 | if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){ | |
4865 | src=mputprintf(src, | |
4866 | " if(field_%s%s.%s().ispresent()){\n" | |
4867 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4868 | ,sdef->elements[i].raw.lengthindex->nthfieldname | |
4869 | ); | |
4870 | } | |
4871 | src=mputprintf(src, | |
4872 | " value_of_length_field%d+=(int)field_%s%s.%s%s()*%d;\n" | |
4873 | ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4874 | ,sdef->elements[i].raw.lengthindex->nthfieldname | |
4875 | ,sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD?"()":"" | |
4876 | ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit | |
4877 | ); | |
4878 | if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){ | |
4879 | src=mputstr(src, | |
4880 | " }\n" | |
4881 | ); | |
4882 | } | |
4883 | } | |
4884 | else if(sdef->elements[i].raw.union_member_num){ | |
4885 | int m; | |
4886 | src = mputprintf(src, " switch (field_%s%s.get_selection()) {\n", | |
4887 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : ""); | |
4888 | for (m = 1; m < sdef->elements[i].raw.union_member_num + 1; m++) { | |
4889 | src = mputprintf(src, " case %s%s%s:\n" | |
4890 | " value_of_length_field%d += (int)field_%s%s.%s() * %d;\n" | |
4891 | " break;\n", sdef->elements[i].raw.member_name[0], | |
4892 | "::ALT_", | |
4893 | sdef->elements[i].raw.member_name[m], i, sdef->elements[i].name, | |
4894 | sdef->elements[i].isOptional ? "()" : "", | |
4895 | sdef->elements[i].raw.member_name[m], | |
4896 | sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit); | |
4897 | } | |
4898 | src = mputprintf(src, " default:\n" | |
4899 | " value_of_length_field%d = 0;\n" | |
4900 | " }\n", i); | |
4901 | } | |
4902 | else{ | |
4903 | src=mputprintf(src, | |
4904 | " value_of_length_field%d+=(int)field_%s%s*%d;\n" | |
4905 | ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4906 | ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit | |
4907 | ); | |
4908 | } | |
4909 | } | |
4910 | if(raw_options[i].pointerto){ /* store the start of pointed field*/ | |
4911 | src=mputprintf(src, | |
4912 | " start_of_field%d=(int)field_%s%s+%d?1:-1;\n" | |
4913 | ,sdef->elements[i].raw.pointerto | |
4914 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" | |
4915 | ,sdef->elements[i].raw.ptroffset | |
4916 | ); | |
4917 | } | |
4918 | if (!delayed_decode) { | |
4919 | /* mark the used bits in length area*/ | |
4920 | for (a = 0; a < raw_options[i].lengthof; a++) { | |
4921 | int field_index = raw_options[i].lengthoffield[a]; | |
4922 | src = mputprintf(src, | |
4923 | " value_of_length_field%d -= decoded_field_length;\n", field_index); | |
4924 | if (i == field_index) src = mputprintf(src, | |
4925 | " if (value_of_length_field%d < 0) return -1;\n", field_index); | |
4926 | } | |
4927 | } | |
4928 | if(sdef->elements[i].isOptional){ | |
4929 | src=mputprintf(src, | |
4930 | " }\n }\n%s" | |
4931 | " else field_%s=OMIT_VALUE;\n" | |
4932 | ,raw_options[i].tag_type?" }\n":"",sdef->elements[i].name | |
4933 | ); | |
4934 | } | |
4935 | return src; | |
4936 | } | |
4937 | ||
4938 | #ifdef __SUNPRO_C | |
4939 | #define SUNPRO_PUBLIC "public:\n" | |
4940 | #define SUNPRO_PRIVATE "private:\n" | |
4941 | #else | |
4942 | #define SUNPRO_PUBLIC | |
4943 | #define SUNPRO_PRIVATE | |
4944 | #endif | |
4945 | ||
4946 | void defRecordTemplate1(const struct_def *sdef, output_struct *output) | |
4947 | { | |
4948 | int i; | |
4949 | const char *name = sdef->name, *dispname = sdef->dispname; | |
4950 | const char* kind_str = sdef->kind == SET ? "set" : "record"; | |
4951 | char *def = NULL, *src = NULL; | |
4952 | ||
4953 | size_t mandatory_fields_count; | |
4954 | ||
4955 | /* class declaration */ | |
4956 | output->header.class_decls = mputprintf(output->header.class_decls, | |
4957 | "class %s_template;\n", name); | |
4958 | ||
4959 | if(sdef->nElements <= 0) { | |
4960 | defEmptyRecordTemplate(name, dispname, output); | |
4961 | return; | |
4962 | } | |
4963 | ||
4964 | /* template class definition */ | |
4965 | def = mputprintf(def, "class %s_template : public Base_Template {\n", name); | |
4966 | ||
4967 | /* data members */ | |
4968 | def = mputprintf(def, | |
4969 | SUNPRO_PUBLIC | |
4970 | "struct single_value_struct;\n" | |
4971 | SUNPRO_PRIVATE | |
4972 | "union {\n" | |
4973 | "single_value_struct *single_value;\n" | |
4974 | "struct {\n" | |
4975 | "unsigned int n_values;\n" | |
4976 | "%s_template *list_value;\n" | |
4977 | "} value_list;\n" | |
4978 | "};\n\n", name); | |
4979 | /* the definition of single_value_struct must be put into the source file | |
4980 | * because the types of optional fields may be incomplete in this position | |
4981 | * of header file (e.g. due to type recursion) */ | |
4982 | src = mputprintf(src, "struct %s_template::single_value_struct {\n", name); | |
4983 | for (i = 0; i < sdef->nElements; i++) { | |
4984 | src = mputprintf(src, "%s_template field_%s;\n", | |
4985 | sdef->elements[i].type, sdef->elements[i].name); | |
4986 | } | |
4987 | src = mputstr(src, "};\n\n"); | |
4988 | ||
4989 | /* set_specific function (used in field access members) */ | |
4990 | def = mputstr(def, "void set_specific();\n"); | |
4991 | src = mputprintf(src, "void %s_template::set_specific()\n" | |
4992 | "{\n" | |
4993 | "if (template_selection != SPECIFIC_VALUE) {\n" | |
4994 | "template_sel old_selection = template_selection;\n" | |
4995 | "clean_up();\n" | |
4996 | "single_value = new single_value_struct;\n" | |
4997 | "set_selection(SPECIFIC_VALUE);\n" | |
4998 | "if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {\n", | |
4999 | name); | |
5000 | for (i = 0; i < sdef->nElements; i++) { | |
5001 | src = mputprintf(src, "single_value->field_%s = %s;\n", | |
5002 | sdef->elements[i].name, | |
5003 | sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE"); | |
5004 | } | |
5005 | src = mputstr(src, "}\n" | |
5006 | "}\n" | |
5007 | "}\n\n"); | |
5008 | ||
5009 | /* copy_value function */ | |
5010 | def = mputprintf(def, "void copy_value(const %s& other_value);\n", name); | |
5011 | src = mputprintf(src, | |
5012 | "void %s_template::copy_value(const %s& other_value)\n" | |
5013 | "{\n" | |
5014 | "single_value = new single_value_struct;\n", name, name); | |
5015 | for (i = 0; i < sdef->nElements; i++) { | |
5016 | src = mputprintf(src, | |
5017 | "if (other_value.%s().is_bound()) {\n", sdef->elements[i].name); | |
5018 | if (sdef->elements[i].isOptional) { | |
5019 | /* If the value is present, "reach into" the OPTIONAL with operator() | |
5020 | * and pass the contained object to the template's constructor. | |
5021 | * Else set the template to omit. */ | |
5022 | src = mputprintf(src, | |
5023 | " if (other_value.%s().ispresent()) single_value->field_%s = " | |
5024 | "other_value.%s()();\n" | |
5025 | " else single_value->field_%s = OMIT_VALUE;\n", | |
5026 | sdef->elements[i].name, sdef->elements[i].name, | |
5027 | sdef->elements[i].name, sdef->elements[i].name); | |
5028 | } else { | |
5029 | src = mputprintf(src, | |
5030 | " single_value->field_%s = other_value.%s();\n", | |
5031 | sdef->elements[i].name, sdef->elements[i].name); | |
5032 | } | |
5033 | src = mputprintf(src, "} else {\n" | |
5034 | " single_value->field_%s.clean_up();\n" | |
5035 | "}\n", sdef->elements[i].name); | |
5036 | } | |
5037 | src = mputstr(src, "set_selection(SPECIFIC_VALUE);\n" | |
5038 | "}\n\n"); | |
5039 | ||
5040 | /* copy_template function */ | |
5041 | def = mputprintf(def, "void copy_template(const %s_template& " | |
5042 | "other_value);\n\n", name); | |
5043 | src = mputprintf(src, | |
5044 | "void %s_template::copy_template(const %s_template& other_value)\n" | |
5045 | "{\n" | |
5046 | "switch (other_value.template_selection) {\n" | |
5047 | "case SPECIFIC_VALUE:\n", name, name); | |
5048 | src = mputstr(src, | |
5049 | "single_value = new single_value_struct;\n"); | |
5050 | for (i = 0; i < sdef->nElements; i++) { | |
5051 | src = mputprintf(src, | |
5052 | "if (UNINITIALIZED_TEMPLATE != other_value.%s().get_selection()) {\n", | |
5053 | sdef->elements[i].name); | |
5054 | src = mputprintf(src, | |
5055 | "single_value->field_%s = other_value.%s();\n", | |
5056 | sdef->elements[i].name, sdef->elements[i].name); | |
5057 | src = mputprintf(src, "} else {\n" | |
5058 | "single_value->field_%s.clean_up();\n" | |
5059 | "}\n", sdef->elements[i].name); | |
5060 | } | |
5061 | src = mputprintf(src, | |
5062 | "case OMIT_VALUE:\n" | |
5063 | "case ANY_VALUE:\n" | |
5064 | "case ANY_OR_OMIT:\n" | |
5065 | "break;\n" | |
5066 | "case VALUE_LIST:\n" | |
5067 | "case COMPLEMENTED_LIST:\n" | |
5068 | "value_list.n_values = other_value.value_list.n_values;\n" | |
5069 | "value_list.list_value = new %s_template[value_list.n_values];\n" | |
5070 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
5071 | "list_count++)\n" | |
5072 | "value_list.list_value[list_count].copy_template(" | |
5073 | "other_value.value_list.list_value[list_count]);\n" | |
5074 | "break;\n" | |
5075 | "default:\n" | |
5076 | "TTCN_error(\"Copying an uninitialized/unsupported template of type " | |
5077 | "%s.\");\n" | |
5078 | "break;\n" | |
5079 | "}\n" | |
5080 | "set_selection(other_value);\n" | |
5081 | "}\n\n", name, dispname); | |
5082 | ||
5083 | /* default constructor */ | |
5084 | def = mputprintf(def, "public:\n" | |
5085 | "%s_template();\n", name); | |
5086 | src = mputprintf(src, "%s_template::%s_template()\n" | |
5087 | "{\n" | |
5088 | "}\n\n", name, name); | |
5089 | ||
5090 | /* constructor t1_template(template_sel other_value) */ | |
5091 | def = mputprintf(def, "%s_template(template_sel other_value);\n", name); | |
5092 | src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n" | |
5093 | " : Base_Template(other_value)\n" | |
5094 | "{\n" | |
5095 | "check_single_selection(other_value);\n" | |
5096 | "}\n\n", name, name); | |
5097 | ||
5098 | /* constructor t1_template(const t1& other_value) */ | |
5099 | def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name); | |
5100 | src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n" | |
5101 | "{\n" | |
5102 | "copy_value(other_value);\n" | |
5103 | "}\n\n", name, name, name); | |
5104 | ||
5105 | /* constructor t1_template(const OPTIONAL<t1>& other_value) */ | |
5106 | def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n", | |
5107 | name, name); | |
5108 | src = mputprintf(src, | |
5109 | "%s_template::%s_template(const OPTIONAL<%s>& other_value)\n" | |
5110 | "{\n" | |
5111 | "switch (other_value.get_selection()) {\n" | |
5112 | "case OPTIONAL_PRESENT:\n" | |
5113 | "copy_value((const %s&)other_value);\n" | |
5114 | "break;\n" | |
5115 | "case OPTIONAL_OMIT:\n" | |
5116 | "set_selection(OMIT_VALUE);\n" | |
5117 | "break;\n" | |
5118 | "default:\n" | |
5119 | "TTCN_error(\"Creating a template of type %s from an unbound optional " | |
5120 | "field.\");\n" | |
5121 | "}\n" | |
5122 | "}\n\n", name, name, name, name, dispname); | |
5123 | ||
5124 | /* copy constructor */ | |
5125 | def = mputprintf(def, "%s_template(const %s_template& other_value);\n", | |
5126 | name, name); | |
5127 | src = mputprintf(src, "%s_template::%s_template(const %s_template& " | |
5128 | "other_value)\n" | |
5129 | ": Base_Template()\n" /* yes, the base class _default_ constructor */ | |
5130 | "{\n" | |
5131 | "copy_template(other_value);\n" | |
5132 | "}\n\n", name, name, name); | |
5133 | ||
5134 | /* destructor */ | |
5135 | def = mputprintf(def, "~%s_template();\n", name); | |
5136 | src = mputprintf(src, "%s_template::~%s_template()\n" | |
5137 | "{\n" | |
5138 | "clean_up();\n" | |
5139 | "}\n\n", name, name); | |
5140 | ||
5141 | /* assignment operator <- template_sel */ | |
5142 | def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n", | |
5143 | name); | |
5144 | src = mputprintf(src, | |
5145 | "%s_template& %s_template::operator=(template_sel other_value)\n" | |
5146 | "{\n" | |
5147 | "check_single_selection(other_value);\n" | |
5148 | "clean_up();\n" | |
5149 | "set_selection(other_value);\n" | |
5150 | "return *this;\n" | |
5151 | "}\n\n", name, name); | |
5152 | ||
5153 | /* assignment operator <- value */ | |
5154 | def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n", | |
5155 | name, name); | |
5156 | ||
5157 | src = mputprintf(src, | |
5158 | "%s_template& %s_template::operator=(const %s& other_value)\n" | |
5159 | "{\n" | |
5160 | "clean_up();\n" | |
5161 | "copy_value(other_value);\n" | |
5162 | "return *this;\n" | |
5163 | "}\n\n", name, name, name); | |
5164 | ||
5165 | /* assignment operator <- optional value */ | |
5166 | def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& " | |
5167 | "other_value);\n", name, name); | |
5168 | ||
5169 | src = mputprintf(src, | |
5170 | "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n" | |
5171 | "{\n" | |
5172 | "clean_up();\n" | |
5173 | "switch (other_value.get_selection()) {\n" | |
5174 | "case OPTIONAL_PRESENT:\n" | |
5175 | "copy_value((const %s&)other_value);\n" | |
5176 | "break;\n" | |
5177 | "case OPTIONAL_OMIT:\n" | |
5178 | "set_selection(OMIT_VALUE);\n" | |
5179 | "break;\n" | |
5180 | "default:\n" | |
5181 | "TTCN_error(\"Assignment of an unbound optional field to a template " | |
5182 | "of type %s.\");\n" | |
5183 | "}\n" | |
5184 | "return *this;\n" | |
5185 | "}\n\n", name, name, name, name, dispname); | |
5186 | ||
5187 | /* assignment operator <- template*/ | |
5188 | def = mputprintf(def, | |
5189 | "%s_template& operator=(const %s_template& other_value);\n", | |
5190 | name, name); | |
5191 | ||
5192 | src = mputprintf(src, | |
5193 | "%s_template& %s_template::operator=(const %s_template& other_value)\n" | |
5194 | "{\n" | |
5195 | "if (&other_value != this) {\n" | |
5196 | "clean_up();\n" | |
5197 | "copy_template(other_value);\n" | |
5198 | "}\n" | |
5199 | "return *this;\n" | |
5200 | "}\n\n", name, name, name); | |
5201 | ||
5202 | /* match operation (template matching) */ | |
3abe9331 | 5203 | def = mputprintf(def, "boolean match(const %s& other_value, boolean legacy " |
5204 | "= FALSE) const;\n", name); | |
970ed795 EL |
5205 | |
5206 | src = mputprintf(src, | |
3abe9331 | 5207 | "boolean %s_template::match(const %s& other_value, boolean legacy) const\n" |
970ed795 EL |
5208 | "{\n" |
5209 | "if (!other_value.is_bound()) return FALSE;\n" | |
5210 | "switch (template_selection) {\n" | |
5211 | "case ANY_VALUE:\n" | |
5212 | "case ANY_OR_OMIT:\n" | |
5213 | "return TRUE;\n" | |
5214 | "case OMIT_VALUE:\n" | |
5215 | "return FALSE;\n" | |
5216 | "case SPECIFIC_VALUE:\n", name, name); | |
5217 | for (i = 0; i < sdef->nElements; i++) { | |
5218 | src = mputprintf(src,"if(!other_value.%s().is_bound()) return FALSE;\n", sdef->elements[i].name); | |
5219 | if (sdef->elements[i].isOptional) src = mputprintf(src, | |
5220 | "if((other_value.%s().ispresent() ? " | |
3abe9331 | 5221 | "!single_value->field_%s.match((const %s&)other_value.%s(), legacy) : " |
5222 | "!single_value->field_%s.match_omit(legacy)))", | |
970ed795 EL |
5223 | sdef->elements[i].name, sdef->elements[i].name, |
5224 | sdef->elements[i].type, sdef->elements[i].name, | |
5225 | sdef->elements[i].name); | |
5226 | else src = mputprintf(src, | |
3abe9331 | 5227 | "if(!single_value->field_%s.match(other_value.%s(), legacy))", |
970ed795 EL |
5228 | sdef->elements[i].name, sdef->elements[i].name); |
5229 | src = mputstr(src, "return FALSE;\n"); | |
5230 | } | |
5231 | src = mputprintf(src, | |
5232 | "return TRUE;\n" | |
5233 | "case VALUE_LIST:\n" | |
5234 | "case COMPLEMENTED_LIST:\n" | |
5235 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
5236 | "list_count++)\n" | |
3abe9331 | 5237 | "if (value_list.list_value[list_count].match(other_value, legacy)) " |
970ed795 EL |
5238 | "return template_selection == VALUE_LIST;\n" |
5239 | "return template_selection == COMPLEMENTED_LIST;\n" | |
5240 | "default:\n" | |
5241 | "TTCN_error(\"Matching an uninitialized/unsupported template of " | |
5242 | "type %s.\");\n" | |
5243 | "}\n" | |
5244 | "return FALSE;\n" | |
5245 | "}\n\n", dispname); | |
5246 | ||
5247 | /* is_bound */ | |
5248 | def = mputstr(def, "boolean is_bound() const;\n"); | |
5249 | ||
5250 | src = mputprintf(src, "boolean %s_template::is_bound() const\n" | |
5251 | "{\n" | |
5252 | "if (template_selection == UNINITIALIZED_TEMPLATE && !is_ifpresent) " | |
5253 | "return FALSE;\n", name); | |
5254 | src = mputstr(src, "if (template_selection != SPECIFIC_VALUE) return TRUE;\n"); | |
5255 | for (i = 0; i < sdef->nElements; i++) { | |
5256 | if (sdef->elements[i].isOptional) { | |
5257 | src = mputprintf(src, | |
5258 | "if (single_value->field_%s.is_omit() ||" | |
5259 | " single_value->field_%s.is_bound()) return TRUE;\n", | |
5260 | sdef->elements[i].name, sdef->elements[i].name); | |
5261 | } else { | |
5262 | src = mputprintf(src, | |
5263 | "if (single_value->field_%s.is_bound()) return TRUE;\n", | |
5264 | sdef->elements[i].name); | |
5265 | } | |
5266 | } | |
5267 | src = mputstr(src, "return FALSE;\n" | |
5268 | "}\n\n"); | |
5269 | ||
5270 | /* is_value */ | |
5271 | def = mputstr(def, "boolean is_value() const;\n"); | |
5272 | ||
5273 | src = mputprintf(src, "boolean %s_template::is_value() const\n" | |
5274 | "{\n" | |
5275 | "if (template_selection != SPECIFIC_VALUE || is_ifpresent) " | |
5276 | "return FALSE;\n", name); | |
5277 | for (i = 0; i < sdef->nElements; i++) { | |
5278 | if (sdef->elements[i].isOptional) { | |
5279 | src = mputprintf(src, | |
5280 | "if (!single_value->field_%s.is_omit() &&" | |
5281 | " !single_value->field_%s.is_value()) return FALSE;\n", | |
5282 | sdef->elements[i].name, sdef->elements[i].name); | |
5283 | } else { | |
5284 | src = mputprintf(src, | |
5285 | "if (!single_value->field_%s.is_value()) return FALSE;\n", | |
5286 | sdef->elements[i].name); | |
5287 | } | |
5288 | } | |
5289 | src = mputstr(src, "return TRUE;\n" | |
5290 | "}\n\n"); | |
5291 | ||
5292 | /* clean_up function */ | |
5293 | def = mputstr(def, "void clean_up();\n"); | |
5294 | src = mputprintf(src, | |
5295 | "void %s_template::clean_up()\n" | |
5296 | "{\n" | |
5297 | "switch (template_selection) {\n" | |
5298 | "case SPECIFIC_VALUE:\n" | |
5299 | "delete single_value;\n" | |
5300 | "break;\n" | |
5301 | "case VALUE_LIST:\n" | |
5302 | "case COMPLEMENTED_LIST:\n" | |
5303 | "delete [] value_list.list_value;\n" | |
5304 | "default:\n" | |
5305 | "break;\n" | |
5306 | "}\n" | |
5307 | "template_selection = UNINITIALIZED_TEMPLATE;\n" | |
5308 | "}\n\n", name); | |
5309 | ||
5310 | /* valueof operation */ | |
5311 | def = mputprintf(def, "%s valueof() const;\n", name); | |
5312 | ||
5313 | src = mputprintf(src, "%s %s_template::valueof() const\n" | |
5314 | "{\n" | |
5315 | "if (template_selection != SPECIFIC_VALUE || is_ifpresent)\n" | |
5316 | "TTCN_error(\"Performing valueof or send operation on a non-specific " | |
5317 | "template of type %s.\");\n" | |
5318 | "%s ret_val;\n", name, name, dispname, name); | |
5319 | for (i = 0; i < sdef->nElements; i++) { | |
5320 | if (sdef->elements[i].isOptional) { | |
5321 | src = mputprintf(src, | |
5322 | "if (single_value->field_%s.is_omit()) " | |
5323 | "ret_val.%s() = OMIT_VALUE;\n" | |
5324 | "else ", | |
5325 | sdef->elements[i].name, sdef->elements[i].name); | |
5326 | } | |
5327 | src = mputprintf(src, "if (single_value->field_%s.is_bound()) {\n" | |
5328 | "ret_val.%s() = single_value->field_%s.valueof();\n" | |
5329 | "}\n", | |
5330 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); | |
5331 | } | |
5332 | src = mputstr(src, "return ret_val;\n" | |
5333 | "}\n\n"); | |
5334 | ||
5335 | /* void set_type(template_sel, int) function */ | |
5336 | def = mputstr(def, | |
5337 | "void set_type(template_sel template_type, " | |
5338 | "unsigned int list_length);\n"); | |
5339 | ||
5340 | src = mputprintf(src, | |
5341 | "void %s_template::set_type(template_sel template_type, " | |
5342 | "unsigned int list_length)\n" | |
5343 | "{\n" | |
5344 | "if (template_type != VALUE_LIST " | |
5345 | "&& template_type != COMPLEMENTED_LIST)\n" | |
5346 | "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n" | |
5347 | "clean_up();\n" | |
5348 | "set_selection(template_type);\n" | |
5349 | "value_list.n_values = list_length;\n" | |
5350 | "value_list.list_value = new %s_template[list_length];\n" | |
5351 | "}\n\n", name, dispname, name); | |
5352 | ||
5353 | /* list_item(int) function */ | |
5354 | ||
5355 | def = mputprintf(def, | |
5356 | "%s_template& list_item(unsigned int list_index) const;\n", name); | |
5357 | ||
5358 | src = mputprintf(src, | |
5359 | "%s_template& %s_template::list_item(unsigned int list_index) const\n" | |
5360 | "{\n" | |
5361 | "if (template_selection != VALUE_LIST " | |
5362 | "&& template_selection != COMPLEMENTED_LIST)\n" | |
5363 | "TTCN_error(\"Accessing a list element of a non-list template of " | |
5364 | "type %s.\");\n" | |
5365 | "if (list_index >= value_list.n_values)\n" | |
5366 | "TTCN_error(\"Index overflow in a value list template of type " | |
5367 | "%s.\");\n" | |
5368 | "return value_list.list_value[list_index];\n" | |
5369 | "}\n\n", name, name, dispname, dispname); | |
5370 | ||
5371 | /* template field access functions (non-const & const) */ | |
5372 | for (i = 0; i < sdef->nElements; i++) { | |
5373 | def = mputprintf(def, "%s_template& %s();\n", | |
5374 | sdef->elements[i].type, sdef->elements[i].name); | |
5375 | src = mputprintf(src, "%s_template& %s_template::%s()\n" | |
5376 | "{\n" | |
5377 | "set_specific();\n" | |
5378 | "return single_value->field_%s;\n" | |
5379 | "}\n\n", | |
5380 | sdef->elements[i].type, name, sdef->elements[i].name, | |
5381 | sdef->elements[i].name); | |
5382 | def = mputprintf(def, "const %s_template& %s() const;\n", | |
5383 | sdef->elements[i].type, sdef->elements[i].name); | |
5384 | src = mputprintf(src, "const %s_template& %s_template::%s() const\n" | |
5385 | "{\n" | |
5386 | "if (template_selection != SPECIFIC_VALUE)\n" | |
5387 | "TTCN_error(\"Accessing field %s of a non-specific " | |
5388 | "template of type %s.\");\n" | |
5389 | "return single_value->field_%s;\n" | |
5390 | "}\n\n", | |
5391 | sdef->elements[i].type, name, sdef->elements[i].name, | |
5392 | sdef->elements[i].dispname, dispname, sdef->elements[i].name); | |
5393 | } | |
5394 | ||
5395 | /* sizeof operation */ | |
5396 | def = mputstr(def, "int size_of() const;\n"); | |
5397 | src = mputprintf(src, | |
5398 | "int %s_template::size_of() const\n" | |
5399 | "{\n" | |
5400 | " if (is_ifpresent) TTCN_error(\"Performing sizeof() operation on a " | |
5401 | "template of type %s which has an ifpresent attribute.\");\n" | |
5402 | " switch (template_selection)\n" | |
5403 | " {\n" | |
5404 | " case SPECIFIC_VALUE:\n", | |
5405 | name, dispname); | |
5406 | mandatory_fields_count = 0; | |
5407 | for (i = 0; i < sdef->nElements; i++) | |
5408 | if (!sdef->elements[i].isOptional) mandatory_fields_count++; | |
5409 | if(sdef->nElements == mandatory_fields_count){ | |
5410 | src = mputprintf(src," return %lu;\n", | |
5411 | (unsigned long) mandatory_fields_count); | |
5412 | }else{ | |
5413 | src = mputprintf(src, | |
5414 | " {" | |
5415 | " int ret_val = %lu;\n", (unsigned long) mandatory_fields_count); | |
5416 | for (i = 0; i < sdef->nElements; i++) | |
5417 | if (sdef->elements[i].isOptional) | |
5418 | src = mputprintf(src, | |
5419 | " if (single_value->field_%s.is_present()) ret_val++;\n", | |
5420 | sdef->elements[i].name); | |
5421 | src = mputstr(src, | |
5422 | " return ret_val;\n" | |
5423 | " }\n"); | |
5424 | } | |
5425 | src = mputprintf(src, | |
5426 | ||
5427 | " case VALUE_LIST:\n" | |
5428 | " {\n" | |
5429 | " if (value_list.n_values<1)\n" | |
5430 | " TTCN_error(\"Internal error: Performing sizeof() operation on a " | |
5431 | "template of type %s containing an empty list.\");\n" | |
5432 | " int item_size = value_list.list_value[0].size_of();\n" | |
5433 | " for (unsigned int l_idx = 1; l_idx < value_list.n_values; l_idx++)\n" | |
5434 | " {\n" | |
5435 | " if (value_list.list_value[l_idx].size_of()!=item_size)\n" | |
5436 | " TTCN_error(\"Performing sizeof() operation on a template " | |
5437 | "of type %s containing a value list with different sizes.\");\n" | |
5438 | " }\n" | |
5439 | " return item_size;\n" | |
5440 | " }\n" | |
5441 | " case OMIT_VALUE:\n" | |
5442 | " TTCN_error(\"Performing sizeof() operation on a template of type %s " | |
5443 | "containing omit value.\");\n" | |
5444 | " case ANY_VALUE:\n" | |
5445 | " case ANY_OR_OMIT:\n" | |
5446 | " TTCN_error(\"Performing sizeof() operation on a template of type %s " | |
5447 | "containing */? value.\");\n" | |
5448 | " case COMPLEMENTED_LIST:\n" | |
5449 | " TTCN_error(\"Performing sizeof() operation on a template of type %s " | |
5450 | "containing complemented list.\");\n" | |
5451 | " default:\n" | |
5452 | " TTCN_error(\"Performing sizeof() operation on an " | |
5453 | "uninitialized/unsupported template of type %s.\");\n" | |
5454 | " }\n" | |
5455 | " return 0;\n" | |
5456 | "}\n\n", | |
5457 | dispname,dispname,dispname,dispname,dispname,dispname); | |
5458 | ||
5459 | /* log function */ | |
5460 | def = mputstr(def, "void log() const;\n"); | |
5461 | src = mputprintf(src, | |
5462 | "void %s_template::log() const\n" | |
5463 | "{\n" | |
5464 | "switch (template_selection) {\n" | |
5465 | "case SPECIFIC_VALUE:\n", name); | |
5466 | for (i = 0; i < sdef->nElements; i++) { | |
5467 | src = mputstr(src, "TTCN_Logger::log_event_str(\""); | |
5468 | if (i == 0) src = mputc(src, '{'); | |
5469 | else src = mputc(src, ','); | |
5470 | src = mputprintf(src, " %s := \");\n" | |
5471 | "single_value->field_%s.log();\n", | |
5472 | sdef->elements[i].dispname, sdef->elements[i].name); | |
5473 | } | |
5474 | src = mputstr(src, | |
5475 | "TTCN_Logger::log_event_str(\" }\");\n" | |
5476 | "break;\n" | |
5477 | "case COMPLEMENTED_LIST:\n" | |
5478 | "TTCN_Logger::log_event_str(\"complement \");\n" | |
5479 | "case VALUE_LIST:\n" | |
5480 | "TTCN_Logger::log_char('(');\n" | |
5481 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
5482 | "list_count++) {\n" | |
5483 | "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n" | |
5484 | "value_list.list_value[list_count].log();\n" | |
5485 | "}\n" | |
5486 | "TTCN_Logger::log_char(')');\n" | |
5487 | "break;\n" | |
5488 | "default:\n" | |
5489 | "log_generic();\n" | |
5490 | "}\n" | |
5491 | "log_ifpresent();\n" | |
5492 | "}\n\n"); | |
5493 | ||
5494 | /* log_match function */ | |
3abe9331 | 5495 | def = mputprintf(def, "void log_match(const %s& match_value, " |
5496 | "boolean legacy = FALSE) const;\n", name); | |
970ed795 | 5497 | src = mputprintf(src, |
3abe9331 | 5498 | "void %s_template::log_match(const %s& match_value, boolean legacy) const\n" |
5499 | "{\n" | |
970ed795 EL |
5500 | "if(TTCN_Logger::VERBOSITY_COMPACT" |
5501 | " == TTCN_Logger::get_matching_verbosity()){\n" | |
3abe9331 | 5502 | "if(match(match_value, legacy)){\n" |
970ed795 EL |
5503 | "TTCN_Logger::print_logmatch_buffer();\n" |
5504 | "TTCN_Logger::log_event_str(\" matched\");\n" | |
5505 | "} else{\n" | |
5506 | "if (template_selection == SPECIFIC_VALUE) {\n" | |
5507 | "size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();\n" | |
5508 | , name, name); | |
5509 | for (i = 0; i < sdef->nElements; i++) { | |
5510 | if (sdef->elements[i].isOptional){ | |
5511 | src = mputprintf(src, | |
5512 | "if (match_value.%s().ispresent()){\n" | |
3abe9331 | 5513 | "if(!single_value->field_%s.match(match_value.%s(), legacy)){\n" |
970ed795 | 5514 | "TTCN_Logger::log_logmatch_info(\".%s\");\n" |
3abe9331 | 5515 | "single_value->field_%s.log_match(match_value.%s(), legacy);\n" |
970ed795 EL |
5516 | "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n" |
5517 | "}\n" | |
5518 | "} else {\n" | |
3abe9331 | 5519 | "if (!single_value->field_%s.match_omit(legacy)){\n " |
970ed795 EL |
5520 | "TTCN_Logger::log_logmatch_info(\".%s := omit with \");\n" |
5521 | "TTCN_Logger::print_logmatch_buffer();\n" | |
5522 | "single_value->field_%s.log();\n" | |
5523 | "TTCN_Logger::log_event_str(\" unmatched\");\n" | |
5524 | "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n" | |
5525 | "}\n" | |
5526 | "}\n" | |
5527 | , sdef->elements[i].name, sdef->elements[i].name, | |
5528 | sdef->elements[i].name, sdef->elements[i].dispname, | |
5529 | sdef->elements[i].name, sdef->elements[i].name, | |
5530 | sdef->elements[i].name, sdef->elements[i].dispname, | |
5531 | sdef->elements[i].name); | |
5532 | }else{ | |
5533 | src = mputprintf(src, | |
3abe9331 | 5534 | "if(!single_value->field_%s.match(match_value.%s(), legacy)){\n" |
970ed795 | 5535 | "TTCN_Logger::log_logmatch_info(\".%s\");\n" |
3abe9331 | 5536 | "single_value->field_%s.log_match(match_value.%s(), legacy);\n" |
970ed795 EL |
5537 | "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n" |
5538 | "}\n",sdef->elements[i].name, sdef->elements[i].name, | |
5539 | sdef->elements[i].dispname, sdef->elements[i].name, | |
5540 | sdef->elements[i].name); | |
5541 | } | |
5542 | } | |
5543 | ||
5544 | src = mputstr(src,"}else {\n" | |
5545 | "TTCN_Logger::print_logmatch_buffer();\n" | |
5546 | "match_value.log();\n" | |
5547 | "TTCN_Logger::log_event_str(\" with \");\n" | |
5548 | "log();\n" | |
5549 | "TTCN_Logger::log_event_str(\" unmatched\");\n" | |
5550 | "}\n" | |
5551 | "}\n" | |
5552 | "return;\n" | |
5553 | "}\n" | |
5554 | "if (template_selection == SPECIFIC_VALUE) {\n"); | |
5555 | for (i = 0; i < sdef->nElements; i++) { | |
5556 | src = mputstr(src, "TTCN_Logger::log_event_str(\""); | |
5557 | if (i == 0) src = mputc(src, '{'); | |
5558 | else src = mputc(src, ','); | |
5559 | src = mputprintf(src, " %s := \");\n", sdef->elements[i].dispname); | |
5560 | if (sdef->elements[i].isOptional) src = mputprintf(src, | |
5561 | "if (match_value.%s().ispresent()) " | |
3abe9331 | 5562 | "single_value->field_%s.log_match(match_value.%s(), legacy);\n" |
970ed795 EL |
5563 | "else {\n" |
5564 | "TTCN_Logger::log_event_str(\"omit with \");\n" | |
5565 | "single_value->field_%s.log();\n" | |
3abe9331 | 5566 | "if (single_value->field_%s.match_omit(legacy)) " |
970ed795 EL |
5567 | "TTCN_Logger::log_event_str(\" matched\");\n" |
5568 | "else TTCN_Logger::log_event_str(\" unmatched\");\n" | |
5569 | "}\n", | |
5570 | sdef->elements[i].name, sdef->elements[i].name, | |
5571 | sdef->elements[i].name, sdef->elements[i].name, | |
5572 | sdef->elements[i].name); | |
5573 | else src = mputprintf(src, | |
3abe9331 | 5574 | "single_value->field_%s.log_match(match_value.%s(), legacy);\n", |
970ed795 EL |
5575 | sdef->elements[i].name, sdef->elements[i].name); |
5576 | } | |
5577 | src = mputstr(src, | |
5578 | "TTCN_Logger::log_event_str(\" }\");\n" | |
5579 | "} else {\n" | |
5580 | "match_value.log();\n" | |
5581 | "TTCN_Logger::log_event_str(\" with \");\n" | |
5582 | "log();\n" | |
3abe9331 | 5583 | "if (match(match_value, legacy)) TTCN_Logger::log_event_str(\" matched\");\n" |
970ed795 EL |
5584 | "else TTCN_Logger::log_event_str(\" unmatched\");\n" |
5585 | "}\n" | |
5586 | "}\n\n"); | |
5587 | ||
5588 | /*encode_text function*/ | |
5589 | def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); | |
5590 | src = mputprintf(src, | |
5591 | "void %s_template::encode_text(Text_Buf& text_buf) const\n" | |
5592 | "{\n" | |
5593 | "encode_text_base(text_buf);\n" | |
5594 | "switch (template_selection) {\n" | |
5595 | "case SPECIFIC_VALUE:\n", name); | |
5596 | for (i = 0; i < sdef->nElements; i++) { | |
5597 | src = mputprintf(src, "single_value->field_%s.encode_text(text_buf);\n", | |
5598 | sdef->elements[i].name); | |
5599 | } | |
5600 | src = mputprintf(src, | |
5601 | "case OMIT_VALUE:\n" | |
5602 | "case ANY_VALUE:\n" | |
5603 | "case ANY_OR_OMIT:\n" | |
5604 | "break;\n" | |
5605 | "case VALUE_LIST:\n" | |
5606 | "case COMPLEMENTED_LIST:\n" | |
5607 | "text_buf.push_int(value_list.n_values);\n" | |
5608 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
5609 | "list_count++)\n" | |
5610 | "value_list.list_value[list_count].encode_text(text_buf);\n" | |
5611 | "break;\n" | |
5612 | "default:\n" | |
5613 | "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported " | |
5614 | "template of type %s.\");\n" | |
5615 | "}\n" | |
5616 | "}\n\n", dispname); | |
5617 | ||
5618 | /*decode_text function*/ | |
5619 | def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); | |
5620 | src = mputprintf(src, | |
5621 | "void %s_template::decode_text(Text_Buf& text_buf)\n" | |
5622 | "{\n" | |
5623 | "clean_up();\n" | |
5624 | "decode_text_base(text_buf);\n" | |
5625 | "switch (template_selection) {\n" | |
5626 | "case SPECIFIC_VALUE:\n" | |
5627 | "single_value = new single_value_struct;\n", name); | |
5628 | for (i = 0; i < sdef->nElements; i++) { | |
5629 | src = mputprintf(src, "single_value->field_%s.decode_text(text_buf);\n", | |
5630 | sdef->elements[i].name); | |
5631 | } | |
5632 | src = mputprintf(src, | |
5633 | "case OMIT_VALUE:\n" | |
5634 | "case ANY_VALUE:\n" | |
5635 | "case ANY_OR_OMIT:\n" | |
5636 | "break;\n" | |
5637 | "case VALUE_LIST:\n" | |
5638 | "case COMPLEMENTED_LIST:\n" | |
5639 | "value_list.n_values = text_buf.pull_int().get_val();\n" | |
5640 | "value_list.list_value = new %s_template[value_list.n_values];\n" | |
5641 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
5642 | "list_count++)\n" | |
5643 | "value_list.list_value[list_count].decode_text(text_buf);\n" | |
5644 | "break;\n" | |
5645 | "default:\n" | |
5646 | "TTCN_error(\"Text decoder: An unknown/unsupported selection was " | |
5647 | "received in a template of type %s.\");\n" | |
5648 | "}\n" | |
5649 | "}\n\n", name, dispname); | |
5650 | ||
5651 | /* set_param() */ | |
5652 | def = mputstr(def, "void set_param(Module_Param& param);\n"); | |
5653 | src = mputprintf(src, | |
5654 | "void %s_template::set_param(Module_Param& param)\n" | |
5655 | "{\n" | |
5656 | " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n" | |
5657 | " param.get_id()->next_name()) {\n" | |
5658 | // Haven't reached the end of the module parameter name | |
5659 | // => the name refers to one of the fields, not to the whole record | |
5660 | " char* param_field = param.get_id()->get_current_name();\n" | |
5661 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" | |
5662 | " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n" | |
5663 | " \" name for %s template type `%s'\");\n" | |
5664 | " }\n" | |
5665 | " ", name, kind_str, dispname); | |
5666 | for (i = 0; i < sdef->nElements; i++) { | |
5667 | src = mputprintf(src, | |
5668 | "if (strcmp(\"%s\", param_field) == 0) {\n" | |
5669 | " %s().set_param(param);\n" | |
5670 | " return;\n" | |
5671 | " } else ", | |
5672 | sdef->elements[i].dispname, sdef->elements[i].name); | |
5673 | } | |
5674 | src = mputprintf(src, | |
5675 | "param.error(\"Field `%%s' not found in %s template type `%s'\", param_field);\n" | |
5676 | " }\n" | |
5677 | " param.basic_check(Module_Param::BC_TEMPLATE, \"%s template\");\n" | |
3f84031e | 5678 | " Module_Param_Ptr m_p = ¶m;\n" |
3abe9331 | 5679 | " if (param.get_type() == Module_Param::MP_Reference) {\n" |
3f84031e | 5680 | " m_p = param.get_referenced_param();\n" |
3abe9331 | 5681 | " }\n" |
3f84031e | 5682 | " switch (m_p->get_type()) {\n" |
970ed795 EL |
5683 | " case Module_Param::MP_Omit:\n" |
5684 | " *this = OMIT_VALUE;\n" | |
5685 | " break;\n" | |
5686 | " case Module_Param::MP_Any:\n" | |
5687 | " *this = ANY_VALUE;\n" | |
5688 | " break;\n" | |
5689 | " case Module_Param::MP_AnyOrNone:\n" | |
5690 | " *this = ANY_OR_OMIT;\n" | |
5691 | " break;\n" | |
5692 | " case Module_Param::MP_List_Template:\n" | |
3abe9331 | 5693 | " case Module_Param::MP_ComplementList_Template: {\n" |
3f84031e | 5694 | " %s_template new_temp;\n" |
5695 | " new_temp.set_type(m_p->get_type()==Module_Param::MP_List_Template ? " | |
5696 | "VALUE_LIST : COMPLEMENTED_LIST, m_p->get_size());\n" | |
5697 | " for (size_t p_i=0; p_i<m_p->get_size(); p_i++) {\n" | |
5698 | " new_temp.list_item(p_i).set_param(*m_p->get_elem(p_i));\n" | |
970ed795 | 5699 | " }\n" |
3f84031e | 5700 | " *this = new_temp;\n" |
3abe9331 | 5701 | " break; }\n" |
970ed795 | 5702 | " case Module_Param::MP_Value_List:\n" |
3f84031e | 5703 | " if (%lu<m_p->get_size()) {\n" |
5704 | " param.error(\"%s template of type %s has %lu fields but list value has %%d fields\", (int)m_p->get_size());\n" | |
970ed795 | 5705 | " }\n", |
3abe9331 | 5706 | kind_str, dispname, kind_str, name, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements); |
970ed795 EL |
5707 | for (i = 0; i < sdef->nElements; ++i) { |
5708 | src = mputprintf(src, | |
3f84031e | 5709 | " if (m_p->get_size()>%lu && m_p->get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*m_p->get_elem(%lu));\n", |
970ed795 EL |
5710 | (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i); |
5711 | } | |
5712 | src = mputstr(src, | |
5713 | " break;\n" | |
5714 | " case Module_Param::MP_Assignment_List: {\n" | |
3f84031e | 5715 | " Vector<bool> value_used(m_p->get_size());\n" |
5716 | " value_used.resize(m_p->get_size(), false);\n"); | |
970ed795 EL |
5717 | for (i = 0; i < sdef->nElements; ++i) { |
5718 | src = mputprintf(src, | |
3f84031e | 5719 | " for (size_t val_idx=0; val_idx<m_p->get_size(); val_idx++) {\n" |
5720 | " Module_Param* const curr_param = m_p->get_elem(val_idx);\n" | |
970ed795 EL |
5721 | " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n" |
5722 | " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n" | |
5723 | " %s().set_param(*curr_param);\n" | |
5724 | " }\n" | |
5725 | " value_used[val_idx]=true;\n" | |
5726 | " }\n" | |
5727 | " }\n" | |
5728 | , sdef->elements[i].dispname, sdef->elements[i].name); | |
5729 | } | |
5730 | src = mputprintf(src, | |
3f84031e | 5731 | " for (size_t val_idx=0; val_idx<m_p->get_size(); val_idx++) if (!value_used[val_idx]) {\n" |
5732 | " m_p->get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", m_p->get_elem(val_idx)->get_id()->get_name());\n" | |
970ed795 EL |
5733 | " break;\n" |
5734 | " }\n" | |
5735 | " } break;\n" | |
5736 | " default:\n" | |
5737 | " param.type_error(\"%s template\", \"%s\");\n" | |
5738 | " }\n" | |
3f84031e | 5739 | " is_ifpresent = param.get_ifpresent() || m_p->get_ifpresent();\n" |
970ed795 | 5740 | "}\n\n", dispname, kind_str, dispname); |
3abe9331 | 5741 | |
5742 | /* get_param() */ | |
5743 | def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); | |
5744 | src = mputprintf(src, | |
5745 | "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n" | |
5746 | "{\n" | |
5747 | " if (param_name.next_name()) {\n" | |
5748 | // Haven't reached the end of the module parameter name | |
5749 | // => the name refers to one of the fields, not to the whole record | |
5750 | " char* param_field = param_name.get_current_name();\n" | |
5751 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" | |
5752 | " TTCN_error(\"Unexpected array index in module parameter reference, \"\n" | |
5753 | " \"expected a valid field name for %s template type `%s'\");\n" | |
5754 | " }\n" | |
5755 | " ", name, kind_str, dispname); | |
5756 | for (i = 0; i < sdef->nElements; i++) { | |
5757 | src = mputprintf(src, | |
5758 | "if (strcmp(\"%s\", param_field) == 0) {\n" | |
5759 | " return %s().get_param(param_name);\n" | |
5760 | " } else ", | |
5761 | sdef->elements[i].dispname, sdef->elements[i].name); | |
5762 | } | |
5763 | src = mputprintf(src, | |
5764 | "TTCN_error(\"Field `%%s' not found in %s type `%s'\", param_field);\n" | |
5765 | " }\n" | |
3f84031e | 5766 | " Module_Param* m_p = NULL;\n" |
3abe9331 | 5767 | " switch (template_selection) {\n" |
5768 | " case UNINITIALIZED_TEMPLATE:\n" | |
3f84031e | 5769 | " m_p = new Module_Param_Unbound();\n" |
3abe9331 | 5770 | " break;\n" |
5771 | " case OMIT_VALUE:\n" | |
3f84031e | 5772 | " m_p = new Module_Param_Omit();\n" |
3abe9331 | 5773 | " break;\n" |
5774 | " case ANY_VALUE:\n" | |
3f84031e | 5775 | " m_p = new Module_Param_Any();\n" |
3abe9331 | 5776 | " break;\n" |
5777 | " case ANY_OR_OMIT:\n" | |
3f84031e | 5778 | " m_p = new Module_Param_AnyOrNone();\n" |
3abe9331 | 5779 | " break;\n" |
5780 | " case SPECIFIC_VALUE: {\n" | |
3f84031e | 5781 | " m_p = new Module_Param_Assignment_List();\n" |
3abe9331 | 5782 | , kind_str, dispname); |
5783 | for (i = 0; i < sdef->nElements; i++) { | |
5784 | src = mputprintf(src, | |
5785 | " Module_Param* mp_field_%s = single_value->field_%s.get_param(param_name);\n" | |
5786 | " mp_field_%s->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n" | |
3f84031e | 5787 | " m_p->add_elem(mp_field_%s);\n" |
3abe9331 | 5788 | , sdef->elements[i].name, sdef->elements[i].name |
5789 | , sdef->elements[i].name, sdef->elements[i].dispname | |
5790 | , sdef->elements[i].name); | |
5791 | } | |
5792 | src = mputstr(src, | |
5793 | " break; }\n" | |
5794 | " case VALUE_LIST:\n" | |
5795 | " case COMPLEMENTED_LIST: {\n" | |
5796 | " if (template_selection == VALUE_LIST) {\n" | |
3f84031e | 5797 | " m_p = new Module_Param_List_Template();\n" |
3abe9331 | 5798 | " }\n" |
5799 | " else {\n" | |
3f84031e | 5800 | " m_p = new Module_Param_ComplementList_Template();\n" |
3abe9331 | 5801 | " }\n" |
3f84031e | 5802 | " for (size_t i_i = 0; i_i < value_list.n_values; ++i_i) {\n" |
5803 | " m_p->add_elem(value_list.list_value[i_i].get_param(param_name));\n" | |
3abe9331 | 5804 | " }\n" |
5805 | " break; }\n" | |
5806 | " default:\n" | |
5807 | " break;\n" | |
5808 | " }\n" | |
5809 | " if (is_ifpresent) {\n" | |
3f84031e | 5810 | " m_p->set_ifpresent();\n" |
3abe9331 | 5811 | " }\n" |
3f84031e | 5812 | " return m_p;\n" |
3abe9331 | 5813 | "}\n\n"); |
970ed795 EL |
5814 | |
5815 | /* check template restriction */ | |
5816 | def = mputstr(def, "void check_restriction(template_res t_res, " | |
3abe9331 | 5817 | "const char* t_name=NULL, boolean legacy = FALSE) const;\n"); |
970ed795 EL |
5818 | src = mputprintf(src, |
5819 | "void %s_template::check_restriction(" | |
3abe9331 | 5820 | "template_res t_res, const char* t_name, boolean legacy) const\n" |
970ed795 EL |
5821 | "{\n" |
5822 | "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n" | |
5823 | "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n" | |
5824 | "case TR_OMIT:\n" | |
5825 | "if (template_selection==OMIT_VALUE) return;\n" | |
5826 | "case TR_VALUE:\n" | |
5827 | "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n", | |
5828 | name); | |
5829 | for (i = 0; i < sdef->nElements; i++) { | |
5830 | src = mputprintf(src, "single_value->field_%s.check_restriction(" | |
5831 | "t_res, t_name ? t_name : \"%s\");\n", | |
5832 | sdef->elements[i].name, dispname); | |
5833 | } | |
5834 | src = mputprintf(src, | |
5835 | "return;\n" | |
5836 | "case TR_PRESENT:\n" | |
3abe9331 | 5837 | "if (!match_omit(legacy)) return;\n" |
970ed795 EL |
5838 | "break;\n" |
5839 | "default:\n" | |
5840 | "return;\n" | |
5841 | "}\n" | |
5842 | "TTCN_error(\"Restriction `%%s' on template of type %%s " | |
5843 | "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n" | |
5844 | "}\n\n", dispname); | |
5845 | ||
5846 | defCommonRecordTemplate(name, &def, &src); | |
5847 | ||
5848 | def = mputstr(def, "};\n\n"); | |
5849 | ||
5850 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
5851 | Free(def); | |
5852 | ||
5853 | output->source.methods = mputstr(output->source.methods, src); | |
5854 | Free(src); | |
5855 | } | |
5856 | ||
5857 | static void defEmptyRecordClass(const struct_def *sdef, | |
5858 | output_struct *output) | |
5859 | { | |
5860 | const char *name = sdef->name, *dispname = sdef->dispname; | |
5861 | char *def = NULL, *src = NULL; | |
5862 | boolean ber_needed = sdef->isASN1 && enable_ber(); | |
5863 | boolean raw_needed = sdef->hasRaw && enable_raw(); | |
5864 | boolean text_needed = sdef->hasText && enable_text(); | |
5865 | boolean xer_needed = sdef->hasXer && enable_xer(); | |
5866 | boolean json_needed = sdef->hasJson && enable_json(); | |
5867 | ||
5868 | def = mputprintf(def, | |
5869 | #ifndef NDEBUG | |
5870 | "// written by %s in " __FILE__ " at line %d\n" | |
5871 | #endif | |
5872 | "class %s : public Base_Type {\n" | |
5873 | "boolean bound_flag;\n" | |
5874 | "public:\n" | |
5875 | #ifndef NDEBUG | |
5876 | , __FUNCTION__, __LINE__ | |
5877 | #endif | |
5878 | , name); | |
5879 | ||
5880 | /* default ctor */ | |
5881 | def = mputprintf(def, "%s();\n", name); | |
5882 | src = mprintf("%s::%s()\n" | |
5883 | "{\n" | |
5884 | "bound_flag = FALSE;\n" | |
5885 | "}\n\n", name, name); | |
5886 | ||
5887 | /* ctor from NULL_VALUE (i.e. {}) */ | |
5888 | def = mputprintf(def, "%s(null_type other_value);\n", name); | |
5889 | src = mputprintf(src, "%s::%s(null_type)\n" | |
5890 | "{\n" | |
5891 | "bound_flag = TRUE;\n" | |
5892 | "}\n\n", name, name); | |
5893 | ||
5894 | /* copy ctor */ | |
5895 | def = mputprintf(def, "%s(const %s& other_value);\n", name, name); | |
5896 | src = mputprintf(src, "%s::%s(const %s& other_value)\n" | |
5897 | "{\n" | |
5898 | "other_value.must_bound(\"Copying an unbound value of " | |
5899 | "type %s.\");\n" | |
5900 | "bound_flag = TRUE;\n" | |
5901 | "}\n\n", name, name, name, dispname); | |
5902 | ||
5903 | /* assignment op: from NULL_VALUE */ | |
5904 | def = mputprintf(def, "%s& operator=(null_type other_value);\n", name); | |
5905 | src = mputprintf(src, "%s& %s::operator=(null_type)\n" | |
5906 | "{\n" | |
5907 | "bound_flag = TRUE;\n" | |
5908 | "return *this;\n" | |
5909 | "}\n\n", name, name); | |
5910 | ||
5911 | /* assignment op: from itself */ | |
5912 | def = mputprintf(def, "%s& operator=(const %s& other_value);\n", name, | |
5913 | name); | |
5914 | src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n" | |
5915 | "{\n" | |
5916 | "other_value.must_bound(\"Assignment of an unbound value of type " | |
5917 | "%s.\");\n" | |
5918 | "bound_flag = TRUE;\n" | |
5919 | "return *this;\n" | |
5920 | "}\n\n", name, name, name, dispname); | |
5921 | ||
5922 | /* comparison op: with NULL_VALUE */ | |
5923 | def = mputstr(def, "boolean operator==(null_type other_value) const;\n"); | |
5924 | src = mputprintf(src, | |
5925 | "boolean %s::operator==(null_type) const\n" | |
5926 | "{\n" | |
5927 | "must_bound(\"Comparison of an unbound value of type %s.\");\n" | |
5928 | "return TRUE;\n" | |
5929 | "}\n\n", name, dispname); | |
5930 | ||
5931 | /* comparison op: with itself */ | |
5932 | def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n", | |
5933 | name); | |
5934 | src = mputprintf(src, | |
5935 | "boolean %s::operator==(const %s& other_value) const\n" | |
5936 | "{\n" | |
5937 | "must_bound(\"Comparison of an unbound value of type %s.\");\n" | |
5938 | "other_value.must_bound(\"Comparison of an unbound value of type " | |
5939 | "%s.\");\n" | |
5940 | "return TRUE;\n" | |
5941 | "}\n\n", name, name, dispname, dispname); | |
5942 | ||
5943 | /* non-equal operators */ | |
5944 | def = mputprintf(def, | |
5945 | "inline boolean operator!=(null_type other_value) const " | |
5946 | "{ return !(*this == other_value); }\n" | |
5947 | "inline boolean operator!=(const %s& other_value) const " | |
5948 | "{ return !(*this == other_value); }\n", name); | |
5949 | ||
5950 | ||
5951 | /* is_bound function */ | |
5952 | def = mputstr(def, "inline boolean is_bound() const " | |
5953 | "{ return bound_flag; }\n"); | |
5954 | ||
5955 | /* is_present function */ | |
5956 | def = mputstr(def, | |
5957 | "inline boolean is_present() const { return is_bound(); }\n"); | |
5958 | ||
5959 | /* is_value function */ | |
5960 | def = mputstr(def, "inline boolean is_value() const " | |
5961 | "{ return bound_flag; }\n"); | |
5962 | ||
5963 | /* clean_up function */ | |
5964 | def = mputstr(def, "inline void clean_up() " | |
5965 | "{ bound_flag = FALSE; }\n"); | |
5966 | ||
5967 | /* must_bound function */ | |
5968 | def = mputstr(def, "inline void must_bound(const char *err_msg) const " | |
5969 | "{ if (!bound_flag) TTCN_error(\"%s\", err_msg); }\n"); | |
5970 | ||
5971 | /* log function */ | |
5972 | def = mputstr(def, "void log() const;\n"); | |
5973 | src = mputprintf(src, "void %s::log() const\n" | |
5974 | "{\n" | |
5975 | "if (bound_flag) TTCN_Logger::log_event_str(\"{ }\");\n" | |
5976 | "else TTCN_Logger::log_event_unbound();\n" | |
5977 | "}\n\n", name); | |
5978 | ||
5979 | /* set_param function */ | |
3abe9331 | 5980 | def = mputstr(def, "void set_param(Module_Param& param);\n"); |
5981 | src = mputprintf(src, "void %s::set_param(Module_Param& param)\n" | |
970ed795 EL |
5982 | "{\n" |
5983 | " param.basic_check(Module_Param::BC_VALUE, \"empty record/set value (i.e. { })\");\n" | |
3abe9331 | 5984 | " Module_Param_Ptr mp = ¶m;\n" |
5985 | " if (param.get_type() == Module_Param::MP_Reference) {\n" | |
5986 | " mp = param.get_referenced_param();\n" | |
5987 | " }\n" | |
5988 | " if (mp->get_type()!=Module_Param::MP_Value_List || mp->get_size()>0) {\n" | |
970ed795 EL |
5989 | " param.type_error(\"empty record/set value (i.e. { })\", \"%s\");\n" |
5990 | " }\n" | |
5991 | " bound_flag = TRUE;\n" | |
5992 | "}\n\n", name, dispname); | |
3abe9331 | 5993 | |
5994 | /* get param function */ | |
5995 | def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); | |
5996 | src = mputprintf(src, | |
5997 | "Module_Param* %s::get_param(Module_Param_Name& /* param_name */) const\n" | |
5998 | "{\n" | |
5999 | " if (!is_bound()) {\n" | |
6000 | " return new Module_Param_Unbound();\n" | |
6001 | " }\n" | |
6002 | " return new Module_Param_Value_List();\n" | |
6003 | "}\n\n", name); | |
970ed795 EL |
6004 | |
6005 | /* encode_text function */ | |
6006 | def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); | |
6007 | src = mputprintf(src, "void %s::encode_text(Text_Buf& /*text_buf*/) const\n" | |
6008 | "{\n" | |
6009 | "must_bound(\"Text encoder: Encoding an unbound value of type %s.\");\n" | |
6010 | "}\n\n", name, dispname); | |
6011 | ||
6012 | /* decode_text function */ | |
6013 | def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); | |
6014 | src = mputprintf(src, "void %s::decode_text(Text_Buf& /*text_buf*/)\n" | |
6015 | "{\n" | |
6016 | "bound_flag = TRUE;\n" | |
6017 | "}\n\n", name); | |
6018 | ||
6019 | if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) | |
6020 | def_encdec(name, &def, &src, ber_needed, raw_needed, | |
6021 | text_needed, xer_needed, json_needed, FALSE); | |
6022 | ||
6023 | /* BER functions */ | |
6024 | if(ber_needed) { | |
6025 | /* BER_encode_TLV() */ | |
6026 | src=mputprintf | |
6027 | (src, | |
6028 | "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td," | |
6029 | " unsigned p_coding) const\n" | |
6030 | "{\n" | |
6031 | " BER_chk_descr(p_td);\n" | |
6032 | " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n" | |
6033 | " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n" | |
6034 | " return new_tlv;\n" | |
6035 | "}\n" | |
6036 | "\n" | |
6037 | , name | |
6038 | ); | |
6039 | ||
6040 | /* BER_decode_TLV() */ | |
6041 | src=mputprintf | |
6042 | (src, | |
6043 | "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td," | |
6044 | " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n" | |
6045 | "{\n" | |
6046 | " BER_chk_descr(p_td);\n" | |
6047 | " ASN_BER_TLV_t stripped_tlv;\n" | |
6048 | " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n" | |
6049 | " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n" | |
6050 | " stripped_tlv.chk_constructed_flag(TRUE);\n" | |
6051 | " bound_flag=TRUE;\n" | |
6052 | " return TRUE;\n" | |
6053 | "}\n" | |
6054 | "\n" | |
6055 | , name, sdef->dispname | |
6056 | ); | |
6057 | } /* if ber_needed */ | |
6058 | if(text_needed){ | |
6059 | src = mputprintf(src, | |
6060 | "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td," | |
6061 | "TTCN_Buffer& p_buf) const{\n" | |
6062 | " int encoded_length=0;\n" | |
6063 | " if(p_td.text->begin_encode){\n" | |
6064 | " p_buf.put_cs(*p_td.text->begin_encode);\n" | |
6065 | " encoded_length+=p_td.text->begin_encode->lengthof();\n" | |
6066 | " }\n" | |
6067 | " if(!bound_flag) {\n" | |
6068 | " TTCN_EncDec_ErrorContext::error\n" | |
6069 | " (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" | |
6070 | " }\n" | |
6071 | " if(p_td.text->end_encode){\n" | |
6072 | " p_buf.put_cs(*p_td.text->end_encode);\n" | |
6073 | " encoded_length+=p_td.text->end_encode->lengthof();\n" | |
6074 | " }\n" | |
6075 | " return encoded_length;\n" | |
6076 | "}\n" | |
6077 | ,name | |
6078 | ); | |
6079 | src = mputprintf(src, | |
6080 | "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td," | |
6081 | " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n" | |
509718e0 | 6082 | " bound_flag = TRUE;\n" |
970ed795 EL |
6083 | " int decoded_length=0;\n" |
6084 | " if(p_td.text->begin_decode){\n" | |
6085 | " int tl;\n" | |
6086 | " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n" | |
6087 | " if(no_err)return -1;\n" | |
6088 | " TTCN_EncDec_ErrorContext::error\n" | |
6089 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
6090 | " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)" | |
6091 | ", p_td.name);\n" | |
6092 | " return 0;\n" | |
6093 | " }\n" | |
6094 | " decoded_length+=tl;\n" | |
6095 | " p_buf.increase_pos(tl);\n" | |
6096 | " }\n" | |
6097 | " if(p_td.text->end_decode){\n" | |
6098 | " int tl;\n" | |
6099 | " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" | |
6100 | " if(no_err)return -1;\n" | |
6101 | " TTCN_EncDec_ErrorContext::error\n" | |
6102 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" | |
6103 | " not found for '%%s': \",(const char*)*(p_td.text->end_decode)" | |
6104 | ", p_td.name);\n" | |
6105 | " return 0;\n" | |
6106 | " }\n" | |
6107 | " decoded_length+=tl;\n" | |
6108 | " p_buf.increase_pos(tl);\n" | |
6109 | " }\n" | |
970ed795 EL |
6110 | " return decoded_length;\n" |
6111 | "}\n" | |
6112 | ,name | |
6113 | ); | |
6114 | ||
6115 | } | |
6116 | /* RAW functions */ | |
6117 | if (raw_needed) { | |
6118 | src = mputprintf(src, | |
6119 | "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td, " | |
6120 | "RAW_enc_tree& /*myleaf*/) const\n" | |
6121 | "{\n" | |
6122 | "if (!bound_flag) TTCN_EncDec_ErrorContext::error" | |
6123 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value of " | |
6124 | "type %%s.\", p_td.name);\n" | |
6125 | "return 0;\n" | |
6126 | "}\n\n", name); | |
6127 | ||
6128 | src = mputprintf(src, | |
6129 | "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, " | |
6130 | "TTCN_Buffer& p_buf, int, raw_order_t, boolean, int, boolean)\n" | |
6131 | "{\n" | |
6132 | "bound_flag = TRUE;\n" | |
6133 | "return p_buf.increase_pos_padd(p_td.raw->prepadding) + " | |
6134 | "p_buf.increase_pos_padd(p_td.raw->padding);\n" | |
6135 | "}\n\n", name); | |
6136 | } | |
6137 | ||
6138 | if (xer_needed) { /* XERSTUFF codegen for empty record/SEQUENCE */ | |
6139 | src=mputprintf(src, | |
6140 | "boolean %s::can_start(const char *p_name, const char *p_uri, " | |
6141 | "const XERdescriptor_t& p_td, unsigned int p_flavor) {\n" | |
6142 | " boolean e_xer = is_exer(p_flavor);\n" | |
6143 | " if (e_xer && (p_td.xer_bits & UNTAGGED)) return false;\n" | |
6144 | " else return check_name(p_name, p_td, e_xer) && (!e_xer || check_namespace(p_uri, p_td));\n" | |
6145 | "}\n\n" | |
6146 | , name | |
6147 | ||
6148 | ); | |
6149 | src = mputprintf(src, | |
af710487 | 6150 | "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, " |
6151 | "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const{\n" | |
970ed795 EL |
6152 | " int encoded_length=(int)p_buf.get_len();\n" |
6153 | " int is_indented = !is_canonical(p_flavor);\n" | |
6154 | " int e_xer = is_exer(p_flavor);\n" | |
6155 | " if (is_indented) do_indent(p_buf, p_indent);\n" | |
6156 | " p_buf.put_c('<');\n" | |
6157 | " if (e_xer) write_ns_prefix(p_td, p_buf);\n" | |
6158 | " p_buf.put_s((size_t)p_td.namelens[e_xer]-2, (cbyte*)p_td.names[e_xer]);\n" | |
6159 | " p_buf.put_s(2 + is_indented, (cbyte*)\"/>\\n\");\n" | |
6160 | " return (int)p_buf.get_len() - encoded_length;\n" | |
6161 | "}\n\n" | |
6162 | , name); | |
6163 | src = mputprintf(src, | |
6164 | #ifndef NDEBUG | |
6165 | "// written by %s in " __FILE__ " at %d\n" | |
6166 | #endif | |
6167 | "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, " | |
feade998 | 6168 | "unsigned int p_flavor, unsigned int /*p_flavor2*/, embed_values_dec_struct_t*)\n" |
970ed795 EL |
6169 | "{\n" |
6170 | " int e_xer = is_exer(p_flavor);\n" | |
6171 | " bound_flag = true;\n" | |
6172 | " int rd_ok, depth=-1;\n" | |
6173 | " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" | |
6174 | " int type = p_reader.NodeType();\n" | |
6175 | " if (type==XML_READER_TYPE_ELEMENT) {\n" | |
6176 | " verify_name(p_reader, p_td, e_xer);\n" | |
6177 | " depth=p_reader.Depth();\n" | |
6178 | " if (p_reader.IsEmptyElement()) {\n" | |
6179 | " rd_ok = p_reader.Read(); break;\n" | |
6180 | " }\n" | |
6181 | " else if ((p_flavor & XER_MASK) == XER_CANONICAL) {\n" | |
6182 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, " | |
6183 | "\"Expected an empty element tag\");\n" | |
6184 | " }\n" | |
6185 | " }\n" | |
6186 | " else if (type == XML_READER_TYPE_END_ELEMENT && depth != -1) {\n" | |
6187 | " verify_end(p_reader, p_td, depth, e_xer);\n" | |
6188 | " rd_ok = p_reader.Read(); break;\n" | |
6189 | " }\n" | |
6190 | " }\n" | |
6191 | " return 1;\n" | |
6192 | "}\n\n" | |
6193 | #ifndef NDEBUG | |
6194 | , __FUNCTION__, __LINE__ | |
6195 | #endif | |
6196 | , name); | |
6197 | } | |
6198 | if (json_needed) { | |
6199 | // JSON encode, RT1 | |
6200 | src = mputprintf(src, | |
6201 | "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n" | |
6202 | "{\n" | |
6203 | " if (!is_bound()) {\n" | |
6204 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" | |
6205 | " \"Encoding an unbound value of type %s.\");\n" | |
6206 | " return -1;\n" | |
6207 | " }\n\n" | |
6208 | " return p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL) + \n" | |
6209 | " p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n" | |
6210 | "}\n\n" | |
6211 | , name, dispname); | |
6212 | ||
6213 | // JSON decode, RT1 | |
6214 | src = mputprintf(src, | |
6215 | "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n" | |
6216 | "{\n" | |
6217 | " json_token_t token = JSON_TOKEN_NONE;\n" | |
6218 | " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n" | |
6219 | " if (JSON_TOKEN_ERROR == token) {\n" | |
6220 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n" | |
6221 | " return JSON_ERROR_FATAL;\n" | |
6222 | " }\n" | |
6223 | " else if (JSON_TOKEN_OBJECT_START != token) {\n" | |
6224 | " return JSON_ERROR_INVALID_TOKEN;\n" | |
6225 | " }\n\n" | |
6226 | " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n" | |
6227 | " if (JSON_TOKEN_OBJECT_END != token) {\n" | |
6228 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n" | |
6229 | " return JSON_ERROR_FATAL;\n" | |
6230 | " }\n\n" | |
6231 | " bound_flag = true;\n\n" | |
6232 | " return dec_len;\n" | |
6233 | "}\n\n" | |
6234 | , name); | |
6235 | } | |
6236 | ||
6237 | /* closing class definition */ | |
6238 | def = mputstr(def, "};\n\n"); | |
6239 | ||
6240 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
6241 | Free(def); | |
6242 | ||
6243 | output->source.methods = mputstr(output->source.methods, src); | |
6244 | Free(src); | |
6245 | ||
6246 | output->header.function_prototypes = | |
6247 | mputprintf(output->header.function_prototypes, | |
6248 | "extern boolean operator==(null_type null_value, const %s& " | |
6249 | "other_value);\n", name); | |
6250 | output->source.function_bodies = | |
6251 | mputprintf(output->source.function_bodies, | |
6252 | "boolean operator==(null_type, const %s& other_value)\n" | |
6253 | "{\n" | |
6254 | "other_value.must_bound(\"Comparison of an unbound value of type " | |
6255 | "%s.\");\n" | |
6256 | "return TRUE;\n" | |
6257 | "}\n\n", name, dispname); | |
6258 | ||
6259 | output->header.function_prototypes = | |
6260 | mputprintf(output->header.function_prototypes, | |
6261 | "inline boolean operator!=(null_type null_value, const %s& " | |
6262 | "other_value) " | |
6263 | "{ return !(null_value == other_value); }\n", name); | |
6264 | } | |
6265 | ||
6266 | static void defEmptyRecordTemplate(const char *name, const char *dispname, | |
6267 | output_struct *output) | |
6268 | { | |
6269 | char *def = NULL, *src = NULL; | |
6270 | ||
6271 | /* class definition */ | |
6272 | def = mprintf("class %s_template : public Base_Template {\n" | |
6273 | "struct {\n" | |
6274 | "unsigned int n_values;\n" | |
6275 | "%s_template *list_value;\n" | |
6276 | "} value_list;\n", name, name); | |
6277 | ||
6278 | /* copy_template function */ | |
6279 | def = mputprintf(def, "void copy_template(const %s_template& " | |
6280 | "other_value);\n\n", name); | |
6281 | src = mputprintf(src, | |
6282 | "void %s_template::copy_template(const %s_template& other_value)\n" | |
6283 | "{\n" | |
6284 | "set_selection(other_value);\n" | |
6285 | "switch (template_selection) {\n" | |
6286 | "case OMIT_VALUE:\n" | |
6287 | "case ANY_VALUE:\n" | |
6288 | "case ANY_OR_OMIT:\n" | |
6289 | "case SPECIFIC_VALUE:\n" | |
6290 | "break;\n" | |
6291 | "case VALUE_LIST:\n" | |
6292 | "case COMPLEMENTED_LIST:\n" | |
6293 | "value_list.n_values = other_value.value_list.n_values;\n" | |
6294 | "value_list.list_value = new %s_template[value_list.n_values];\n" | |
6295 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
6296 | "list_count++)\n" | |
6297 | "value_list.list_value[list_count].copy_template(" | |
6298 | "other_value.value_list.list_value[list_count]);\n" | |
6299 | "break;\n" | |
6300 | "default:\n" | |
6301 | "TTCN_error(\"Copying an uninitialized/unsupported template of type " | |
6302 | "%s.\");\n" | |
6303 | "break;\n" | |
6304 | "}\n" | |
6305 | "}\n\n", name, name, name, dispname); | |
6306 | ||
6307 | /* default ctor */ | |
6308 | def = mputprintf(def, "public:\n" | |
6309 | "%s_template();\n", name); | |
6310 | src = mputprintf(src, "%s_template::%s_template()\n" | |
6311 | "{\n" | |
6312 | "}\n\n", name, name); | |
6313 | ||
6314 | /* ctor for generic wildcards */ | |
6315 | def = mputprintf(def, "%s_template(template_sel other_value);\n", name); | |
6316 | src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n" | |
6317 | " : Base_Template(other_value)\n" | |
6318 | "{\n" | |
6319 | "check_single_selection(other_value);\n" | |
6320 | "}\n\n", name, name); | |
6321 | ||
6322 | /* ctor for value {} */ | |
6323 | def = mputprintf(def, "%s_template(null_type other_value);\n", name); | |
6324 | src = mputprintf(src, "%s_template::%s_template(null_type)\n" | |
6325 | " : Base_Template(SPECIFIC_VALUE)\n" | |
6326 | "{\n" | |
6327 | "}\n\n", name, name); | |
6328 | ||
6329 | /* ctor for specific value */ | |
6330 | def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name); | |
6331 | src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n" | |
6332 | " : Base_Template(SPECIFIC_VALUE)\n" | |
6333 | "{\n" | |
6334 | "other_value.must_bound(\"Creating a template from an unbound value of " | |
6335 | "type %s.\");\n" | |
6336 | "}\n\n", name, name, name, dispname); | |
6337 | ||
6338 | /* ctor for optional value */ | |
6339 | def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n", | |
6340 | name, name); | |
6341 | src = mputprintf(src, "%s_template::%s_template(const OPTIONAL<%s>& " | |
6342 | "other_value)\n" | |
6343 | "{\n" | |
6344 | "switch (other_value.get_selection()) {\n" | |
6345 | "case OPTIONAL_PRESENT:\n" | |
6346 | "set_selection(SPECIFIC_VALUE);\n" | |
6347 | "break;\n" | |
6348 | "case OPTIONAL_OMIT:\n" | |
6349 | "set_selection(OMIT_VALUE);\n" | |
6350 | "break;\n" | |
6351 | "default:\n" | |
6352 | "TTCN_error(\"Creating a template of type %s from an unbound optional " | |
6353 | "field.\");\n" | |
6354 | "}\n" | |
6355 | "}\n\n", name, name, name, dispname); | |
6356 | ||
6357 | /* copy ctor */ | |
6358 | def = mputprintf(def, "%s_template(const %s_template& other_value);\n", | |
6359 | name, name); | |
6360 | src = mputprintf(src, "%s_template::%s_template(const %s_template& " | |
6361 | "other_value)\n" | |
6362 | ": Base_Template()" /* yes, the base class _default_ constructor */ | |
6363 | "{\n" | |
6364 | "copy_template(other_value);\n" | |
6365 | "}\n\n", name, name, name); | |
6366 | ||
6367 | /* dtor */ | |
6368 | def = mputprintf(def, "~%s_template();\n", name); | |
6369 | src = mputprintf(src, "%s_template::~%s_template()\n" | |
6370 | "{\n" | |
6371 | "clean_up();\n" | |
6372 | "}\n\n", name, name); | |
6373 | ||
6374 | /* clean_up function */ | |
6375 | def = mputstr(def, "void clean_up();\n"); | |
6376 | src = mputprintf(src, "void %s_template::clean_up()\n" | |
6377 | "{\n" | |
6378 | "if (template_selection == VALUE_LIST || " | |
6379 | "template_selection == COMPLEMENTED_LIST)\n" | |
6380 | "delete [] value_list.list_value;\n" | |
6381 | "template_selection = UNINITIALIZED_TEMPLATE;\n" | |
6382 | "}\n\n", name); | |
6383 | ||
6384 | /* assignment op for generic wildcards */ | |
6385 | def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n", | |
6386 | name); | |
6387 | src = mputprintf(src, "%s_template& %s_template::operator=(template_sel " | |
6388 | "other_value)\n" | |
6389 | "{\n" | |
6390 | "check_single_selection(other_value);\n" | |
6391 | "clean_up();\n" | |
6392 | "set_selection(other_value);\n" | |
6393 | "return *this;\n" | |
6394 | "}\n\n", name, name); | |
6395 | ||
6396 | /* assignment op for value {} */ | |
6397 | def = mputprintf(def, "%s_template& operator=(null_type other_value);\n", | |
6398 | name); | |
6399 | src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n" | |
6400 | "{\n" | |
6401 | "clean_up();\n" | |
6402 | "set_selection(SPECIFIC_VALUE);\n" | |
6403 | "return *this;\n" | |
6404 | "}\n\n", name, name); | |
6405 | ||
6406 | /* assignment op for specific value */ | |
6407 | def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n", | |
6408 | name, name); | |
6409 | src = mputprintf(src, "%s_template& %s_template::operator=(const %s& " | |
6410 | "other_value)\n" | |
6411 | "{\n" | |
6412 | "other_value.must_bound(\"Assignment of an unbound value of type %s " | |
6413 | "to a template.\");\n" | |
6414 | "clean_up();\n" | |
6415 | "set_selection(SPECIFIC_VALUE);\n" | |
6416 | "return *this;\n" | |
6417 | "}\n\n", name, name, name, dispname); | |
6418 | ||
6419 | /* assignment op for optional value */ | |
6420 | def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& " | |
6421 | "other_value);\n", name, name); | |
6422 | src = mputprintf(src, "%s_template& %s_template::operator=" | |
6423 | "(const OPTIONAL<%s>& other_value)\n" | |
6424 | "{\n" | |
6425 | "clean_up();\n" | |
6426 | "switch (other_value.get_selection()) {\n" | |
6427 | "case OPTIONAL_PRESENT:\n" | |
6428 | "set_selection(SPECIFIC_VALUE);\n" | |
6429 | "break;\n" | |
6430 | "case OPTIONAL_OMIT:\n" | |
6431 | "set_selection(OMIT_VALUE);\n" | |
6432 | "break;\n" | |
6433 | "default:\n" | |
6434 | "TTCN_error(\"Assignment of an unbound optional field to a template " | |
6435 | "of type %s.\");\n" | |
6436 | "}\n" | |
6437 | "return *this;\n" | |
6438 | "}\n\n", name, name, name, dispname); | |
6439 | ||
6440 | /* assignment op for itself */ | |
6441 | def = mputprintf(def, "%s_template& operator=(const %s_template& " | |
6442 | "other_value);\n", name, name); | |
6443 | src = mputprintf(src, "%s_template& %s_template::operator=" | |
6444 | "(const %s_template& other_value)\n" | |
6445 | "{\n" | |
6446 | "if (&other_value != this) {\n" | |
6447 | "clean_up();\n" | |
6448 | "set_selection(other_value);\n" | |
6449 | "}\n" | |
6450 | "return *this;\n" | |
6451 | "}\n\n", name, name, name); | |
6452 | ||
6453 | /* match operation with {} */ | |
3abe9331 | 6454 | def = mputstr(def, "boolean match(null_type other_value, boolean legacy " |
6455 | "= FALSE) const;\n"); | |
6456 | src = mputprintf(src, "boolean %s_template::match(null_type other_value," | |
6457 | "boolean) const\n" | |
970ed795 EL |
6458 | "{\n" |
6459 | "switch (template_selection) {\n" | |
6460 | "case ANY_VALUE:\n" | |
6461 | "case ANY_OR_OMIT:\n" | |
6462 | "case SPECIFIC_VALUE:\n" | |
6463 | "return TRUE;\n" | |
6464 | "case OMIT_VALUE:\n" | |
6465 | "return FALSE;\n" | |
6466 | "case VALUE_LIST:\n" | |
6467 | "case COMPLEMENTED_LIST:\n" | |
6468 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
6469 | "list_count++)\n" | |
6470 | "if (value_list.list_value[list_count].match(other_value)) " | |
6471 | "return template_selection == VALUE_LIST;\n" | |
6472 | "return template_selection == COMPLEMENTED_LIST;\n" | |
6473 | "default:\n" | |
6474 | "TTCN_error(\"Matching an uninitialized/unsupported template of " | |
6475 | "type %s.\");\n" | |
6476 | "}\n" | |
6477 | "return FALSE;\n" | |
6478 | "}\n\n", name, dispname); | |
6479 | ||
6480 | /* match operation with specific value */ | |
3abe9331 | 6481 | def = mputprintf(def, "boolean match(const %s& other_value, boolean legacy " |
6482 | "= FALSE) const;\n", name); | |
6483 | src = mputprintf(src, "boolean %s_template::match(const %s& other_value, " | |
6484 | "boolean) const\n" | |
970ed795 EL |
6485 | "{\n" |
6486 | "if (!other_value.is_bound()) return FALSE;" | |
6487 | "return match(NULL_VALUE);\n" | |
6488 | "}\n\n", name, name); | |
6489 | ||
6490 | /* valueof operation */ | |
6491 | def = mputprintf(def, "%s valueof() const;\n", name); | |
6492 | src = mputprintf(src, "%s %s_template::valueof() const\n" | |
6493 | "{\n" | |
6494 | "if (template_selection != SPECIFIC_VALUE || is_ifpresent) " | |
6495 | "TTCN_error(\"Performing a valueof or send operation on a " | |
6496 | "non-specific template of type %s.\");\n" | |
6497 | "return NULL_VALUE;\n" | |
6498 | "}\n\n", name, name, dispname); | |
6499 | ||
6500 | /* void set_type(template_sel, int) function */ | |
6501 | def = mputstr(def, | |
6502 | "void set_type(template_sel template_type, " | |
6503 | "unsigned int list_length);\n"); | |
6504 | ||
6505 | src = mputprintf(src, | |
6506 | "void %s_template::set_type(template_sel template_type, " | |
6507 | "unsigned int list_length)\n" | |
6508 | "{\n" | |
6509 | "if (template_type != VALUE_LIST " | |
6510 | "&& template_type != COMPLEMENTED_LIST)\n" | |
6511 | "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n" | |
6512 | "clean_up();\n" | |
6513 | "set_selection(template_type);\n" | |
6514 | "value_list.n_values = list_length;\n" | |
6515 | "value_list.list_value = new %s_template[list_length];\n" | |
6516 | "}\n\n", name, dispname, name); | |
6517 | ||
6518 | /* list_item(int) function */ | |
6519 | ||
6520 | def = mputprintf(def, | |
6521 | "%s_template& list_item(unsigned int list_index) const;\n", name); | |
6522 | ||
6523 | src = mputprintf(src, | |
6524 | "%s_template& %s_template::list_item(unsigned int list_index) const\n" | |
6525 | "{\n" | |
6526 | "if (template_selection != VALUE_LIST " | |
6527 | "&& template_selection != COMPLEMENTED_LIST)\n" | |
6528 | "TTCN_error(\"Accessing a list element of a non-list template of " | |
6529 | "type %s.\");\n" | |
6530 | "if (list_index >= value_list.n_values)\n" | |
6531 | "TTCN_error(\"Index overflow in a value list template of type " | |
6532 | "%s.\");\n" | |
6533 | "return value_list.list_value[list_index];\n" | |
6534 | "}\n\n", name, name, dispname, dispname); | |
6535 | ||
6536 | /* log function */ | |
6537 | def = mputstr(def, "void log() const;\n"); | |
6538 | src = mputprintf(src, "void %s_template::log() const\n" | |
6539 | "{\n" | |
6540 | "switch (template_selection) {\n" | |
6541 | "case SPECIFIC_VALUE:\n" | |
6542 | "TTCN_Logger::log_event_str(\"{ }\");\n" | |
6543 | "break;\n" | |
6544 | "case COMPLEMENTED_LIST:\n" | |
6545 | "TTCN_Logger::log_event_str(\"complement \");\n" | |
6546 | "case VALUE_LIST:\n" | |
6547 | "TTCN_Logger::log_char('(');\n" | |
6548 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
6549 | "list_count++) {\n" | |
6550 | "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n" | |
6551 | "value_list.list_value[list_count].log();\n" | |
6552 | "}\n" | |
6553 | "TTCN_Logger::log_char(')');\n" | |
6554 | "break;\n" | |
6555 | "default:\n" | |
6556 | "log_generic();\n" | |
6557 | "}\n" | |
6558 | "log_ifpresent();\n" | |
6559 | "}\n\n", name); | |
6560 | ||
6561 | /* log_match function */ | |
3abe9331 | 6562 | def = mputprintf(def, "void log_match(const %s& match_value, " |
6563 | "boolean legacy = FALSE) const;\n", name); | |
6564 | src = mputprintf(src, "void %s_template::log_match(const %s& match_value, " | |
6565 | "boolean) const\n" | |
970ed795 EL |
6566 | "{\n" |
6567 | "match_value.log();\n" | |
6568 | "TTCN_Logger::log_event_str(\" with \");\n" | |
6569 | "log();\n" | |
6570 | "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n" | |
6571 | "else TTCN_Logger::log_event_str(\" unmatched\");\n" | |
6572 | "}\n\n", name, name); | |
6573 | ||
6574 | /* encode_text function */ | |
6575 | def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); | |
6576 | src = mputprintf(src, "void %s_template::encode_text(Text_Buf& text_buf) " | |
6577 | "const\n" | |
6578 | "{\n" | |
6579 | "encode_text_base(text_buf);\n" | |
6580 | "switch (template_selection) {\n" | |
6581 | "case OMIT_VALUE:\n" | |
6582 | "case ANY_VALUE:\n" | |
6583 | "case ANY_OR_OMIT:\n" | |
6584 | "case SPECIFIC_VALUE:\n" | |
6585 | "break;\n" | |
6586 | "case VALUE_LIST:\n" | |
6587 | "case COMPLEMENTED_LIST:\n" | |
6588 | "text_buf.push_int(value_list.n_values);\n" | |
6589 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
6590 | "list_count++)\n" | |
6591 | "value_list.list_value[list_count].encode_text(text_buf);\n" | |
6592 | "break;\n" | |
6593 | "default:\n" | |
6594 | "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported " | |
6595 | "template of type %s.\");\n" | |
6596 | "}\n" | |
6597 | "}\n\n", name, dispname); | |
6598 | ||
6599 | /* decode_text function */ | |
6600 | def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); | |
6601 | src = mputprintf(src, "void %s_template::decode_text(Text_Buf& text_buf)\n" | |
6602 | "{\n" | |
6603 | "clean_up();\n" | |
6604 | "decode_text_base(text_buf);\n" | |
6605 | "switch (template_selection) {\n" | |
6606 | "case OMIT_VALUE:\n" | |
6607 | "case ANY_VALUE:\n" | |
6608 | "case ANY_OR_OMIT:\n" | |
6609 | "case SPECIFIC_VALUE:\n" | |
6610 | "break;\n" | |
6611 | "case VALUE_LIST:\n" | |
6612 | "case COMPLEMENTED_LIST:\n" | |
6613 | "value_list.n_values = text_buf.pull_int().get_val();\n" | |
6614 | "value_list.list_value = new %s_template[value_list.n_values];\n" | |
6615 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " | |
6616 | "list_count++)\n" | |
6617 | "value_list.list_value[list_count].decode_text(text_buf);\n" | |
6618 | "break;\n" | |
6619 | "default:\n" | |
6620 | "TTCN_error(\"Text decoder: An unknown/unsupported selection was " | |
6621 | "received in a template of type %s.\");\n" | |
6622 | "}\n" | |
6623 | "}\n\n", name, name, dispname); | |
6624 | ||
6625 | /* set_param() */ | |
3abe9331 | 6626 | def = mputstr(def, "void set_param(Module_Param& param);\n"); |
970ed795 | 6627 | src = mputprintf(src, |
3abe9331 | 6628 | "void %s_template::set_param(Module_Param& param)\n" |
970ed795 EL |
6629 | "{\n" |
6630 | " param.basic_check(Module_Param::BC_TEMPLATE, \"empty record/set template\");\n" | |
3abe9331 | 6631 | " Module_Param_Ptr mp = ¶m;\n" |
6632 | " if (param.get_type() == Module_Param::MP_Reference) {\n" | |
6633 | " mp = param.get_referenced_param();\n" | |
6634 | " }\n" | |
6635 | " switch (mp->get_type()) {\n" | |
970ed795 EL |
6636 | " case Module_Param::MP_Omit:\n" |
6637 | " *this = OMIT_VALUE;\n" | |
6638 | " break;\n" | |
6639 | " case Module_Param::MP_Any:\n" | |
6640 | " *this = ANY_VALUE;\n" | |
6641 | " break;\n" | |
6642 | " case Module_Param::MP_AnyOrNone:\n" | |
6643 | " *this = ANY_OR_OMIT;\n" | |
6644 | " break;\n" | |
6645 | " case Module_Param::MP_List_Template:\n" | |
3abe9331 | 6646 | " case Module_Param::MP_ComplementList_Template: {\n" |
6647 | " %s_template temp;\n" | |
6648 | " temp.set_type(mp->get_type()==Module_Param::MP_List_Template ? " | |
6649 | "VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());\n" | |
6650 | " for (size_t p_i=0; p_i<mp->get_size(); p_i++) {\n" | |
6651 | " temp.list_item(p_i).set_param(*mp->get_elem(p_i));\n" | |
970ed795 | 6652 | " }\n" |
3abe9331 | 6653 | " *this = temp;\n" |
6654 | " break; }\n" | |
970ed795 | 6655 | " case Module_Param::MP_Value_List:\n" |
3abe9331 | 6656 | " if (mp->get_size()>0) param.type_error(\"empty record/set template\", \"%s\");\n" |
970ed795 EL |
6657 | " *this = NULL_VALUE;\n" |
6658 | " break;\n" | |
6659 | " default:\n" | |
6660 | " param.type_error(\"empty record/set template\", \"%s\");\n" | |
6661 | " }\n" | |
3abe9331 | 6662 | " is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();\n" |
6663 | "}\n\n", name, name, dispname, dispname); | |
6664 | ||
6665 | /* get_param() */ | |
6666 | def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); | |
6667 | src = mputprintf(src, | |
6668 | "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n" | |
6669 | "{\n" | |
6670 | " Module_Param* mp = NULL;\n" | |
6671 | " switch (template_selection) {\n" | |
6672 | " case UNINITIALIZED_TEMPLATE:\n" | |
6673 | " mp = new Module_Param_Unbound();\n" | |
6674 | " break;\n" | |
6675 | " case OMIT_VALUE:\n" | |
6676 | " mp = new Module_Param_Omit();\n" | |
6677 | " break;\n" | |
6678 | " case ANY_VALUE:\n" | |
6679 | " mp = new Module_Param_Any();\n" | |
6680 | " break;\n" | |
6681 | " case ANY_OR_OMIT:\n" | |
6682 | " mp = new Module_Param_AnyOrNone();\n" | |
6683 | " break;\n" | |
6684 | " case SPECIFIC_VALUE:\n" | |
6685 | " mp = new Module_Param_Value_List();\n" | |
6686 | " break;\n" | |
6687 | " case VALUE_LIST:\n" | |
6688 | " case COMPLEMENTED_LIST: {\n" | |
6689 | " if (template_selection == VALUE_LIST) {\n" | |
6690 | " mp = new Module_Param_List_Template();\n" | |
6691 | " }\n" | |
6692 | " else {\n" | |
6693 | " mp = new Module_Param_ComplementList_Template();\n" | |
6694 | " }\n" | |
6695 | " for (size_t i = 0; i < value_list.n_values; ++i) {\n" | |
6696 | " mp->add_elem(value_list.list_value[i].get_param(param_name));\n" | |
6697 | " }\n" | |
6698 | " break; }\n" | |
6699 | " default:\n" | |
6700 | " break;\n" | |
6701 | " }\n" | |
6702 | " if (is_ifpresent) {\n" | |
6703 | " mp->set_ifpresent();\n" | |
6704 | " }\n" | |
6705 | " return mp;\n" | |
6706 | "}\n\n", name); | |
970ed795 EL |
6707 | |
6708 | /* check template restriction */ | |
6709 | def = mputstr(def, "void check_restriction(template_res t_res, " | |
3abe9331 | 6710 | "const char* t_name=NULL, boolean legacy = FALSE) const;\n"); |
970ed795 EL |
6711 | src = mputprintf(src, |
6712 | "void %s_template::check_restriction(" | |
3abe9331 | 6713 | "template_res t_res, const char* t_name, boolean legacy) const\n" |
970ed795 EL |
6714 | "{\n" |
6715 | "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n" | |
6716 | "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n" | |
6717 | "case TR_OMIT:\n" | |
6718 | "if (template_selection==OMIT_VALUE) return;\n" | |
6719 | "case TR_VALUE:\n" | |
6720 | "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n" | |
6721 | "return;\n" | |
6722 | "case TR_PRESENT:\n" | |
3abe9331 | 6723 | "if (!match_omit(legacy)) return;\n" |
970ed795 EL |
6724 | "break;\n" |
6725 | "default:\n" | |
6726 | "return;\n" | |
6727 | "}\n" | |
6728 | "TTCN_error(\"Restriction `%%s' on template of type %%s " | |
6729 | "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n" | |
6730 | "}\n\n", name, dispname); | |
6731 | ||
6732 | defCommonRecordTemplate(name, &def, &src); | |
6733 | ||
6734 | def = mputstr(def, "};\n\n"); | |
6735 | ||
6736 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
6737 | Free(def); | |
6738 | ||
6739 | output->source.methods = mputstr(output->source.methods, src); | |
6740 | Free(src); | |
6741 | } | |
6742 | ||
6743 | static void defCommonRecordTemplate(const char *name, | |
6744 | char **def, char **src) | |
6745 | { | |
6746 | /* TTCN-3 ispresent() function */ | |
3abe9331 | 6747 | *def = mputstr(*def, "boolean is_present(boolean legacy = FALSE) const;\n"); |
970ed795 | 6748 | *src = mputprintf(*src, |
3abe9331 | 6749 | "boolean %s_template::is_present(boolean legacy) const\n" |
970ed795 EL |
6750 | "{\n" |
6751 | "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n" | |
3abe9331 | 6752 | "return !match_omit(legacy);\n" |
970ed795 EL |
6753 | "}\n\n", name); |
6754 | ||
6755 | /* match_omit() */ | |
3abe9331 | 6756 | *def = mputstr(*def, "boolean match_omit(boolean legacy = FALSE) const;\n"); |
970ed795 | 6757 | *src = mputprintf(*src, |
3abe9331 | 6758 | "boolean %s_template::match_omit(boolean legacy) const\n" |
970ed795 EL |
6759 | "{\n" |
6760 | "if (is_ifpresent) return TRUE;\n" | |
6761 | "switch (template_selection) {\n" | |
6762 | "case OMIT_VALUE:\n" | |
6763 | "case ANY_OR_OMIT:\n" | |
6764 | "return TRUE;\n" | |
6765 | "case VALUE_LIST:\n" | |
6766 | "case COMPLEMENTED_LIST:\n" | |
3abe9331 | 6767 | "if (legacy) {\n" |
970ed795 EL |
6768 | "for (unsigned int l_idx=0; l_idx<value_list.n_values; l_idx++)\n" |
6769 | "if (value_list.list_value[l_idx].match_omit())\n" | |
6770 | "return template_selection==VALUE_LIST;\n" | |
6771 | "return template_selection==COMPLEMENTED_LIST;\n" | |
3abe9331 | 6772 | "} // else fall through\n" |
970ed795 EL |
6773 | "default:\n" |
6774 | "return FALSE;\n" | |
6775 | "}\n" | |
6776 | "return FALSE;\n" | |
6777 | "}\n\n", name); | |
6778 | } | |
6779 | ||
6780 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ | |
6781 | ||
6782 | void defRecordClass2(const struct_def *sdef, output_struct *output) | |
6783 | { | |
6784 | size_t i; | |
6785 | size_t optional_num = 0; | |
6786 | const char *name = sdef->name; | |
6787 | char *def = NULL, *src = NULL; | |
6788 | ||
6789 | boolean xer_needed = sdef->hasXer && enable_xer(); | |
6790 | boolean raw_needed = sdef->hasRaw && enable_raw(); | |
6791 | boolean has_optional = FALSE; | |
6792 | boolean has_default = FALSE; | |
6793 | ||
6794 | const char* base_class = (sdef->nElements==0) ? "Empty_Record_Type" : "Record_Type"; | |
6795 | ||
6796 | /* class declaration code */ | |
6797 | output->header.class_decls = mputprintf(output->header.class_decls, | |
6798 | "class %s;\n", name); | |
6799 | ||
6800 | /* class definition and source code */ | |
6801 | def=mputprintf(def, "class %s : public %s {\n", name, base_class); | |
6802 | ||
6803 | /* data members */ | |
6804 | for (i = 0; i < sdef->nElements; i++) { | |
6805 | if(sdef->elements[i].isOptional) { | |
6806 | optional_num++; | |
6807 | def = mputprintf(def, " OPTIONAL<%s> field_%s;\n", | |
6808 | sdef->elements[i].type, | |
6809 | sdef->elements[i].name); | |
6810 | } else { | |
6811 | def = mputprintf(def, " %s field_%s;\n", | |
6812 | sdef->elements[i].type, sdef->elements[i].name); | |
6813 | } | |
6814 | } | |
6815 | if (sdef->nElements) { | |
6816 | def = mputprintf(def, " Base_Type* fld_vec[%lu];\n", (unsigned long)sdef->nElements); | |
6817 | } | |
6818 | ||
6819 | /* default constructor */ | |
6820 | if (sdef->nElements==0) { | |
6821 | def = mputprintf(def, "public:\n" | |
6822 | " %s();\n", name); | |
6823 | src = mputprintf(src, | |
6824 | "%s::%s() : Empty_Record_Type() {}\n\n", | |
6825 | name, name); | |
6826 | } else { | |
6827 | def = mputstr(def, " void init_vec();\n"); | |
6828 | src = mputprintf(src, "void %s::init_vec() { ", name); | |
6829 | for (i = 0; i < sdef->nElements; i++) { | |
6830 | src = mputprintf(src, "fld_vec[%lu]=&field_%s; ", | |
6831 | (unsigned long)i, sdef->elements[i].name); | |
6832 | } | |
6833 | src = mputstr(src, " }\n\n"); | |
6834 | ||
6835 | def = mputprintf(def, "public:\n" | |
6836 | " %s();\n", name); | |
6837 | src = mputprintf(src, | |
6838 | "%s::%s() : Record_Type() { init_vec(); }\n\n", name, name); | |
6839 | } | |
6840 | ||
6841 | /* copy constructor */ | |
6842 | if (sdef->nElements) { | |
6843 | def = mputprintf(def, " %s(const %s& other_value);\n", name, name); | |
6844 | src = mputprintf(src, "%s::%s(const %s& other_value) : Record_Type(other_value)\n", name, name, name); | |
6845 | src = mputstr(src, "{\n" | |
6846 | " if(!other_value.is_bound()) " | |
feade998 | 6847 | "TTCN_error(\"Copying an unbound record/set value.\");\n"); |
970ed795 EL |
6848 | for (i = 0; i < sdef->nElements; i++) { |
6849 | src = mputprintf(src, | |
6850 | "if (other_value.field_%s.is_bound() )\n" | |
6851 | " field_%s = other_value.field_%s;\n", | |
6852 | sdef->elements[i].name, sdef->elements[i].name, | |
6853 | sdef->elements[i].name); | |
6854 | } | |
6855 | ||
6856 | src = mputstr(src, "init_vec();\n" | |
6857 | "}\n\n"); | |
6858 | } else { | |
6859 | def = mputprintf(def, " %s(const %s& other_value): %s(other_value) {}\n", name, name, base_class); | |
6860 | } | |
6861 | ||
6862 | if (sdef->nElements>0) { /* constructor by fields */ | |
6863 | def = mputprintf(def, " %s(", name); | |
6864 | src = mputprintf(src, "%s::%s(", name, name); | |
6865 | for (i = 0; i < sdef->nElements; i++) { | |
6866 | char *tmp = NULL; | |
6867 | if (i > 0) tmp = mputstr(tmp, ",\n "); | |
6868 | if (sdef->elements[i].isOptional) | |
6869 | tmp = mputprintf | |
6870 | (tmp, | |
6871 | "const OPTIONAL<%s>& par_%s", | |
6872 | sdef->elements[i].type, sdef->elements[i].name); | |
6873 | else | |
6874 | tmp = mputprintf | |
6875 | (tmp, | |
6876 | "const %s& par_%s", | |
6877 | sdef->elements[i].type, sdef->elements[i].name); | |
6878 | def = mputstr(def, tmp); | |
6879 | src = mputstr(src, tmp); | |
6880 | Free(tmp); | |
6881 | } | |
6882 | def = mputstr(def, ");\n"); | |
6883 | src = mputprintf(src, ") : "); | |
6884 | for (i = 0; i < sdef->nElements; i++) { | |
6885 | if (i > 0) src = mputstr(src, ",\n "); | |
6886 | src = mputprintf(src, "field_%s(par_%s)", sdef->elements[i].name, | |
6887 | sdef->elements[i].name); | |
6888 | } | |
6889 | src = mputstr(src, "\n" | |
6890 | "{\n" | |
6891 | "init_vec();\n" | |
970ed795 EL |
6892 | "}\n\n"); |
6893 | } else { /* constructor from null */ | |
6894 | def = mputprintf(def, " %s(null_type) {bound_flag = TRUE;}\n", name); | |
6895 | } | |
6896 | ||
6897 | /* assignment operators */ | |
6898 | def = mputprintf(def, "inline %s& operator=(const %s& other_value) " | |
6899 | "{ set_value(&other_value); return *this; }\n\n", name, name); | |
6900 | if (sdef->nElements == 0) { | |
6901 | def = mputprintf(def, "inline %s& operator=(null_type) " | |
6902 | "{ bound_flag = TRUE; return *this; }\n", name); | |
6903 | } | |
6904 | ||
6905 | /* == operator */ | |
6906 | def = mputprintf(def, "inline boolean operator==(const %s& other_value) " | |
6907 | "const { return is_equal(&other_value); }\n", name); | |
6908 | /* != operator */ | |
6909 | def = mputprintf(def, | |
6910 | " inline boolean operator!=(const %s& other_value) const\n" | |
6911 | " { return !is_equal(&other_value); }\n\n", name); | |
6912 | ||
6913 | for (i = 0; i < sdef->nElements; i++) { | |
6914 | if(sdef->elements[i].isOptional) | |
6915 | def = mputprintf | |
6916 | (def, | |
6917 | " inline OPTIONAL<%s>& %s()\n" | |
6918 | " {return field_%s;}\n" | |
6919 | " inline const OPTIONAL<%s>& %s() const\n" | |
6920 | " {return field_%s;}\n", | |
6921 | sdef->elements[i].type, sdef->elements[i].name, | |
6922 | sdef->elements[i].name, | |
6923 | sdef->elements[i].type, sdef->elements[i].name, | |
6924 | sdef->elements[i].name); | |
6925 | else def = mputprintf | |
6926 | (def, | |
6927 | " inline %s& %s()\n" | |
6928 | " {return field_%s;}\n" | |
6929 | " inline const %s& %s() const\n" | |
6930 | " {return field_%s;}\n", | |
6931 | sdef->elements[i].type, sdef->elements[i].name, | |
6932 | sdef->elements[i].name, sdef->elements[i].type, | |
6933 | sdef->elements[i].name, sdef->elements[i].name); | |
6934 | ||
6935 | } | |
6936 | ||
6937 | /* override virtual functions where needed */ | |
6938 | def = mputprintf(def, | |
6939 | "Base_Type* clone() const { return new %s(*this); }\n" | |
6940 | "const TTCN_Typedescriptor_t* get_descriptor() const;\n" | |
6941 | "boolean is_set() const { return %s; }\n", | |
6942 | name, | |
6943 | (sdef->kind==SET) ? "TRUE" : "FALSE"); | |
6944 | src = mputprintf(src, | |
6945 | "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n", | |
6946 | name, name); | |
6947 | ||
6948 | if (sdef->nElements > 0) { | |
6949 | ||
6950 | /* field access functions */ | |
6951 | def = mputprintf(def, | |
6952 | "Base_Type* get_at(int index_value) { return fld_vec[index_value]; }\n" | |
6953 | "const Base_Type* get_at(int index_value) const { return fld_vec[index_value]; }\n\n" | |
6954 | "int get_count() const { return %lu; }\n", (unsigned long)sdef->nElements); | |
6955 | ||
6956 | /* override if there are optional fields */ | |
6957 | if (optional_num) { | |
6958 | def = mputprintf(def, | |
6959 | "int optional_count() const { return %lu; }\n", (unsigned long)optional_num); | |
6960 | } | |
6961 | ||
6962 | if (sdef->opentype_outermost) | |
6963 | def = mputstr(def, "boolean is_opentype_outermost() const { return TRUE; }\n"); | |
6964 | ||
6965 | /* FIXME: use static member in Record_Type and initialize somewhere */ | |
6966 | if (default_as_optional) | |
6967 | def = mputstr(def, "boolean default_as_optional() const { return TRUE; }\n"); | |
6968 | ||
6969 | for (i = 0; i < sdef->nElements; i++) { | |
6970 | if (sdef->elements[i].isOptional) { | |
6971 | has_optional = TRUE; | |
6972 | break; | |
6973 | } | |
6974 | } | |
6975 | ||
6976 | for (i = 0; i < sdef->nElements; i++) { | |
6977 | if (sdef->elements[i].isDefault) { | |
6978 | has_default = TRUE; | |
6979 | break; | |
6980 | } | |
6981 | } | |
6982 | def = mputstr(def, | |
6983 | "static const TTCN_Typedescriptor_t* fld_descriptors[];\n" | |
6984 | "const TTCN_Typedescriptor_t* fld_descr(int p_index) const;\n\n" | |
6985 | "static const char* fld_names[];\n" | |
6986 | "const char* fld_name(int p_index) const;\n\n"); | |
6987 | ||
6988 | src = mputprintf(src, "const TTCN_Typedescriptor_t* %s::fld_descriptors[] = ", name); | |
6989 | for (i = 0; i < sdef->nElements; i++) { | |
6990 | src = mputprintf(src, "%c &%s_descr_", | |
6991 | (i ? ',' : '{'), sdef->elements[i].typedescrname); | |
6992 | } | |
6993 | src = mputstr(src, " };\n"); | |
6994 | src = mputprintf(src, | |
6995 | "const TTCN_Typedescriptor_t* %s::fld_descr(int p_index) const " | |
6996 | "{ return fld_descriptors[p_index]; }\n\n", name); | |
6997 | ||
6998 | src = mputprintf(src, "const char* %s::fld_names[] = ", name); | |
6999 | for (i = 0; i < sdef->nElements; i++) { | |
7000 | src = mputprintf(src, "%c \"%s\"", | |
7001 | (i ? ',' : '{'), sdef->elements[i].dispname); | |
7002 | } | |
7003 | src = mputstr(src, " };\n"); | |
7004 | ||
7005 | src = mputprintf(src, | |
7006 | "const char* %s::fld_name(int p_index) const " | |
7007 | "{ return fld_names[p_index]; }\n\n", name); | |
7008 | ||
7009 | if (has_optional) { | |
7010 | def = mputstr(def, | |
7011 | "static const int optional_indexes[];\n" | |
7012 | "const int* get_optional_indexes() const;\n\n"); | |
7013 | src = mputprintf(src, "const int %s::optional_indexes[] = { ", name); | |
7014 | for (i = 0; i < sdef->nElements; i++) { | |
7015 | if (sdef->elements[i].isOptional) { | |
7016 | src = mputprintf(src, "%lu, ", (unsigned long)i); | |
7017 | } | |
7018 | } | |
7019 | src = mputstr(src, "-1 };\n"); | |
7020 | src = mputprintf(src, | |
7021 | "const int* %s::get_optional_indexes() const " | |
7022 | "{ return optional_indexes; }\n\n", name); | |
7023 | } | |
7024 | ||
7025 | if (has_default) { | |
7026 | def = mputstr(def, | |
7027 | "static const default_struct default_indexes[];\n" | |
7028 | "const default_struct* get_default_indexes() const;\n"); | |
7029 | src = mputprintf(src, "const Record_Type::default_struct %s::default_indexes[] = { ", name); | |
7030 | for (i = 0; i < sdef->nElements; i++) { | |
7031 | if (sdef->elements[i].isDefault) { | |
7032 | src = mputprintf(src, "{%lu,&%s}, ", | |
7033 | (unsigned long)i, sdef->elements[i].defvalname); | |
7034 | } | |
7035 | } | |
7036 | src = mputstr(src, "{-1,NULL} };\n"); | |
7037 | src = mputprintf(src, | |
7038 | "const Record_Type::default_struct* %s::get_default_indexes() const " | |
7039 | "{ return default_indexes; }\n", name); | |
7040 | } | |
7041 | ||
7042 | if (raw_needed) { | |
7043 | struct raw_option_struct *raw_options; | |
7044 | boolean haslengthto, haspointer, hascrosstag, has_ext_bit; | |
7045 | boolean generate_raw_function = FALSE; | |
7046 | ||
7047 | raw_options = (struct raw_option_struct*) | |
7048 | Malloc(sdef->nElements * sizeof(*raw_options)); | |
7049 | ||
7050 | set_raw_options(sdef, raw_options, &haslengthto, | |
7051 | &haspointer, &hascrosstag, &has_ext_bit); | |
7052 | ||
7053 | /* set the value of generate_raw_function: if the coding/decoding is too | |
7054 | complex for this type then generate the functions, otherwise generate | |
7055 | helper functions only which are called by the default RAW enc/dec | |
7056 | functions */ | |
7057 | if (haslengthto || haspointer || hascrosstag) { | |
7058 | generate_raw_function = TRUE; | |
7059 | goto check_generate_end; | |
7060 | } | |
7061 | for (i = 0; i < sdef->nElements; i++) { | |
7062 | if (raw_options[i].lengthto || raw_options[i].lengthof || | |
7063 | raw_options[i].lengthoffield || raw_options[i].pointerto || | |
7064 | raw_options[i].pointerof || raw_options[i].ptrbase || | |
7065 | raw_options[i].extbitgroup || raw_options[i].tag_type || | |
7066 | raw_options[i].delayed_decode || raw_options[i].nof_dependent_fields | |
7067 | || raw_options[i].dependent_fields) { | |
7068 | generate_raw_function = TRUE; | |
7069 | goto check_generate_end; | |
7070 | } | |
7071 | } | |
7072 | for (i = 0; i < sdef->nElements; i++) { | |
7073 | if (raw_options[i].lengthof || raw_options[i].lengthoffield || | |
7074 | raw_options[i].nof_dependent_fields || | |
7075 | raw_options[i].dependent_fields) { | |
7076 | generate_raw_function = TRUE; | |
7077 | goto check_generate_end; | |
7078 | } | |
7079 | } | |
7080 | if (sdef->raw.ext_bit_goup_num || sdef->raw.ext_bit_groups || | |
7081 | sdef->raw.lengthto || sdef->raw.lengthindex || | |
7082 | sdef->raw.taglist.nElements || sdef->raw.crosstaglist.nElements || | |
7083 | sdef->raw.presence.fieldnum || sdef->raw.presence.fields || | |
7084 | sdef->raw.member_name) { | |
7085 | generate_raw_function = TRUE; | |
7086 | goto check_generate_end; | |
7087 | } | |
7088 | for (i = 0; i < sdef->nElements; i++) { | |
7089 | if (sdef->elements[i].hasRaw) { | |
7090 | generate_raw_function = TRUE; | |
7091 | goto check_generate_end; | |
7092 | } | |
7093 | } | |
7094 | check_generate_end: | |
7095 | ||
7096 | if (generate_raw_function) { | |
7097 | def = mputprintf(def, | |
7098 | "int RAW_encode(const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n" | |
7099 | "virtual int RAW_encode_negtest(const Erroneous_descriptor_t *, const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n" | |
7100 | "int RAW_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, " | |
7101 | "int, raw_order_t, boolean no_err = FALSE, " | |
7102 | "int sel_field = -1, boolean first_call = TRUE);\n"); | |
7103 | src = generate_raw_coding(src, sdef, raw_options, haspointer, | |
7104 | hascrosstag, has_ext_bit); | |
7105 | } else { /* generate helper functions for the default RAW enc/dec */ | |
7106 | if (has_ext_bit) | |
7107 | def = mputstr(def,"boolean raw_has_ext_bit() const { return TRUE; }\n"); | |
7108 | } | |
7109 | for (i = 0; i < sdef->nElements; i++) { | |
7110 | Free(raw_options[i].lengthoffield); | |
7111 | Free(raw_options[i].dependent_fields); | |
7112 | } | |
7113 | Free(raw_options); | |
7114 | } /* if (raw_needed) */ | |
7115 | ||
7116 | if (xer_needed) { /* XERSTUFF codegen for record/SEQUENCE in RT2 */ | |
7117 | size_t num_attributes = 0; | |
7118 | ||
7119 | /* XER descriptors needed because of the xer antipattern */ | |
7120 | def = mputstr(def, | |
7121 | "static const XERdescriptor_t* xer_descriptors[];\n" | |
7122 | "const XERdescriptor_t* xer_descr(int p_index) const;\n" | |
7123 | "virtual boolean can_start_v(const char *name, const char *prefix, " | |
7124 | "XERdescriptor_t const& xd, unsigned int flavor);\n" | |
7125 | "static boolean can_start (const char *name, const char *prefix, " | |
7126 | "XERdescriptor_t const& xd, unsigned int flavor);\n"); | |
7127 | src = mputprintf(src, "const XERdescriptor_t* %s::xer_descriptors[] = ", name); | |
7128 | for (i = 0; i < sdef->nElements; i++) { | |
7129 | src = mputprintf(src, "%c &%s_xer_", | |
7130 | (i ? ',' : '{'), sdef->elements[i].typegen); | |
7131 | } | |
7132 | src = mputstr(src, " };\n"); | |
7133 | src = mputprintf(src, | |
7134 | "const XERdescriptor_t* %s::xer_descr(int p_index) const " | |
7135 | "{ return xer_descriptors[p_index]; }\n" | |
7136 | /* The virtual can_start_v hands off to the static can_start. | |
7137 | * We must make a virtual call in Record_Type::XER_decode because | |
7138 | * we don't know the actual type (derived from Record_Type) */ | |
7139 | "boolean %s::can_start_v(const char *p_name, const char *p_uri, " | |
7140 | "XERdescriptor_t const& p_td, unsigned int p_flavor)\n" | |
7141 | "{ return can_start(p_name, p_uri, p_td, p_flavor); }\n" | |
7142 | "boolean %s::can_start(const char *p_name, const char *p_uri, " | |
7143 | "XERdescriptor_t const& p_td, unsigned int p_flavor) {\n" | |
7144 | " boolean e_xer = is_exer(p_flavor);\n" | |
7145 | " if (!e_xer || (!(p_td.xer_bits & UNTAGGED) && !(p_flavor & USE_NIL))) return check_name(p_name, p_td, e_xer) && (!e_xer || check_namespace(p_uri, p_td));\n" | |
7146 | , name , name, name); | |
7147 | for (i = 0; i < sdef->nElements; i++) { | |
7148 | src = mputprintf(src, | |
7149 | " else if (%s::can_start(p_name, p_uri, %s_xer_, p_flavor)) return true;\n" | |
7150 | , sdef->elements[i].type, sdef->elements[i].typegen); | |
7151 | } | |
7152 | src = mputstr(src, | |
7153 | " return false;\n" | |
7154 | "}\n\n"); | |
7155 | /* end of antipattern */ | |
7156 | ||
7157 | /* calculate num_attributes in compile time */ | |
7158 | for ( i=0; i < sdef->nElements; ++i ) { | |
7159 | if (sdef->elements[i].xerAttribute | |
7160 | ||(sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) ++num_attributes; | |
7161 | else if (num_attributes) break; | |
7162 | } | |
7163 | ||
7164 | /* generate helper virtual functions for XER encdec */ | |
7165 | if (num_attributes) { | |
7166 | def = mputprintf(def, | |
7167 | "int get_xer_num_attr() const { return %lu; }\n", | |
7168 | (unsigned long)num_attributes); | |
7169 | } | |
7170 | } | |
7171 | else { /* XER not needed */ | |
7172 | def = mputstr(def, | |
7173 | "boolean can_start_v(const char *, const char *, XERdescriptor_t const&, unsigned int)\n" | |
7174 | "{ return FALSE; }\n" | |
7175 | ); | |
7176 | } /* if (xer_needed) */ | |
7177 | } /* if (sdef->nElements > 0) */ | |
7178 | ||
7179 | /* end of class definition */ | |
7180 | def = mputstr(def, "};\n\n"); | |
7181 | ||
7182 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
7183 | Free(def); | |
7184 | ||
7185 | output->source.methods = mputstr(output->source.methods, src); | |
7186 | Free(src); | |
7187 | } | |
7188 | ||
7189 | void defRecordTemplate2(const struct_def *sdef, output_struct *output) | |
7190 | { | |
7191 | int i; | |
7192 | const char *name = sdef->name; | |
7193 | char *def = NULL, *src = NULL; | |
7194 | ||
7195 | const char* base_class = (sdef->nElements==0) ? "Empty_Record_Template" : "Record_Template"; | |
7196 | ||
7197 | /* class declaration */ | |
7198 | output->header.class_decls = mputprintf(output->header.class_decls, | |
7199 | "class %s_template;\n", name); | |
7200 | ||
7201 | /* template class definition */ | |
7202 | def = mputprintf(def, "class %s_template : public %s {\n", name, base_class); | |
7203 | ||
7204 | if (sdef->nElements>0) { | |
7205 | /* set_specific function (used in field access members) */ | |
7206 | def = mputstr(def, "void set_specific();\n"); | |
7207 | src = mputprintf(src, "void %s_template::set_specific()\n" | |
7208 | "{\n" | |
7209 | "if (template_selection != SPECIFIC_VALUE) {\n" | |
7210 | "%s" | |
7211 | "clean_up();\n" | |
7212 | "single_value.n_elements = %lu;\n" | |
7213 | "single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);\n" | |
7214 | "set_selection(SPECIFIC_VALUE);\n", | |
7215 | name, sdef->nElements ? "boolean was_any = (template_selection == ANY_VALUE || template_selection == ANY_OR_OMIT);\n" : "", | |
7216 | (unsigned long)sdef->nElements); | |
7217 | for (i = 0; i < sdef->nElements; i++) { | |
7218 | src = mputprintf(src, | |
7219 | "single_value.value_elements[%d] = was_any ? new %s_template(%s) : new %s_template;\n", | |
7220 | i, sdef->elements[i].type, | |
7221 | sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE", | |
7222 | sdef->elements[i].type); | |
7223 | } | |
7224 | src = mputstr(src, | |
7225 | "}\n" | |
7226 | "}\n\n"); | |
7227 | } | |
7228 | ||
7229 | /* default constructor */ | |
7230 | def = mputprintf(def, "public:\n" | |
7231 | "%s_template(): %s() {}\n", name, base_class); | |
7232 | ||
7233 | if (sdef->nElements==0) { | |
7234 | /* ctor for value {} */ | |
7235 | def = mputprintf(def, "%s_template(null_type) : " | |
7236 | "Empty_Record_Template() { set_selection(SPECIFIC_VALUE); }\n", | |
7237 | name); | |
7238 | } | |
7239 | ||
7240 | /* constructor t1_template(template_sel other_value) */ | |
7241 | def = mputprintf(def, "%s_template(template_sel other_value): " | |
7242 | "%s(other_value) {}\n", name, base_class); | |
7243 | ||
7244 | /* constructor t1_template(const t1& other_value) */ | |
7245 | def = mputprintf(def, "%s_template(const %s& other_value): " | |
7246 | "%s() { copy_value(&other_value); }\n", | |
7247 | name, name, base_class); | |
7248 | ||
7249 | /* constructor t1_template(const OPTIONAL<t1>& other_value) */ | |
7250 | def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value): " | |
7251 | "%s() { copy_optional(&other_value); }\n", | |
7252 | name, name, base_class); | |
7253 | ||
7254 | /* copy constructor */ | |
7255 | def = mputprintf(def, "%s_template(const %s_template& other_value): %s() " | |
7256 | "{ copy_template(other_value); }\n", name, name, base_class); | |
7257 | ||
7258 | /* assignment operator <- template_sel */ | |
7259 | def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n", | |
7260 | name); | |
7261 | src = mputprintf(src, | |
7262 | "%s_template& %s_template::operator=(template_sel other_value)\n" | |
7263 | "{\n" | |
7264 | "check_single_selection(other_value);\n" | |
7265 | "clean_up();\n" | |
7266 | "set_selection(other_value);\n" | |
7267 | "return *this;\n" | |
7268 | "}\n\n", name, name); | |
7269 | ||
7270 | /* assignment operator <- value */ | |
7271 | def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n", | |
7272 | name, name); | |
7273 | src = mputprintf(src, | |
7274 | "%s_template& %s_template::operator=(const %s& other_value)\n" | |
7275 | "{\n" | |
7276 | "clean_up();\n" | |
7277 | "copy_value(&other_value);\n" | |
7278 | "return *this;\n" | |
7279 | "}\n\n", name, name, name); | |
7280 | ||
7281 | /* assignment operator <- optional value */ | |
7282 | def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& " | |
7283 | "other_value);\n", name, name); | |
7284 | src = mputprintf(src, | |
7285 | "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n" | |
7286 | "{\n" | |
7287 | "clean_up();\n" | |
7288 | "copy_optional(&other_value);\n" | |
7289 | "return *this;\n" | |
7290 | "}\n\n", name, name, name); | |
7291 | ||
7292 | /* assignment operator <- template*/ | |
7293 | def = mputprintf(def, | |
7294 | "%s_template& operator=(const %s_template& other_value);\n", | |
7295 | name, name); | |
7296 | src = mputprintf(src, | |
7297 | "%s_template& %s_template::operator=(const %s_template& other_value)\n" | |
7298 | "{\n" | |
7299 | "if (&other_value != this) {\n" | |
7300 | "clean_up();\n" | |
7301 | "copy_template(other_value);\n" | |
7302 | "}\n" | |
7303 | "return *this;\n" | |
7304 | "}\n\n", name, name, name); | |
7305 | ||
7306 | if (sdef->nElements==0) { | |
7307 | /* assignment op for value {} */ | |
7308 | def = mputprintf(def, "%s_template& operator=(null_type other_value);\n", | |
7309 | name); | |
7310 | src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n" | |
7311 | "{\n" | |
7312 | "clean_up();\n" | |
7313 | "set_selection(SPECIFIC_VALUE);\n" | |
7314 | "return *this;\n" | |
7315 | "}\n\n", name, name); | |
7316 | } | |
7317 | ||
7318 | /* match operation (template matching) */ | |
3abe9331 | 7319 | def = mputprintf(def, "inline boolean match(const %s& other_value, " |
7320 | "boolean legacy = FALSE) const " | |
7321 | "{ return matchv(&other_value, legacy); }\n", name); | |
970ed795 EL |
7322 | |
7323 | /* log_match */ | |
3abe9331 | 7324 | def = mputprintf(def, "inline void log_match(const %s& match_value, " |
7325 | "boolean legacy = FALSE) const " | |
7326 | "{ log_matchv(&match_value, legacy); }\n", name); | |
970ed795 EL |
7327 | |
7328 | /* valueof operation */ | |
7329 | def = mputprintf(def, "%s valueof() const;\n", name); | |
7330 | ||
7331 | src = mputprintf(src, "%s %s_template::valueof() const\n" | |
7332 | "{\n" | |
7333 | "%s ret_val;\n" | |
7334 | "valueofv(&ret_val);\n" | |
7335 | "return ret_val;\n" | |
7336 | "}\n\n", name, name, name); | |
7337 | ||
7338 | /* list_item(int) function */ | |
7339 | ||
7340 | def = mputprintf(def, | |
7341 | "inline %s_template& list_item(unsigned int list_index) const " | |
7342 | "{ return *(static_cast<%s_template*>(get_list_item(list_index))); }\n", name, name); | |
7343 | ||
7344 | if (sdef->nElements>0) { | |
7345 | /* template field access functions (non-const & const) */ | |
7346 | for (i = 0; i < sdef->nElements; i++) { | |
7347 | def = mputprintf(def, | |
7348 | "%s_template& %s();\n" | |
7349 | "const %s_template& %s() const;\n", | |
7350 | sdef->elements[i].type, sdef->elements[i].name, | |
7351 | sdef->elements[i].type, sdef->elements[i].name); | |
7352 | src = mputprintf(src, | |
7353 | "%s_template& %s_template::%s() { return *(static_cast<%s_template*>(get_at(%d))); }\n" | |
7354 | "const %s_template& %s_template::%s() const { return *(static_cast<const %s_template*>(get_at(%d))); }\n", | |
7355 | sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i, | |
7356 | sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i); | |
7357 | } | |
7358 | } | |
7359 | ||
7360 | /* virtual functions */ | |
7361 | def = mputprintf(def, | |
7362 | "%s* create() const { return new %s_template; }\n" | |
7363 | "const TTCN_Typedescriptor_t* get_descriptor() const;\n", | |
7364 | base_class, name); | |
7365 | src = mputprintf(src, | |
7366 | "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const { return &%s_descr_; }\n", | |
7367 | name, name); | |
7368 | ||
7369 | if (sdef->nElements>0) { | |
7370 | def = mputprintf(def, "const char* fld_name(int p_index) const;\n"); | |
7371 | src = mputprintf(src, | |
7372 | "const char* %s_template::fld_name(int p_index) const { return %s::fld_names[p_index]; }\n", | |
7373 | name, name); | |
7374 | } | |
7375 | ||
7376 | def = mputstr(def, "};\n\n"); | |
7377 | ||
7378 | output->header.class_defs = mputstr(output->header.class_defs, def); | |
7379 | Free(def); | |
7380 | ||
7381 | output->source.methods = mputstr(output->source.methods, src); | |
7382 | Free(src); | |
7383 | } | |
7384 |