| 1 | /////////////////////////////////////////////////////////////////////////////// |
| 2 | // Copyright (c) 2000-2015 Ericsson Telecom AB |
| 3 | // All rights reserved. This program and the accompanying materials |
| 4 | // are made available under the terms of the Eclipse Public License v1.0 |
| 5 | // which accompanies this distribution, and is available at |
| 6 | // http://www.eclipse.org/legal/epl-v10.html |
| 7 | /////////////////////////////////////////////////////////////////////////////// |
| 8 | #include <string.h> |
| 9 | #include "datatypes.h" |
| 10 | #include "../common/memory.h" |
| 11 | #include "record.h" |
| 12 | #include "encdec.h" |
| 13 | |
| 14 | #include "main.hh" |
| 15 | #include "error.h" |
| 16 | #include "ttcn3/compiler.h" |
| 17 | |
| 18 | static void defEmptyRecordClass(const struct_def *sdef, |
| 19 | output_struct *output); |
| 20 | |
| 21 | static void defEmptyRecordTemplate(const char *name, const char *dispname, |
| 22 | output_struct *output); |
| 23 | |
| 24 | /** this is common code for both empty and non-empty cases, called from |
| 25 | * both functions for template generation */ |
| 26 | static void defCommonRecordTemplate(const char *name, |
| 27 | char **def, char **src); |
| 28 | |
| 29 | /** code generation for original runtime */ |
| 30 | static void defRecordClass1(const struct_def *sdef, output_struct *output); |
| 31 | static void defRecordTemplate1(const struct_def *sdef, output_struct *output); |
| 32 | /** code generation for alternative runtime (TITAN_RUNTIME_2) */ |
| 33 | static void defRecordClass2(const struct_def *sdef, output_struct *output); |
| 34 | static void defRecordTemplate2(const struct_def *sdef, output_struct *output); |
| 35 | |
| 36 | void defRecordClass(const struct_def *sdef, output_struct *output) |
| 37 | { |
| 38 | if (use_runtime_2) defRecordClass2(sdef, output); |
| 39 | else defRecordClass1(sdef, output); |
| 40 | } |
| 41 | |
| 42 | void defRecordTemplate(const struct_def *sdef, output_struct *output) |
| 43 | { |
| 44 | if (use_runtime_2) defRecordTemplate2(sdef, output); |
| 45 | else defRecordTemplate1(sdef, output); |
| 46 | } |
| 47 | |
| 48 | struct raw_option_struct { |
| 49 | boolean lengthto; /* indicates whether this field contains a length */ |
| 50 | int lengthof; /* how many length indicators this field counted in */ |
| 51 | int *lengthoffield; /* the list of length indicator field indices */ |
| 52 | boolean pointerto; |
| 53 | int pointerof; |
| 54 | boolean ptrbase; |
| 55 | int extbitgroup; |
| 56 | int tag_type; |
| 57 | boolean delayed_decode; /* indicates whether the field has to be decoded |
| 58 | out of order (later) */ |
| 59 | int nof_dependent_fields; /* list of fields that are to be decoded */ |
| 60 | int *dependent_fields; /* after this field */ |
| 61 | }; |
| 62 | |
| 63 | static char *genRawFieldDecodeLimit(char *src, const struct_def *sdef, |
| 64 | int i, const struct raw_option_struct *raw_options); |
| 65 | |
| 66 | static char *genRawDecodeRecordField(char *src, const struct_def *sdef, |
| 67 | int i, const struct raw_option_struct *raw_options, boolean delayed_decode, |
| 68 | int *prev_ext_group); |
| 69 | |
| 70 | static void set_raw_options(const struct_def *sdef, |
| 71 | struct raw_option_struct *raw_options, boolean* haslengthto, |
| 72 | boolean* haspointer, boolean* hascrosstag, boolean* has_ext_bit); |
| 73 | |
| 74 | static char *generate_raw_coding(char *src, |
| 75 | const struct_def *sdef, struct raw_option_struct *raw_options, |
| 76 | boolean haspointer, boolean hascrosstag, boolean has_ext_bit); |
| 77 | static char *generate_raw_coding_negtest(char *src, |
| 78 | const struct_def *sdef, struct raw_option_struct *raw_options); |
| 79 | |
| 80 | void set_raw_options(const struct_def *sdef, |
| 81 | struct raw_option_struct *raw_options, boolean *haslengthto, |
| 82 | boolean *haspointer, boolean *hascrosstag, boolean *has_ext_bit) |
| 83 | { |
| 84 | int i; |
| 85 | for (i = 0; i < sdef->nElements; i++) { |
| 86 | raw_options[i].lengthto = FALSE; |
| 87 | raw_options[i].lengthof = 0; |
| 88 | raw_options[i].lengthoffield = NULL; |
| 89 | raw_options[i].pointerto = FALSE; |
| 90 | raw_options[i].pointerof = 0; |
| 91 | raw_options[i].ptrbase = FALSE; |
| 92 | raw_options[i].extbitgroup = 0; |
| 93 | raw_options[i].tag_type = 0; |
| 94 | raw_options[i].delayed_decode = FALSE; |
| 95 | raw_options[i].nof_dependent_fields = 0; |
| 96 | raw_options[i].dependent_fields = NULL; |
| 97 | } |
| 98 | *haslengthto = FALSE; |
| 99 | *haspointer = FALSE; |
| 100 | *hascrosstag = FALSE; |
| 101 | *has_ext_bit = sdef->hasRaw && sdef->raw.extension_bit!=XDEFNO && |
| 102 | sdef->raw.extension_bit!=XDEFDEFAULT; |
| 103 | for(i=0;i<sdef->nElements;i++){ |
| 104 | if(sdef->elements[i].hasRaw && |
| 105 | sdef->elements[i].raw.crosstaglist.nElements){ |
| 106 | *hascrosstag = TRUE; |
| 107 | break; |
| 108 | } |
| 109 | } |
| 110 | if(sdef->hasRaw){ /* fill tag_type. 0-No tag, >0 index of the tag + 1 */ |
| 111 | for(i=0;i<sdef->raw.taglist.nElements;i++){ |
| 112 | raw_options[sdef->raw.taglist.list[i].fieldnum].tag_type= i+1; |
| 113 | } |
| 114 | for(i=0;i<sdef->raw.ext_bit_goup_num;i++){ |
| 115 | int k; |
| 116 | for(k=sdef->raw.ext_bit_groups[i].from; |
| 117 | k<=sdef->raw.ext_bit_groups[i].to;k++) |
| 118 | raw_options[k].extbitgroup=i+1; |
| 119 | } |
| 120 | } |
| 121 | for(i=0;i<sdef->nElements;i++){ |
| 122 | if (sdef->elements[i].hasRaw && sdef->elements[i].raw.lengthto_num > 0) { |
| 123 | int j; |
| 124 | *haslengthto = TRUE; |
| 125 | raw_options[i].lengthto = TRUE; |
| 126 | for(j = 0; j < sdef->elements[i].raw.lengthto_num; j++) { |
| 127 | int field_index = sdef->elements[i].raw.lengthto[j]; |
| 128 | raw_options[field_index].lengthoffield = (int*) |
| 129 | Realloc(raw_options[field_index].lengthoffield, |
| 130 | (raw_options[field_index].lengthof + 1) * sizeof(int)); |
| 131 | raw_options[field_index].lengthoffield[ |
| 132 | raw_options[field_index].lengthof] = i; |
| 133 | raw_options[field_index].lengthof++; |
| 134 | } |
| 135 | } |
| 136 | if(sdef->elements[i].hasRaw && sdef->elements[i].raw.pointerto!=-1){ |
| 137 | raw_options[i].pointerto = TRUE; |
| 138 | raw_options[sdef->elements[i].raw.pointerto].pointerof=i+1; |
| 139 | *haspointer = TRUE; |
| 140 | raw_options[sdef->elements[i].raw.pointerbase].ptrbase = TRUE; |
| 141 | } |
| 142 | } |
| 143 | if (sdef->kind == RECORD && *hascrosstag) { |
| 144 | /* looking for fields that require delayed decoding because of |
| 145 | forward references in CROSSTAG */ |
| 146 | for (i = 0; i < sdef->nElements; i++) { |
| 147 | int j; |
| 148 | /* we are looking for a field index that is greater than i */ |
| 149 | size_t max_index = i; |
| 150 | if (!sdef->elements[i].hasRaw) continue; |
| 151 | for (j = 0; j < sdef->elements[i].raw.crosstaglist.nElements; j++) { |
| 152 | int k; |
| 153 | rawAST_coding_taglist *crosstag = |
| 154 | sdef->elements[i].raw.crosstaglist.list + j; |
| 155 | for (k = 0; k < crosstag->nElements; k++) { |
| 156 | rawAST_coding_field_list *keyid = crosstag->fields + k; |
| 157 | if (keyid->nElements >= 1) { |
| 158 | int field_index = keyid->fields[0].nthfield; |
| 159 | if (field_index > max_index) max_index = field_index; |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | if (max_index > i) { |
| 164 | raw_options[i].delayed_decode = TRUE; |
| 165 | raw_options[max_index].nof_dependent_fields++; |
| 166 | raw_options[max_index].dependent_fields = (int*) |
| 167 | Realloc(raw_options[max_index].dependent_fields, |
| 168 | raw_options[max_index].nof_dependent_fields * |
| 169 | sizeof(*raw_options[max_index].dependent_fields)); |
| 170 | raw_options[max_index].dependent_fields[ |
| 171 | raw_options[max_index].nof_dependent_fields - 1] = i; |
| 172 | } |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | |
| 177 | char* generate_raw_coding(char* src, |
| 178 | const struct_def *sdef, struct raw_option_struct *raw_options, |
| 179 | boolean haspointer, boolean hascrosstag, boolean has_ext_bit) |
| 180 | { |
| 181 | int i; |
| 182 | const char *name = sdef->name; |
| 183 | |
| 184 | if (sdef->kind == SET) { /* set decoder start */ |
| 185 | size_t mand_num = 0; |
| 186 | for (i = 0; i < sdef->nElements; i++) { |
| 187 | if (!sdef->elements[i].isOptional) mand_num++; |
| 188 | } |
| 189 | src = mputprintf(src, "int %s::RAW_decode(const TTCN_Typedescriptor_t& " |
| 190 | "p_td, TTCN_Buffer& p_buf, int limit, raw_order_t top_bit_ord, " |
| 191 | "boolean, int, boolean)\n" |
| 192 | "{\n" |
| 193 | "bound_flag = TRUE;\n" |
| 194 | "int prepaddlength = p_buf.increase_pos_padd(p_td.raw->prepadding);\n" |
| 195 | "limit -= prepaddlength;\n" |
| 196 | "int decoded_length = 0;\n" |
| 197 | "int field_map[%lu];\n" |
| 198 | "memset(field_map, 0, sizeof(field_map));\n", |
| 199 | name, (unsigned long) sdef->nElements); |
| 200 | if (mand_num > 0) |
| 201 | src = mputstr(src, "size_t nof_mand_fields = 0;\n"); |
| 202 | for (i = 0; i < sdef->nElements; i++) { |
| 203 | if (sdef->elements[i].isOptional) |
| 204 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", |
| 205 | sdef->elements[i].name); |
| 206 | } |
| 207 | src = mputstr(src, |
| 208 | "raw_order_t local_top_order;\n" |
| 209 | "if (p_td.raw->top_bit_order == TOP_BIT_INHERITED) " |
| 210 | "local_top_order = top_bit_ord;\n" |
| 211 | "else if (p_td.raw->top_bit_order == TOP_BIT_RIGHT) " |
| 212 | "local_top_order = ORDER_MSB;\n" |
| 213 | "else local_top_order = ORDER_LSB;\n" |
| 214 | "while (limit > 0) {\n" |
| 215 | "size_t fl_start_pos = p_buf.get_pos_bit();\n" |
| 216 | ); |
| 217 | for (i = 0; i < sdef->nElements; i++) { /* decoding fields with tag */ |
| 218 | if (raw_options[i].tag_type && |
| 219 | sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements > 0) { |
| 220 | rawAST_coding_taglist* cur_choice = |
| 221 | sdef->raw.taglist.list + raw_options[i].tag_type - 1; |
| 222 | size_t j; |
| 223 | boolean has_fixed = FALSE, has_variable = FALSE, flag_needed = FALSE; |
| 224 | for (j = 0; j < cur_choice->nElements; j++) { |
| 225 | if (cur_choice->fields[j].start_pos >= 0) { |
| 226 | if (has_fixed || has_variable) flag_needed = TRUE; |
| 227 | has_fixed = TRUE; |
| 228 | } else { |
| 229 | if (has_fixed) flag_needed = TRUE; |
| 230 | has_variable = TRUE; |
| 231 | } |
| 232 | if (has_fixed && has_variable) break; |
| 233 | } |
| 234 | src = mputprintf(src, "if (field_map[%lu] == 0) {\n", |
| 235 | (unsigned long) i); |
| 236 | if (flag_needed) |
| 237 | src = mputstr(src, "boolean already_failed = FALSE;\n"); |
| 238 | if (has_fixed) { |
| 239 | /* first check the fields we can precode |
| 240 | * try to decode those key variables whose position we know |
| 241 | * this way we might be able to step over bad values faster |
| 242 | */ |
| 243 | boolean first_fixed = TRUE; |
| 244 | src = mputstr(src, "raw_order_t temporal_top_order;\n" |
| 245 | "int temporal_decoded_length;\n"); |
| 246 | for (j = 0; j < cur_choice->nElements; j++) { |
| 247 | size_t k; |
| 248 | rawAST_coding_field_list *cur_field_list = cur_choice->fields + j; |
| 249 | if (cur_field_list->start_pos < 0) continue; |
| 250 | if (!first_fixed) src = mputstr(src, "if (!already_failed) {\n"); |
| 251 | for (k = cur_field_list->nElements - 1; k > 0; k--) { |
| 252 | src = mputprintf(src, "if (%s_descr_.raw->top_bit_order == " |
| 253 | "TOP_BIT_RIGHT) temporal_top_order = ORDER_MSB;\n" |
| 254 | "else if (%s_descr_.raw->top_bit_order == TOP_BIT_LEFT) " |
| 255 | "temporal_top_order = ORDER_LSB;\n" |
| 256 | "else ", cur_field_list->fields[k - 1].typedescr, |
| 257 | cur_field_list->fields[k - 1].typedescr); |
| 258 | } |
| 259 | src = mputprintf(src, "temporal_top_order = top_bit_ord;\n" |
| 260 | "%s temporal_%lu;\n" |
| 261 | "p_buf.set_pos_bit(fl_start_pos + %d);\n" |
| 262 | "temporal_decoded_length = temporal_%lu.RAW_decode(%s_descr_, " |
| 263 | "p_buf, limit, temporal_top_order, TRUE);\n" |
| 264 | "p_buf.set_pos_bit(fl_start_pos);\n" |
| 265 | "if (temporal_decoded_length > 0 && temporal_%lu == %s) {\n" |
| 266 | "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, " |
| 267 | "p_buf, limit, local_top_order, TRUE);\n" |
| 268 | "if (decoded_field_length %s 0 && (", |
| 269 | cur_field_list->fields[cur_field_list->nElements - 1].type, |
| 270 | (unsigned long) j, cur_field_list->start_pos, (unsigned long) j, |
| 271 | cur_field_list->fields[cur_field_list->nElements - 1].typedescr, |
| 272 | (unsigned long) j, cur_field_list->value, |
| 273 | sdef->elements[i].name, |
| 274 | sdef->elements[i].isOptional ? "()" : "", |
| 275 | sdef->elements[i].typedescrname, |
| 276 | sdef->elements[i].isOptional ? ">" : ">="); |
| 277 | src = genRawFieldChecker(src, cur_choice, TRUE); |
| 278 | src = mputstr(src, ")) {\n" |
| 279 | "decoded_length += decoded_field_length;\n" |
| 280 | "limit -= decoded_field_length;\n"); |
| 281 | if (!sdef->elements[i].isOptional) |
| 282 | src = mputstr(src, "nof_mand_fields++;\n"); |
| 283 | src = mputprintf(src, "field_map[%lu] = 1;\n" |
| 284 | "continue;\n" |
| 285 | "} else {\n" |
| 286 | "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i); |
| 287 | if (sdef->elements[i].isOptional) |
| 288 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", |
| 289 | sdef->elements[i].name); |
| 290 | if (flag_needed) src = mputstr(src, "already_failed = TRUE;\n"); |
| 291 | src = mputstr(src, "}\n" |
| 292 | "}\n"); |
| 293 | if (first_fixed) first_fixed = FALSE; |
| 294 | else src = mputstr(src, "}\n"); |
| 295 | } |
| 296 | } |
| 297 | if (has_variable) { |
| 298 | /* if there is one tag key whose position we don't know |
| 299 | * and we couldn't decide yet if element can be decoded or not |
| 300 | * than we have to decode it. |
| 301 | */ |
| 302 | if (flag_needed) src = mputstr(src, "if (!already_failed) {\n"); |
| 303 | src = mputprintf(src, "int decoded_field_length = " |
| 304 | "field_%s%s.RAW_decode(%s_descr_, p_buf, limit, " |
| 305 | "local_top_order, TRUE);\n" |
| 306 | "if (decoded_field_length %s 0 && (", |
| 307 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", |
| 308 | sdef->elements[i].typedescrname, |
| 309 | sdef->elements[i].isOptional ? ">" : ">="); |
| 310 | src = genRawFieldChecker(src, cur_choice, TRUE); |
| 311 | src = mputstr(src, ")) {\n" |
| 312 | "decoded_length += decoded_field_length;\n" |
| 313 | "limit -= decoded_field_length;\n"); |
| 314 | if (!sdef->elements[i].isOptional) |
| 315 | src = mputstr(src, "nof_mand_fields++;\n"); |
| 316 | src = mputprintf(src, "field_map[%lu] = 1;\n" |
| 317 | "continue;\n" |
| 318 | "} else {\n" |
| 319 | "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i); |
| 320 | if (sdef->elements[i].isOptional) |
| 321 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", |
| 322 | sdef->elements[i].name); |
| 323 | src = mputstr(src, "}\n"); |
| 324 | if (flag_needed) src = mputstr(src, "}\n"); |
| 325 | } |
| 326 | src = mputstr(src, "}\n"); |
| 327 | } |
| 328 | } |
| 329 | for (i = 0; i < sdef->nElements; i++) { |
| 330 | /* decoding fields without TAG */ |
| 331 | if (!raw_options[i].tag_type) { |
| 332 | boolean repeatable; |
| 333 | if (sdef->elements[i].of_type && sdef->elements[i].hasRaw && |
| 334 | sdef->elements[i].raw.repeatable == XDEFYES) repeatable = TRUE; |
| 335 | else { |
| 336 | repeatable = FALSE; |
| 337 | src = mputprintf(src, "if (field_map[%lu] == 0) ", |
| 338 | (unsigned long) i); |
| 339 | } |
| 340 | src = mputprintf(src, "{\n" |
| 341 | "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, " |
| 342 | "p_buf, limit, local_top_order, TRUE", |
| 343 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", |
| 344 | sdef->elements[i].typedescrname); |
| 345 | if (repeatable) |
| 346 | src = mputprintf(src, ", -1, field_map[%lu] == 0", |
| 347 | (unsigned long) i); |
| 348 | src = mputprintf(src, ");\n" |
| 349 | "if (decoded_field_length %s 0) {\n" |
| 350 | "decoded_length += decoded_field_length;\n" |
| 351 | "limit -= decoded_field_length;\n", |
| 352 | sdef->elements[i].isOptional ? ">" : ">="); |
| 353 | if (repeatable) { |
| 354 | if (!sdef->elements[i].isOptional) src = mputprintf(src, |
| 355 | "if (field_map[%lu] == 0) nof_mand_fields++;\n", |
| 356 | (unsigned long) i); |
| 357 | src = mputprintf(src, "field_map[%lu]++;\n", (unsigned long) i); |
| 358 | } else { |
| 359 | if (!sdef->elements[i].isOptional) |
| 360 | src = mputstr(src, "nof_mand_fields++;\n"); |
| 361 | src = mputprintf(src, "field_map[%lu] = 1;\n", (unsigned long) i); |
| 362 | } |
| 363 | src = mputstr(src, "continue;\n" |
| 364 | "} else {\n" |
| 365 | "p_buf.set_pos_bit(fl_start_pos);\n"); |
| 366 | if (sdef->elements[i].isOptional) { |
| 367 | if (repeatable) |
| 368 | src = mputprintf(src, "if (field_map[%lu] == 0) ", |
| 369 | (unsigned long) i); |
| 370 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", |
| 371 | sdef->elements[i].name); |
| 372 | } |
| 373 | src = mputstr(src, "}\n" |
| 374 | "}\n"); |
| 375 | } |
| 376 | } |
| 377 | for (i = 0; i < sdef->nElements; i++){ |
| 378 | /* decoding fields with tag OTHERWISE */ |
| 379 | if (raw_options[i].tag_type && |
| 380 | sdef->raw.taglist.list[raw_options[i].tag_type-1].nElements == 0) { |
| 381 | src = mputprintf(src, "if (field_map[%lu] == 0) {\n" |
| 382 | "int decoded_field_length = field_%s%s.RAW_decode(%s_descr_, " |
| 383 | "p_buf, limit, local_top_order, TRUE);\n" |
| 384 | "if (decoded_field_length %s 0) {\n" |
| 385 | "decoded_length += decoded_field_length;\n" |
| 386 | "limit -= decoded_field_length;\n", (unsigned long) i, |
| 387 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", |
| 388 | sdef->elements[i].typedescrname, |
| 389 | sdef->elements[i].isOptional ? ">" : ">="); |
| 390 | if (!sdef->elements[i].isOptional) |
| 391 | src = mputstr(src, "nof_mand_fields++;\n"); |
| 392 | src = mputprintf(src, "field_map[%lu] = 1;\n" |
| 393 | "continue;\n" |
| 394 | "} else {\n" |
| 395 | "p_buf.set_pos_bit(fl_start_pos);\n", (unsigned long) i); |
| 396 | if (sdef->elements[i].isOptional) |
| 397 | src = mputprintf(src, "field_%s = OMIT_VALUE;\n", |
| 398 | sdef->elements[i].name); |
| 399 | src = mputstr(src, "}\n" |
| 400 | "}\n"); |
| 401 | } |
| 402 | } |
| 403 | src = mputstr(src, "break;\n" /* no field decoded successfully, quit */ |
| 404 | "}\n"); |
| 405 | if (mand_num > 0) src = mputprintf(src, |
| 406 | "if (nof_mand_fields != %lu) return limit ? -1 : -TTCN_EncDec::ET_INCOMPL_MSG;\n", |
| 407 | (unsigned long) mand_num); |
| 408 | /* If not all required fields were decoded and there are no bits left, |
| 409 | * that means that the last field was decoded successfully but used up |
| 410 | * the buffer. Signal "incomplete". If there were bits left, that means that |
| 411 | * no field could be decoded from them; signal an error. |
| 412 | */ |
| 413 | src = mputstr(src, "return decoded_length + prepaddlength + " |
| 414 | "p_buf.increase_pos_padd(p_td.raw->padding);\n" |
| 415 | "}\n\n"); |
| 416 | } else { |
| 417 | /* set decoder end, record decoder start */ |
| 418 | int prev_ext_group = 0; |
| 419 | src = mputprintf(src, |
| 420 | "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, " |
| 421 | "TTCN_Buffer& p_buf, int limit, raw_order_t top_bit_ord, boolean no_err, " |
| 422 | "int, boolean)\n" |
| 423 | "{ (void)no_err;\n" |
| 424 | " bound_flag = TRUE;\n" |
| 425 | " int prepaddlength=p_buf.increase_pos_padd(p_td.raw->prepadding);\n" |
| 426 | " limit-=prepaddlength;\n" |
| 427 | " size_t last_decoded_pos = p_buf.get_pos_bit();\n" |
| 428 | " int decoded_length = 0;\n" |
| 429 | " int decoded_field_length = 0;\n" |
| 430 | " raw_order_t local_top_order;\n" |
| 431 | , name); |
| 432 | if (hascrosstag) { |
| 433 | src = mputstr(src, " int selected_field = -1;\n"); |
| 434 | } |
| 435 | if (sdef->raw.ext_bit_goup_num) { |
| 436 | src=mputstr(src, " int group_limit = 0;\n"); |
| 437 | } |
| 438 | src=mputstr(src, |
| 439 | " if(p_td.raw->top_bit_order==TOP_BIT_INHERITED)" |
| 440 | "local_top_order=top_bit_ord;\n" |
| 441 | " else if(p_td.raw->top_bit_order==TOP_BIT_RIGHT)local_top_order" |
| 442 | "=ORDER_MSB;\n" |
| 443 | " else local_top_order=ORDER_LSB;\n" |
| 444 | ); |
| 445 | if(has_ext_bit){ |
| 446 | src=mputstr(src, |
| 447 | " {\n" |
| 448 | " cbyte* data=p_buf.get_read_data();\n" |
| 449 | " int count=1;\n" |
| 450 | " unsigned mask = 1 << (local_top_order==ORDER_LSB ? 0 : 7);\n" |
| 451 | " if(p_td.raw->extension_bit==EXT_BIT_YES){\n" |
| 452 | " while((data[count-1] & mask)==0 && count*8<(int)limit) count++;\n" |
| 453 | " }\n" |
| 454 | " else{\n" |
| 455 | " while((data[count-1] & mask)!=0 && count*8<(int)limit) count++;\n" |
| 456 | " }\n" |
| 457 | " if(limit) limit=count*8;\n" |
| 458 | " }\n" |
| 459 | ); |
| 460 | } |
| 461 | if(haspointer) |
| 462 | src=mputstr(src, |
| 463 | " int end_of_available_data=last_decoded_pos+limit;\n"); |
| 464 | for(i=0;i<sdef->nElements;i++){ |
| 465 | if(raw_options[i].pointerof) |
| 466 | src=mputprintf(src, |
| 467 | " int start_of_field%lu=-1;\n" |
| 468 | ,(unsigned long) i |
| 469 | ); |
| 470 | if(raw_options[i].ptrbase) |
| 471 | src=mputprintf(src, |
| 472 | " int start_pos_of_field%lu=-1;\n" |
| 473 | ,(unsigned long) i |
| 474 | ); |
| 475 | if(raw_options[i].lengthto) |
| 476 | src=mputprintf(src, |
| 477 | " int value_of_length_field%lu = 0;\n" |
| 478 | ,(unsigned long) i |
| 479 | ); |
| 480 | } |
| 481 | for(i=0;i<sdef->nElements;i++){ /* decoding fields */ |
| 482 | if (raw_options[i].delayed_decode) { |
| 483 | int j; |
| 484 | /* checking whether there are enough bits in the buffer to decode |
| 485 | the field */ |
| 486 | src = mputstr(src, " if ("); |
| 487 | src = genRawFieldDecodeLimit(src, sdef, i, raw_options); |
| 488 | src = mputprintf(src, " < %d) return -TTCN_EncDec::ET_LEN_ERR;\n", |
| 489 | sdef->elements[i].raw.length); |
| 490 | /* skipping over the field that has to be decoded later because of |
| 491 | forward referencing in CROSSTAG */ |
| 492 | src = mputprintf(src, |
| 493 | " size_t start_of_field%lu = p_buf.get_pos_bit();\n" |
| 494 | " p_buf.set_pos_bit(start_of_field%lu + %d);\n" |
| 495 | " decoded_length += %d;\n" |
| 496 | " last_decoded_pos += %d;\n" |
| 497 | " limit -= %d;\n", |
| 498 | (unsigned long) i, (unsigned long) i, sdef->elements[i].raw.length, |
| 499 | sdef->elements[i].raw.length, |
| 500 | sdef->elements[i].raw.length, sdef->elements[i].raw.length); |
| 501 | for (j = 0; j < raw_options[i].lengthof; j++) { |
| 502 | src = mputprintf(src, |
| 503 | " value_of_length_field%d -= %d;\n", |
| 504 | raw_options[i].lengthoffield[j], sdef->elements[i].raw.length); |
| 505 | } |
| 506 | } else { |
| 507 | src = genRawDecodeRecordField(src, sdef, i, raw_options, FALSE, |
| 508 | &prev_ext_group); |
| 509 | if (raw_options[i].nof_dependent_fields > 0) { |
| 510 | int j; |
| 511 | for (j = 0; j < raw_options[i].nof_dependent_fields; j++) { |
| 512 | int dependent_field_index = raw_options[i].dependent_fields[j]; |
| 513 | /* seek to the beginning of the dependent field */ |
| 514 | src = mputprintf(src, |
| 515 | " p_buf.set_pos_bit(start_of_field%d);\n", |
| 516 | dependent_field_index); |
| 517 | /* decode the dependent field */ |
| 518 | src = genRawDecodeRecordField(src, sdef, dependent_field_index, |
| 519 | raw_options, TRUE, &prev_ext_group); |
| 520 | } |
| 521 | if (i < sdef->nElements - 1) { |
| 522 | /* seek back if there are more regular fields to decode */ |
| 523 | src = mputstr(src, |
| 524 | " p_buf.set_pos_bit(last_decoded_pos);\n"); |
| 525 | } |
| 526 | } |
| 527 | } |
| 528 | } /* decoding fields*/ |
| 529 | |
| 530 | if(sdef->hasRaw && sdef->raw.presence.nElements > 0) |
| 531 | { |
| 532 | src = mputstr(src, " if ("); |
| 533 | src = genRawFieldChecker(src, &sdef->raw.presence, FALSE); |
| 534 | src = mputstr(src, ") return -1;\n"); |
| 535 | } |
| 536 | |
| 537 | src=mputstr(src, |
| 538 | " p_buf.set_pos_bit(last_decoded_pos);\n" |
| 539 | " return decoded_length+prepaddlength+" |
| 540 | "p_buf.increase_pos_padd(p_td.raw->padding);\n}\n\n"); |
| 541 | } /* record decoder end */ |
| 542 | |
| 543 | src = mputprintf(src, /* encoder */ |
| 544 | "int %s::RAW_encode(const TTCN_Typedescriptor_t&%s, " |
| 545 | "RAW_enc_tree& myleaf) const {\n", name, |
| 546 | use_runtime_2 ? " p_td" : ""); |
| 547 | if (use_runtime_2) { |
| 548 | src = mputstr(src, " if (err_descr) return RAW_encode_negtest(err_descr, p_td, myleaf);\n"); |
| 549 | } |
| 550 | src = mputprintf(src, |
| 551 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" |
| 552 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" |
| 553 | " int encoded_length = 0;\n" |
| 554 | " myleaf.isleaf = false;\n" |
| 555 | " myleaf.body.node.num_of_nodes = %lu;\n" |
| 556 | " myleaf.body.node.nodes = init_nodes_of_enc_tree(%lu);\n", |
| 557 | (unsigned long)sdef->nElements, (unsigned long)sdef->nElements); |
| 558 | /* init nodes */ |
| 559 | for (i = 0; i < sdef->nElements; i++) { |
| 560 | if (sdef->elements[i].isOptional) { |
| 561 | src = mputprintf(src, |
| 562 | " if (field_%s.ispresent()) {\n", sdef->elements[i].name); |
| 563 | } |
| 564 | src = mputprintf(src, |
| 565 | " myleaf.body.node.nodes[%lu] = new RAW_enc_tree(true, &myleaf, " |
| 566 | "&(myleaf.curr_pos), %lu, %s_descr_.raw);\n", |
| 567 | (unsigned long)i, (unsigned long)i, sdef->elements[i].typedescrname); |
| 568 | if (sdef->elements[i].isOptional) { |
| 569 | src = mputprintf(src, |
| 570 | " }\n" |
| 571 | " else myleaf.body.node.nodes[%lu] = NULL;\n", (unsigned long)i); |
| 572 | } |
| 573 | } |
| 574 | for (i = 0; i < sdef->raw.ext_bit_goup_num; i++) { |
| 575 | if (sdef->raw.ext_bit_groups[i].ext_bit != XDEFNO) { |
| 576 | src = mputprintf(src, |
| 577 | " {\n" |
| 578 | " int node_idx = %d;\n" |
| 579 | " while (node_idx <= %d && myleaf.body.node.nodes[node_idx] == NULL) node_idx++;\n" |
| 580 | " if (myleaf.body.node.nodes[node_idx]) {\n" |
| 581 | " myleaf.body.node.nodes[node_idx]->ext_bit_handling = 1;\n" |
| 582 | " myleaf.body.node.nodes[node_idx]->ext_bit = %s;\n }\n" |
| 583 | " node_idx = %d;\n" |
| 584 | " while (node_idx >= %d && myleaf.body.node.nodes[node_idx] == NULL) node_idx--;\n" |
| 585 | " if (myleaf.body.node.nodes[node_idx]) myleaf.body.node.nodes[node_idx]" |
| 586 | "->ext_bit_handling += 2;\n" |
| 587 | " }\n", |
| 588 | sdef->raw.ext_bit_groups[i].from, |
| 589 | sdef->raw.ext_bit_groups[i].to, |
| 590 | sdef->raw.ext_bit_groups[i].ext_bit == XDEFYES ? "EXT_BIT_YES" : "EXT_BIT_REVERSE", |
| 591 | sdef->raw.ext_bit_groups[i].to, |
| 592 | sdef->raw.ext_bit_groups[i].from); |
| 593 | } |
| 594 | } |
| 595 | for (i = 0; i < sdef->nElements; i++) { |
| 596 | /* encoding fields */ |
| 597 | if (sdef->elements[i].isOptional) { |
| 598 | src = mputprintf(src, |
| 599 | " if (field_%s.ispresent()) {\n", sdef->elements[i].name); |
| 600 | } |
| 601 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex == NULL |
| 602 | && sdef->elements[i].raw.union_member_num == 0) { |
| 603 | /* encoding of lenghto fields */ |
| 604 | int a; |
| 605 | src = mputprintf(src, |
| 606 | " encoded_length += %d;\n" |
| 607 | " myleaf.body.node.nodes[%lu]->calc = CALC_LENGTH;\n" |
| 608 | " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n" |
| 609 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.num_of_fields = %d;\n" |
| 610 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.unit = %d;\n" |
| 611 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields = " |
| 612 | "init_lengthto_fields_list(%d);\n" |
| 613 | " myleaf.body.node.nodes[%lu]->length = %d;\n", |
| 614 | sdef->elements[i].raw.fieldlength, (unsigned long)i, |
| 615 | (unsigned long)i, sdef->elements[i].typedescrname, |
| 616 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, |
| 617 | (unsigned long)i, sdef->elements[i].raw.unit, |
| 618 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, |
| 619 | (unsigned long)i, sdef->elements[i].raw.fieldlength); |
| 620 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { |
| 621 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 622 | src = mputprintf(src, |
| 623 | " if (field_%s.ispresent()) {\n", |
| 624 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); |
| 625 | } |
| 626 | src = mputprintf(src, |
| 627 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].level = " |
| 628 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" |
| 629 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].pos = " |
| 630 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", |
| 631 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a], |
| 632 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]); |
| 633 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 634 | src = mputprintf(src, |
| 635 | " } else {\n" |
| 636 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].level = 0;\n" |
| 637 | " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields[%d].pos = 0;\n" |
| 638 | " }\n", (unsigned long)i, a, (unsigned long)i, a); |
| 639 | } |
| 640 | } |
| 641 | } else if (raw_options[i].pointerto) { |
| 642 | /* encoding of pointerto fields */ |
| 643 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { |
| 644 | src = mputprintf(src, |
| 645 | " if (field_%s.ispresent()) {\n", |
| 646 | sdef->elements[sdef->elements[i].raw.pointerto].name); |
| 647 | } |
| 648 | src = mputprintf(src, |
| 649 | " encoded_length += %d;\n" |
| 650 | " myleaf.body.node.nodes[%lu]->calc = CALC_POINTER;\n" |
| 651 | " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n" |
| 652 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.unit = %d;\n" |
| 653 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.ptr_offset = %d;\n" |
| 654 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.ptr_base = %d;\n" |
| 655 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.target.level = " |
| 656 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" |
| 657 | " myleaf.body.node.nodes[%lu]->calcof.pointerto.target.pos = " |
| 658 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n" |
| 659 | " myleaf.body.node.nodes[%lu]->length = %d;\n", |
| 660 | sdef->elements[i].raw.fieldlength,(unsigned long)i, |
| 661 | (unsigned long)i, sdef->elements[i].typedescrname, |
| 662 | (unsigned long)i, sdef->elements[i].raw.unit, |
| 663 | (unsigned long)i, sdef->elements[i].raw.ptroffset, |
| 664 | (unsigned long)i, sdef->elements[i].raw.pointerbase, |
| 665 | (unsigned long)i, sdef->elements[i].raw.pointerto, |
| 666 | (unsigned long)i, sdef->elements[i].raw.pointerto, |
| 667 | (unsigned long)i, sdef->elements[i].raw.fieldlength); |
| 668 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { |
| 669 | src = mputprintf(src, |
| 670 | " } else {\n" |
| 671 | " INTEGER atm;\n" |
| 672 | " atm = 0;\n" |
| 673 | " encoded_length += atm.RAW_encode(%s_descr_" |
| 674 | ", *myleaf.body.node.nodes[%lu]);\n" |
| 675 | " }\n", |
| 676 | sdef->elements[i].typedescrname, (unsigned long)i); |
| 677 | } |
| 678 | } else { |
| 679 | /* encoding of normal fields */ |
| 680 | src = mputprintf(src, |
| 681 | " encoded_length += field_%s%s.RAW_encode(%s_descr_" |
| 682 | ", *myleaf.body.node.nodes[%lu]);\n", |
| 683 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", |
| 684 | sdef->elements[i].typedescrname, (unsigned long)i); |
| 685 | } |
| 686 | if (sdef->elements[i].isOptional) { |
| 687 | src = mputstr(src, " }\n"); |
| 688 | } |
| 689 | } |
| 690 | for (i = 0; i < sdef->nElements; i++) { |
| 691 | /* fill presence, tag and crosstag */ |
| 692 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex) { |
| 693 | /* encoding of lenghto fields */ |
| 694 | int a; |
| 695 | if (sdef->elements[i].isOptional) { |
| 696 | src = mputprintf(src, |
| 697 | " if (field_%s.ispresent()) {\n", |
| 698 | sdef->elements[i].name); |
| 699 | } |
| 700 | src = mputprintf(src, |
| 701 | " if (myleaf.body.node.nodes[%lu]->body.node.nodes[%d]) {\n" |
| 702 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" |
| 703 | "calc = CALC_LENGTH;\n" |
| 704 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" |
| 705 | "coding_descr = &%s_descr_;\n" |
| 706 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" |
| 707 | "calcof.lengthto.num_of_fields = %d;\n" |
| 708 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" |
| 709 | "calcof.lengthto.unit = %d;\n" |
| 710 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" |
| 711 | "calcof.lengthto.fields = " |
| 712 | "init_lengthto_fields_list(%d);\n", |
| 713 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 714 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 715 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 716 | sdef->elements[i].raw.lengthindex->typedescr, |
| 717 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 718 | sdef->elements[i].raw.lengthto_num, |
| 719 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 720 | sdef->elements[i].raw.unit, |
| 721 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 722 | sdef->elements[i].raw.lengthto_num); |
| 723 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { |
| 724 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 725 | src = mputprintf(src, |
| 726 | " if (field_%s.ispresent()) {\n", |
| 727 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); |
| 728 | } |
| 729 | src = mputprintf(src, |
| 730 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]" |
| 731 | "->calcof.lengthto.fields[%d].level = " |
| 732 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" |
| 733 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]" |
| 734 | "->calcof.lengthto.fields[%d].pos = " |
| 735 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", |
| 736 | (unsigned long)i,sdef->elements[i].raw.lengthindex->nthfield, |
| 737 | a, sdef->elements[i].raw.lengthto[a], |
| 738 | (unsigned long)i,sdef->elements[i].raw.lengthindex->nthfield, |
| 739 | a, sdef->elements[i].raw.lengthto[a]); |
| 740 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 741 | src = mputprintf(src, |
| 742 | " } else {\n" |
| 743 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" |
| 744 | "calcof.lengthto.fields[%d].level = 0;\n" |
| 745 | " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" |
| 746 | "calcof.lengthto.fields[%d].pos = 0;\n" |
| 747 | " }\n", |
| 748 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a, |
| 749 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a); |
| 750 | } |
| 751 | } |
| 752 | src = mputstr(src, " }\n"); |
| 753 | if (sdef->elements[i].isOptional) { |
| 754 | src = mputstr(src, " }\n"); |
| 755 | } |
| 756 | } |
| 757 | if (raw_options[i].lengthto && sdef->elements[i].raw.union_member_num) { |
| 758 | /* encoding of lenghto fields */ |
| 759 | int a; |
| 760 | if (sdef->elements[i].isOptional) { |
| 761 | src = mputprintf(src, |
| 762 | " if (field_%s.ispresent()) ", sdef->elements[i].name); |
| 763 | } |
| 764 | |
| 765 | src = mputprintf(src, |
| 766 | " {\n" |
| 767 | " int sel_field = 0;\n" |
| 768 | " while (myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field] == NULL) " |
| 769 | "{ sel_field++; }\n" |
| 770 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" |
| 771 | "calc = CALC_LENGTH;\n" |
| 772 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" |
| 773 | "calcof.lengthto.num_of_fields = %d;\n" |
| 774 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" |
| 775 | "calcof.lengthto.unit = %d;\n" |
| 776 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" |
| 777 | "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", |
| 778 | (unsigned long)i,(unsigned long)i, |
| 779 | (unsigned long)i,sdef->elements[i].raw.lengthto_num, |
| 780 | (unsigned long)i,sdef->elements[i].raw.unit, |
| 781 | (unsigned long)i,sdef->elements[i].raw.lengthto_num); |
| 782 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { |
| 783 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 784 | src = mputprintf(src, |
| 785 | " if (field_%s.ispresent()) {\n", |
| 786 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); |
| 787 | } |
| 788 | src = mputprintf(src, |
| 789 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" |
| 790 | "->calcof.lengthto.fields[%d].level = " |
| 791 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" |
| 792 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" |
| 793 | "->calcof.lengthto.fields[%d].pos = " |
| 794 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", |
| 795 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a], |
| 796 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]); |
| 797 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 798 | src = mputprintf(src, |
| 799 | " }else{\n" |
| 800 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" |
| 801 | "->calcof.lengthto.fields[%d].level = 0;\n" |
| 802 | " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]" |
| 803 | "->calcof.lengthto.fields[%d].pos = 0;\n" |
| 804 | " }\n", |
| 805 | (unsigned long)i, a, |
| 806 | (unsigned long)i, a); |
| 807 | } |
| 808 | } |
| 809 | src = mputstr(src, |
| 810 | " }\n"); |
| 811 | } |
| 812 | if (raw_options[i].tag_type && sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements) { |
| 813 | /* tag */ |
| 814 | rawAST_coding_taglist *cur_choice = |
| 815 | sdef->raw.taglist.list + raw_options[i].tag_type - 1; |
| 816 | src = mputstr(src, " if ("); |
| 817 | if (sdef->elements[i].isOptional) { |
| 818 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); |
| 819 | } |
| 820 | src = genRawFieldChecker(src, cur_choice, FALSE); |
| 821 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); |
| 822 | src = mputstr(src,") {\n"); |
| 823 | src = genRawTagChecker(src, cur_choice); |
| 824 | src=mputstr(src," }\n"); |
| 825 | } |
| 826 | if (sdef->elements[i].hasRaw && sdef->elements[i].raw.presence.nElements) { |
| 827 | /* presence */ |
| 828 | src = mputstr(src, " if ("); |
| 829 | if (sdef->elements[i].isOptional) { |
| 830 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); |
| 831 | } |
| 832 | src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, FALSE); |
| 833 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); |
| 834 | src = mputstr(src, ") {\n"); |
| 835 | src = genRawTagChecker(src, &sdef->elements[i].raw.presence); |
| 836 | src = mputstr(src," }\n"); |
| 837 | } |
| 838 | if (sdef->elements[i].hasRaw && |
| 839 | sdef->elements[i].raw.crosstaglist.nElements) { |
| 840 | /* crosstag */ |
| 841 | int a; |
| 842 | if (sdef->elements[i].isOptional) { |
| 843 | src = mputprintf(src, |
| 844 | " if (field_%s.ispresent()) {\n", |
| 845 | sdef->elements[i].name); |
| 846 | } |
| 847 | src = mputprintf(src, |
| 848 | " switch (field_%s%s.get_selection()) {\n", |
| 849 | sdef->elements[i].name,sdef->elements[i].isOptional ? "()" : ""); |
| 850 | for (a = 0; a < sdef->elements[i].raw.crosstaglist.nElements; a++) { |
| 851 | rawAST_coding_taglist *cur_choice = |
| 852 | sdef->elements[i].raw.crosstaglist.list + a; |
| 853 | if (cur_choice->nElements > 0) { |
| 854 | src = mputprintf(src, " case %s%s%s:\n" |
| 855 | " if (", sdef->elements[i].type, |
| 856 | "::ALT_", cur_choice->fieldName); |
| 857 | src = genRawFieldChecker(src, cur_choice, FALSE); |
| 858 | src = mputstr(src, ") {\n"); |
| 859 | if (!strcmp(cur_choice->fields[0].value, "OMIT_VALUE")) { |
| 860 | if (cur_choice->fields[0].nElements != 1) |
| 861 | NOTSUPP("omit value with multiple fields in CROSSTAG"); |
| 862 | /* eliminating the corresponding encoded leaf, which will have |
| 863 | the same effect as if the referred field had been omit */ |
| 864 | src = mputprintf(src, |
| 865 | " encoded_length -= myleaf.body.node.nodes[%d]->length;\n" |
| 866 | " delete myleaf.body.node.nodes[%d];\n" |
| 867 | " myleaf.body.node.nodes[%d] = NULL;\n", |
| 868 | cur_choice->fields[0].fields[0].nthfield, |
| 869 | cur_choice->fields[0].fields[0].nthfield, |
| 870 | cur_choice->fields[0].fields[0].nthfield); |
| 871 | } else { |
| 872 | int ll; |
| 873 | src = mputprintf(src, |
| 874 | " RAW_enc_tr_pos pr_pos;\n" |
| 875 | " pr_pos.level = myleaf.curr_pos.level + %d;\n" |
| 876 | " int new_pos[] = { ", |
| 877 | cur_choice->fields[0].nElements); |
| 878 | for (ll = 0; ll < cur_choice->fields[0].nElements; ll++) { |
| 879 | if (ll > 0) src = mputstr(src, ", "); |
| 880 | src = mputprintf(src, "%d", |
| 881 | cur_choice->fields[0].fields[ll].nthfield); |
| 882 | } |
| 883 | src = mputprintf(src, " };\n" |
| 884 | " pr_pos.pos = init_new_tree_pos(myleaf.curr_pos, %d, " |
| 885 | "new_pos);\n", |
| 886 | cur_choice->fields[0].nElements); |
| 887 | if (cur_choice->fields[0].value[0] == ' ') { |
| 888 | /* the value is a string literal (the encoder can be called |
| 889 | on that object directly */ |
| 890 | src = mputprintf(src, |
| 891 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" |
| 892 | " if (temp_leaf != NULL)\n" |
| 893 | " %s.RAW_encode(%s_descr_,*temp_leaf);\n" |
| 894 | " else\n" |
| 895 | " TTCN_EncDec_ErrorContext::error\n" |
| 896 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged," |
| 897 | " but omitted value.\");\n", |
| 898 | cur_choice->fields[0].value, |
| 899 | cur_choice->fields[0].fields[ |
| 900 | cur_choice->fields[0].nElements - 1].typedescr); |
| 901 | } else { |
| 902 | /* a temporary object needs to be created for encoding */ |
| 903 | src = mputprintf(src, |
| 904 | " %s new_val(%s);\n" |
| 905 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" |
| 906 | " if (temp_leaf != NULL)\n" |
| 907 | " new_val.RAW_encode(%s_descr_,*temp_leaf);\n" |
| 908 | " else\n" |
| 909 | " TTCN_EncDec_ErrorContext::error\n" |
| 910 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged," |
| 911 | " but omitted value.\");\n", |
| 912 | cur_choice->fields[0].fields[ |
| 913 | cur_choice->fields[0].nElements - 1].type, |
| 914 | cur_choice->fields[0].value, |
| 915 | cur_choice->fields[0].fields[ |
| 916 | cur_choice->fields[0].nElements - 1].typedescr); |
| 917 | } |
| 918 | src = mputstr(src, " free_tree_pos(pr_pos.pos);\n"); |
| 919 | } |
| 920 | src = mputstr(src, " }\n" |
| 921 | " break;\n"); |
| 922 | } |
| 923 | } |
| 924 | src = mputstr(src, " default:;\n" |
| 925 | " }\n"); |
| 926 | if (sdef->elements[i].isOptional) src = mputstr(src, " }\n"); |
| 927 | } |
| 928 | } |
| 929 | /* presence */ |
| 930 | if (sdef->hasRaw && sdef->raw.presence.nElements > 0) { |
| 931 | src = mputstr(src, " if ("); |
| 932 | src = genRawFieldChecker(src, &sdef->raw.presence, FALSE); |
| 933 | src = mputstr(src,") {\n"); |
| 934 | src = genRawTagChecker(src, &sdef->raw.presence); |
| 935 | src = mputstr(src," }\n"); |
| 936 | } |
| 937 | src = mputstr(src, " return myleaf.length = encoded_length;\n}\n\n"); |
| 938 | |
| 939 | if (use_runtime_2) |
| 940 | src = generate_raw_coding_negtest(src, sdef, raw_options); |
| 941 | return src; |
| 942 | } |
| 943 | |
| 944 | char *generate_raw_coding_negtest(char *src, const struct_def *sdef, |
| 945 | struct raw_option_struct *raw_options) |
| 946 | { |
| 947 | int i; |
| 948 | const char *name = sdef->name; |
| 949 | src = mputprintf(src, |
| 950 | /* Count the nodes and discover the new node order only. No node creation |
| 951 | or encoding. */ |
| 952 | "int %s::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr, " |
| 953 | "const TTCN_Typedescriptor_t& /*p_td*/, RAW_enc_tree& myleaf) const\n" |
| 954 | "{\n" |
| 955 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" |
| 956 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" |
| 957 | " int idx_map[%lu];\n" |
| 958 | " for (int idx_map_idx = 0; idx_map_idx < %lu; ++idx_map_idx)\n" |
| 959 | " idx_map[idx_map_idx] = -1;\n" |
| 960 | " (void)idx_map;\n" |
| 961 | " int encoded_length = 0;\n" |
| 962 | " int num_fields = get_count();\n" |
| 963 | " myleaf.isleaf = false;\n" |
| 964 | " myleaf.body.node.num_of_nodes = 0;\n" |
| 965 | " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n" |
| 966 | " if ((p_err_descr->omit_before != -1) &&\n" |
| 967 | " (field_idx < p_err_descr->omit_before))\n" |
| 968 | " continue;\n" |
| 969 | " const Erroneous_values_t *err_vals = p_err_descr->get_field_err_values(field_idx);\n" |
| 970 | " const Erroneous_descriptor_t *emb_descr = p_err_descr->get_field_emb_descr(field_idx);\n" |
| 971 | " if (err_vals && err_vals->before)\n" |
| 972 | " ++myleaf.body.node.num_of_nodes;\n" |
| 973 | " if (err_vals && err_vals->value) {\n" |
| 974 | " if (err_vals->value->errval) {\n" |
| 975 | " // Field is modified, but it's still there. Otherwise, it's\n" |
| 976 | " // initialized to `-1'.\n" |
| 977 | " idx_map[field_idx] = -2;\n" |
| 978 | " ++myleaf.body.node.num_of_nodes;\n" |
| 979 | " }\n" |
| 980 | " } else {\n" |
| 981 | " if (emb_descr) idx_map[field_idx] = -2;\n" |
| 982 | " else idx_map[field_idx] = myleaf.body.node.num_of_nodes;\n" |
| 983 | " ++myleaf.body.node.num_of_nodes;\n" |
| 984 | " }\n" |
| 985 | " if (err_vals && err_vals->after)\n" |
| 986 | " ++myleaf.body.node.num_of_nodes;\n" |
| 987 | " if ((p_err_descr->omit_after != -1) &&\n" |
| 988 | " (field_idx >= p_err_descr->omit_after))\n" |
| 989 | " break;\n" |
| 990 | " }\n", |
| 991 | name, (unsigned long)sdef->nElements, (unsigned long)sdef->nElements); |
| 992 | /* Init nodes. */ |
| 993 | src = mputprintf(src, |
| 994 | " myleaf.body.node.nodes =\n" |
| 995 | " init_nodes_of_enc_tree(myleaf.body.node.num_of_nodes);\n" |
| 996 | " TTCN_EncDec_ErrorContext e_c;\n" |
| 997 | " int node_pos = 0;\n" |
| 998 | " int next_optional_idx = 0;\n" |
| 999 | " const int *my_optional_indexes = get_optional_indexes();\n" |
| 1000 | " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n" |
| 1001 | " boolean is_optional_field = my_optional_indexes &&\n" |
| 1002 | " (my_optional_indexes[next_optional_idx] == field_idx);\n" |
| 1003 | " if ((p_err_descr->omit_before != -1) &&\n" |
| 1004 | " (field_idx < p_err_descr->omit_before)) {\n" |
| 1005 | " if (is_optional_field) ++next_optional_idx;\n" |
| 1006 | " continue;\n" |
| 1007 | " }\n" |
| 1008 | " const Erroneous_values_t *err_vals =\n" |
| 1009 | " p_err_descr->get_field_err_values(field_idx);\n" |
| 1010 | " if (err_vals && err_vals->before) {\n" |
| 1011 | " if (err_vals->before->errval == NULL)\n" |
| 1012 | " TTCN_error(\"internal error: erroneous before value missing\");\n" |
| 1013 | " if (err_vals->before->raw) {\n" |
| 1014 | " myleaf.body.node.nodes[node_pos] =\n" |
| 1015 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" |
| 1016 | " node_pos, err_vals->before->errval" |
| 1017 | "->get_descriptor()->raw);\n" |
| 1018 | " } else {\n" |
| 1019 | " if (err_vals->before->type_descr == NULL)\n" |
| 1020 | " TTCN_error(\"internal error: erroneous before typedescriptor " |
| 1021 | "missing\");\n" |
| 1022 | " myleaf.body.node.nodes[node_pos] =\n" |
| 1023 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" |
| 1024 | " node_pos, err_vals->before->type_descr->raw);\n" |
| 1025 | " }\n" |
| 1026 | " ++node_pos;\n" |
| 1027 | " }\n" |
| 1028 | " if (err_vals && err_vals->value) {\n" |
| 1029 | " if (err_vals->value->errval) {\n" |
| 1030 | " e_c.set_msg(\"'%%s'(erroneous value): \", fld_name(field_idx));\n" |
| 1031 | " if (err_vals->value->raw) {\n" |
| 1032 | " myleaf.body.node.nodes[node_pos] =\n" |
| 1033 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" |
| 1034 | " node_pos, err_vals->value->errval" |
| 1035 | "->get_descriptor()->raw);\n" |
| 1036 | " } else {\n" |
| 1037 | " if (err_vals->value->type_descr == NULL)\n" |
| 1038 | " TTCN_error(\"internal error: erroneous value typedescriptor " |
| 1039 | "missing\");\n" |
| 1040 | " myleaf.body.node.nodes[node_pos] =\n" |
| 1041 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" |
| 1042 | " node_pos, err_vals->value->type_descr->raw);\n" |
| 1043 | " }\n" |
| 1044 | " ++node_pos;\n" |
| 1045 | " }\n" |
| 1046 | " } else {\n" |
| 1047 | " e_c.set_msg(\"'%%s': \", fld_name(field_idx));\n" |
| 1048 | " if (!is_optional_field || get_at(field_idx)->ispresent()) {\n" |
| 1049 | " myleaf.body.node.nodes[node_pos] =\n" |
| 1050 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" |
| 1051 | " node_pos, fld_descr(field_idx)->raw);\n" |
| 1052 | " } else {\n" |
| 1053 | " // `omitted' field.\n" |
| 1054 | " myleaf.body.node.nodes[node_pos] = NULL;\n" |
| 1055 | " }\n" |
| 1056 | " ++node_pos;\n" |
| 1057 | " }\n" |
| 1058 | " if (err_vals && err_vals->after) {\n" |
| 1059 | " if (err_vals->after->errval == NULL)\n" |
| 1060 | " TTCN_error(\"internal error: erroneous before value missing\");\n" |
| 1061 | " if (err_vals->after->raw) {\n" |
| 1062 | " myleaf.body.node.nodes[node_pos] =\n" |
| 1063 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" |
| 1064 | " node_pos, err_vals->after->errval" |
| 1065 | "->get_descriptor()->raw);\n" |
| 1066 | " } else {\n" |
| 1067 | " if (err_vals->after->type_descr == NULL)\n" |
| 1068 | " TTCN_error(\"internal error: erroneous after typedescriptor " |
| 1069 | "missing\");\n" |
| 1070 | " myleaf.body.node.nodes[node_pos] =\n" |
| 1071 | " new RAW_enc_tree(true, &myleaf, &(myleaf.curr_pos),\n" |
| 1072 | " node_pos, err_vals->after->type_descr->raw);\n" |
| 1073 | " }\n" |
| 1074 | " ++node_pos;\n" |
| 1075 | " }\n" |
| 1076 | " if (is_optional_field) ++next_optional_idx;\n" |
| 1077 | " if ((p_err_descr->omit_after != -1) &&\n" |
| 1078 | " (field_idx >= p_err_descr->omit_after))\n" |
| 1079 | " break;\n" |
| 1080 | " }\n"); |
| 1081 | /* Handling of the tricky attributes. A simple integer array will be used |
| 1082 | to track changes (field positions) in the record. |
| 1083 | int idx_map[n_fields] = { |
| 1084 | -1 (= field 0. was omitted), |
| 1085 | 1 (= field 1. can be found at index 1.), |
| 1086 | -2 (= field 2. is still at index 2., but its value has changed) }; */ |
| 1087 | for (i = 0; i < sdef->raw.ext_bit_goup_num; i++) { |
| 1088 | if (sdef->raw.ext_bit_groups[i].ext_bit != XDEFNO) { |
| 1089 | src = mputprintf(src, |
| 1090 | " {\n" |
| 1091 | " bool in_between_modified = false;\n" |
| 1092 | " for (int idx_map_idx = %d; idx_map_idx <= %d; ++idx_map_idx)\n" |
| 1093 | " if (idx_map[idx_map_idx] < 0) {\n" |
| 1094 | " in_between_modified = true;\n" |
| 1095 | " break;\n" |
| 1096 | " }\n" |
| 1097 | " if (idx_map[%d] < 0 || idx_map[%d] < 0 ||\n" |
| 1098 | " %d != idx_map[%d] - idx_map[%d] || in_between_modified) {\n" |
| 1099 | " e_c.set_msg(\"Field #%d and/or #%d: \");\n" |
| 1100 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1101 | " \"Conflicting negative testing attributes, extension bit " |
| 1102 | "group #%d will be ignored\");\n" |
| 1103 | " } else {\n" |
| 1104 | " int node_idx = idx_map[%d];\n" |
| 1105 | " while (node_idx <= idx_map[%d] &&\n" |
| 1106 | " myleaf.body.node.nodes[node_idx] == NULL)\n" |
| 1107 | " node_idx++;\n" |
| 1108 | " if (myleaf.body.node.nodes[node_idx]) {\n" |
| 1109 | " myleaf.body.node.nodes[node_idx]->ext_bit_handling = 1;\n" |
| 1110 | " myleaf.body.node.nodes[node_idx]->ext_bit = %s;\n" |
| 1111 | " }\n" |
| 1112 | " node_idx = idx_map[%d];\n" |
| 1113 | " while (node_idx >= idx_map[%d] &&\n" |
| 1114 | " myleaf.body.node.nodes[node_idx] == NULL)\n" |
| 1115 | " node_idx--;\n" |
| 1116 | " if (myleaf.body.node.nodes[node_idx])\n" |
| 1117 | " myleaf.body.node.nodes[node_idx]->ext_bit_handling += 2;\n" |
| 1118 | " }\n" |
| 1119 | " }\n", |
| 1120 | sdef->raw.ext_bit_groups[i].from, |
| 1121 | sdef->raw.ext_bit_groups[i].to, |
| 1122 | sdef->raw.ext_bit_groups[i].from, |
| 1123 | sdef->raw.ext_bit_groups[i].to, |
| 1124 | sdef->raw.ext_bit_groups[i].to - sdef->raw.ext_bit_groups[i].from, |
| 1125 | sdef->raw.ext_bit_groups[i].to, |
| 1126 | sdef->raw.ext_bit_groups[i].from, |
| 1127 | sdef->raw.ext_bit_groups[i].from, |
| 1128 | sdef->raw.ext_bit_groups[i].to, i, |
| 1129 | sdef->raw.ext_bit_groups[i].from, |
| 1130 | sdef->raw.ext_bit_groups[i].to, |
| 1131 | sdef->raw.ext_bit_groups[i].ext_bit == XDEFYES ? "EXT_BIT_YES" : "EXT_BIT_REVERSE", |
| 1132 | sdef->raw.ext_bit_groups[i].to, |
| 1133 | sdef->raw.ext_bit_groups[i].from); |
| 1134 | } |
| 1135 | } |
| 1136 | for (i = 0; i < sdef->nElements; i++) { |
| 1137 | if (sdef->elements[i].isOptional) { |
| 1138 | src = mputprintf(src, |
| 1139 | " if (field_%s.ispresent()) {\n", |
| 1140 | sdef->elements[i].name); |
| 1141 | } |
| 1142 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex == NULL |
| 1143 | && sdef->elements[i].raw.union_member_num == 0) { |
| 1144 | /* Encoding of lenghto fields. */ |
| 1145 | int a; |
| 1146 | src = mputprintf(src, |
| 1147 | " if (idx_map[%lu] < 0) {\n" |
| 1148 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1149 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1150 | " \"Conflicting negative testing attributes, LENGTHTO " |
| 1151 | "attribute will be ignored\");\n" |
| 1152 | " } else {\n" |
| 1153 | " bool negtest_confl_lengthto = false;\n", |
| 1154 | (unsigned long)i, sdef->elements[i].name); |
| 1155 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { |
| 1156 | src = mputprintf(src, |
| 1157 | " if (idx_map[%lu] < 0) {\n" |
| 1158 | " negtest_confl_lengthto = true;\n" |
| 1159 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1160 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1161 | " \"Conflicting negative testing attributes, LENGTHTO " |
| 1162 | "attribute will be ignored\");\n" |
| 1163 | " }\n", |
| 1164 | (unsigned long)sdef->elements[i].raw.lengthto[a], |
| 1165 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); |
| 1166 | } |
| 1167 | src = mputprintf(src, |
| 1168 | " if (!negtest_confl_lengthto) {\n" |
| 1169 | " encoded_length += %d;\n" |
| 1170 | " myleaf.body.node.nodes[idx_map[%lu]]->calc = CALC_LENGTH;\n" |
| 1171 | " myleaf.body.node.nodes[idx_map[%lu]]->coding_descr = &%s_descr_;\n" |
| 1172 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.num_of_fields = %d;\n" |
| 1173 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.unit = %d;\n" |
| 1174 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields = " |
| 1175 | "init_lengthto_fields_list(%d);\n" |
| 1176 | " myleaf.body.node.nodes[idx_map[%lu]]->length = %d;\n", |
| 1177 | sdef->elements[i].raw.fieldlength, (unsigned long)i, |
| 1178 | (unsigned long)i, sdef->elements[i].typedescrname, |
| 1179 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, |
| 1180 | (unsigned long)i, sdef->elements[i].raw.unit, |
| 1181 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, |
| 1182 | (unsigned long)i, sdef->elements[i].raw.fieldlength); |
| 1183 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { |
| 1184 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 1185 | src = mputprintf(src, |
| 1186 | " if (field_%s.ispresent()) {\n", |
| 1187 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); |
| 1188 | } |
| 1189 | src = mputprintf(src, |
| 1190 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields[%lu].level = " |
| 1191 | "myleaf.body.node.nodes[idx_map[%lu]]->curr_pos.level;\n" |
| 1192 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields[%lu].pos = " |
| 1193 | "myleaf.body.node.nodes[idx_map[%lu]]->curr_pos.pos;\n", |
| 1194 | (unsigned long)i, (unsigned long)a, |
| 1195 | (unsigned long)sdef->elements[i].raw.lengthto[a], |
| 1196 | (unsigned long)i, (unsigned long)a, |
| 1197 | (unsigned long)sdef->elements[i].raw.lengthto[a]); |
| 1198 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 1199 | src = mputprintf(src, |
| 1200 | " } else {\n" |
| 1201 | " myleaf.body.node.nodes[idx_map[%lu]]->" |
| 1202 | "calcof.lengthto.fields[%lu].level = 0;\n" |
| 1203 | " myleaf.body.node.nodes[idx_map[%lu]]->" |
| 1204 | "calcof.lengthto.fields[%lu].pos = 0;\n" |
| 1205 | " }\n", |
| 1206 | (unsigned long)i, (unsigned long)a, |
| 1207 | (unsigned long)i, (unsigned long)a); |
| 1208 | } |
| 1209 | } |
| 1210 | /* Closing inner index check. */ |
| 1211 | src = mputstr(src, |
| 1212 | " }\n"); |
| 1213 | /* Closing outer index check. */ |
| 1214 | src = mputstr(src, |
| 1215 | " }\n"); |
| 1216 | } else if (raw_options[i].pointerto) { |
| 1217 | /* Encoding of pointerto fields. */ |
| 1218 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { |
| 1219 | src = mputprintf(src, |
| 1220 | " if (field_%s.ispresent()) {\n", |
| 1221 | sdef->elements[sdef->elements[i].raw.pointerto].name); |
| 1222 | } |
| 1223 | src = mputprintf(src, |
| 1224 | " bool in_between_modified_pointerto_%s = false;\n" |
| 1225 | " for (int idx_map_idx = %d; idx_map_idx <= %d; ++idx_map_idx) {\n" |
| 1226 | " if (idx_map[idx_map_idx] < 0) {\n" |
| 1227 | " in_between_modified_pointerto_%s = true;\n" |
| 1228 | " break;\n" |
| 1229 | " }\n" |
| 1230 | " }\n" |
| 1231 | " if (idx_map[%lu] < 0 || idx_map[%lu] < 0 ||\n" |
| 1232 | " %lu != idx_map[%lu] - idx_map[%lu] || in_between_modified_pointerto_%s) {\n" |
| 1233 | " e_c.set_msg(\"Field '%s' and/or '%s': \");\n" |
| 1234 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1235 | " \"Conflicting negative testing attributes, POINTERTO " |
| 1236 | "attribute will be ignored\");\n" |
| 1237 | " } else {\n" |
| 1238 | " encoded_length += %d;\n" |
| 1239 | " myleaf.body.node.nodes[idx_map[%lu]]->calc = CALC_POINTER;\n" |
| 1240 | " myleaf.body.node.nodes[idx_map[%lu]]->coding_descr = &%s_descr_;\n" |
| 1241 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.unit = %d;\n" |
| 1242 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.ptr_offset = %d;\n" |
| 1243 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.ptr_base = %d;\n" |
| 1244 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.target.level = " |
| 1245 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" |
| 1246 | " myleaf.body.node.nodes[idx_map[%lu]]->calcof.pointerto.target.pos = " |
| 1247 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n" |
| 1248 | " myleaf.body.node.nodes[idx_map[%lu]]->length = %d;\n" |
| 1249 | " }\n", |
| 1250 | sdef->elements[i].name, |
| 1251 | i, sdef->elements[i].raw.pointerto, |
| 1252 | sdef->elements[i].name, (unsigned long)i, |
| 1253 | (unsigned long)sdef->elements[i].raw.pointerto, |
| 1254 | (unsigned long)sdef->elements[i].raw.pointerto - (unsigned long)i, |
| 1255 | (unsigned long)sdef->elements[i].raw.pointerto, (unsigned long)i, |
| 1256 | sdef->elements[i].name, sdef->elements[i].name, |
| 1257 | sdef->elements[sdef->elements[i].raw.pointerto].name, |
| 1258 | sdef->elements[i].raw.fieldlength, (unsigned long)i, |
| 1259 | (unsigned long)i, sdef->elements[i].typedescrname, |
| 1260 | (unsigned long)i, sdef->elements[i].raw.unit, |
| 1261 | (unsigned long)i, sdef->elements[i].raw.ptroffset, |
| 1262 | (unsigned long)i, sdef->elements[i].raw.pointerbase, |
| 1263 | (unsigned long)i, sdef->elements[i].raw.pointerto, |
| 1264 | (unsigned long)i, sdef->elements[i].raw.pointerto, |
| 1265 | (unsigned long)i, sdef->elements[i].raw.fieldlength); |
| 1266 | if (sdef->elements[sdef->elements[i].raw.pointerto].isOptional) { |
| 1267 | src = mputprintf(src, |
| 1268 | " } else {\n" |
| 1269 | " INTEGER atm;\n" |
| 1270 | " atm = 0;\n" |
| 1271 | " encoded_length += atm.RAW_encode(%s_descr_, " |
| 1272 | "*myleaf.body.node.nodes[idx_map[%lu]]);\n" |
| 1273 | " }\n", |
| 1274 | sdef->elements[i].typedescrname, (unsigned long)i); |
| 1275 | } |
| 1276 | } else { |
| 1277 | /* Encoding of normal fields with no negative testing. Needed for the |
| 1278 | later phase. */ |
| 1279 | src = mputprintf(src, |
| 1280 | " if (idx_map[%lu] >= 0) " |
| 1281 | "encoded_length += field_%s%s.RAW_encode(%s_descr_, " |
| 1282 | "*myleaf.body.node.nodes[idx_map[%lu]]);\n", |
| 1283 | (unsigned long)i, sdef->elements[i].name, |
| 1284 | sdef->elements[i].isOptional ? "()" : "", |
| 1285 | sdef->elements[i].typedescrname, (unsigned long)i); |
| 1286 | } |
| 1287 | if (sdef->elements[i].isOptional) { |
| 1288 | src = mputstr(src, |
| 1289 | " }\n"); |
| 1290 | } |
| 1291 | } |
| 1292 | for (i = 0; i < sdef->nElements; i++) { |
| 1293 | /* Fill presence, tag and crosstag. */ |
| 1294 | if (raw_options[i].lengthto && sdef->elements[i].raw.lengthindex) { |
| 1295 | /* Encoding of lenghto fields with lengthindex. */ |
| 1296 | int a; |
| 1297 | if (sdef->elements[i].isOptional) { |
| 1298 | src = mputprintf(src, |
| 1299 | " if (field_%s.ispresent()) {\n", |
| 1300 | sdef->elements[i].name); |
| 1301 | } |
| 1302 | src = mputprintf(src, |
| 1303 | " if (idx_map[%lu] < 0) {\n" |
| 1304 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1305 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1306 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " |
| 1307 | "attribute will be ignored\");\n" |
| 1308 | " } else {\n" |
| 1309 | " if (myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]) {\n" |
| 1310 | " bool negtest_confl_lengthto = false;\n", |
| 1311 | (unsigned long)i, sdef->elements[i].name, (unsigned long)i, |
| 1312 | sdef->elements[i].raw.lengthindex->nthfield); |
| 1313 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { |
| 1314 | src = mputprintf(src, |
| 1315 | " if (idx_map[%lu] < 0) {\n" |
| 1316 | " negtest_confl_lengthto = true;\n" |
| 1317 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1318 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1319 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " |
| 1320 | "attribute will be ignored\");\n" |
| 1321 | " }\n", |
| 1322 | (unsigned long)sdef->elements[i].raw.lengthto[a], |
| 1323 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); |
| 1324 | } |
| 1325 | src = mputprintf(src, |
| 1326 | " if (!negtest_confl_lengthto) {\n" |
| 1327 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" |
| 1328 | "calc = CALC_LENGTH;\n" |
| 1329 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" |
| 1330 | "coding_descr = &%s_descr_;\n" |
| 1331 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" |
| 1332 | "calcof.lengthto.num_of_fields = %d;\n" |
| 1333 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" |
| 1334 | "calcof.lengthto.unit = %d;\n" |
| 1335 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" |
| 1336 | "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", |
| 1337 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 1338 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 1339 | sdef->elements[i].raw.lengthindex->typedescr, |
| 1340 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 1341 | sdef->elements[i].raw.lengthto_num, |
| 1342 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 1343 | sdef->elements[i].raw.unit, |
| 1344 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, |
| 1345 | sdef->elements[i].raw.lengthto_num); |
| 1346 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { |
| 1347 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 1348 | src = mputprintf(src, |
| 1349 | " if (field_%s.ispresent()) {\n", |
| 1350 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); |
| 1351 | } |
| 1352 | src = mputprintf(src, |
| 1353 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]" |
| 1354 | "->calcof.lengthto.fields[%d].level = " |
| 1355 | "myleaf.body.node.nodes[idx_map[%d]]->curr_pos.level;\n" |
| 1356 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]" |
| 1357 | "->calcof.lengthto.fields[%d].pos = " |
| 1358 | "myleaf.body.node.nodes[idx_map[%d]]->curr_pos.pos;\n", |
| 1359 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a, |
| 1360 | sdef->elements[i].raw.lengthto[a], (unsigned long)i, |
| 1361 | sdef->elements[i].raw.lengthindex->nthfield, a, |
| 1362 | sdef->elements[i].raw.lengthto[a]); |
| 1363 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 1364 | src = mputprintf(src, |
| 1365 | " } else {\n" |
| 1366 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" |
| 1367 | "calcof.lengthto.fields[%d].level = 0;\n" |
| 1368 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" |
| 1369 | "calcof.lengthto.fields[%d].pos = 0;\n" |
| 1370 | " }\n", |
| 1371 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a, |
| 1372 | (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, a); |
| 1373 | } |
| 1374 | } |
| 1375 | /* Closing index check. */ |
| 1376 | src = mputstr(src, |
| 1377 | " }\n"); |
| 1378 | src = mputstr(src, " }\n }\n"); |
| 1379 | if (sdef->elements[i].isOptional) { |
| 1380 | src = mputstr(src, " }\n"); |
| 1381 | } |
| 1382 | } |
| 1383 | if (raw_options[i].lengthto && sdef->elements[i].raw.union_member_num) { |
| 1384 | /* Encoding of lenghto fields. */ |
| 1385 | int a; |
| 1386 | if (sdef->elements[i].isOptional) { |
| 1387 | src = mputprintf(src, |
| 1388 | " if (field_%s.ispresent()) ", sdef->elements[i].name); |
| 1389 | } |
| 1390 | src = mputprintf(src, |
| 1391 | " {\n" |
| 1392 | " if (idx_map[%lu] < 0) {\n" |
| 1393 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1394 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1395 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " |
| 1396 | "attribute will be ignored\");\n" |
| 1397 | " } else {\n" |
| 1398 | " bool negtest_confl_lengthto = false;\n", |
| 1399 | (unsigned long)i, sdef->elements[i].name); |
| 1400 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { |
| 1401 | src = mputprintf(src, |
| 1402 | " if (idx_map[%lu] < 0) {\n" |
| 1403 | " negtest_confl_lengthto = true;\n" |
| 1404 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1405 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1406 | " \"Conflicting negative testing attributes, LENGTHTO/LENGTHINDEX " |
| 1407 | "attribute will be ignored\");\n" |
| 1408 | " }\n", |
| 1409 | (unsigned long)sdef->elements[i].raw.lengthto[a], |
| 1410 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); |
| 1411 | } |
| 1412 | src = mputprintf(src, |
| 1413 | " if (!negtest_confl_lengthto) {\n" |
| 1414 | " int sel_field = 0;\n" |
| 1415 | " while (myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field] == NULL) " |
| 1416 | "{ sel_field++; }\n" |
| 1417 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" |
| 1418 | "calc = CALC_LENGTH;\n" |
| 1419 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" |
| 1420 | "calcof.lengthto.num_of_fields = %d;\n" |
| 1421 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" |
| 1422 | "calcof.lengthto.unit = %d;\n" |
| 1423 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" |
| 1424 | "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", |
| 1425 | (unsigned long)i, (unsigned long)i, |
| 1426 | (unsigned long)i, sdef->elements[i].raw.lengthto_num, |
| 1427 | (unsigned long)i, sdef->elements[i].raw.unit, |
| 1428 | (unsigned long)i, sdef->elements[i].raw.lengthto_num); |
| 1429 | for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { |
| 1430 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 1431 | src = mputprintf(src, |
| 1432 | " if (field_%s.ispresent()) {\n", |
| 1433 | sdef->elements[sdef->elements[i].raw.lengthto[a]].name); |
| 1434 | } |
| 1435 | src = mputprintf(src, |
| 1436 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" |
| 1437 | "->calcof.lengthto.fields[%d].level = " |
| 1438 | "myleaf.body.node.nodes[%d]->curr_pos.level;\n" |
| 1439 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" |
| 1440 | "->calcof.lengthto.fields[%d].pos = " |
| 1441 | "myleaf.body.node.nodes[%d]->curr_pos.pos;\n", |
| 1442 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a], |
| 1443 | (unsigned long)i, a, sdef->elements[i].raw.lengthto[a]); |
| 1444 | if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { |
| 1445 | src = mputprintf(src, |
| 1446 | " } else {\n" |
| 1447 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" |
| 1448 | "->calcof.lengthto.fields[%d].level = 0;\n" |
| 1449 | " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]" |
| 1450 | "->calcof.lengthto.fields[%d].pos = 0;\n" |
| 1451 | " }\n", |
| 1452 | (unsigned long)i, a, |
| 1453 | (unsigned long)i, a); |
| 1454 | } |
| 1455 | } |
| 1456 | /* Closing inner index check. */ |
| 1457 | src = mputstr(src, |
| 1458 | " }\n"); |
| 1459 | /* Closing outer index check. */ |
| 1460 | src = mputstr(src, |
| 1461 | " }\n"); |
| 1462 | /* Closing ispresent or local block. */ |
| 1463 | src = mputstr(src, |
| 1464 | " }\n"); |
| 1465 | } |
| 1466 | if (raw_options[i].tag_type && |
| 1467 | sdef->raw.taglist.list[raw_options[i].tag_type - 1].nElements) { |
| 1468 | /* Plain, old tag. */ |
| 1469 | rawAST_coding_taglist *cur_choice = |
| 1470 | sdef->raw.taglist.list + raw_options[i].tag_type - 1; |
| 1471 | src = mputprintf(src, |
| 1472 | " bool negtest_confl_tag_%s = false;\n" |
| 1473 | " if (idx_map[%lu] < 0) {\n" |
| 1474 | " negtest_confl_tag_%s = true;\n" |
| 1475 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1476 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1477 | " \"Conflicting negative testing attributes, TAG attribute will " |
| 1478 | "be ignored\");\n" |
| 1479 | " }\n", |
| 1480 | sdef->elements[i].name, (unsigned long)i, sdef->elements[i].name, |
| 1481 | sdef->elements[i].name); |
| 1482 | src = mputprintf(src, " if (!negtest_confl_tag_%s && (", |
| 1483 | sdef->elements[i].name); |
| 1484 | if (sdef->elements[i].isOptional) { |
| 1485 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); |
| 1486 | } |
| 1487 | src = genRawFieldChecker(src, cur_choice, FALSE); |
| 1488 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); |
| 1489 | src = mputstr(src,")) {\n"); |
| 1490 | src = genRawTagChecker(src, cur_choice); |
| 1491 | src = mputstr(src," }\n"); |
| 1492 | } |
| 1493 | if (sdef->elements[i].hasRaw && sdef->elements[i].raw.presence.nElements) { |
| 1494 | /* Presence attribute for fields. */ |
| 1495 | int taglist_idx, field_idx; |
| 1496 | /* The optional field itself. */ |
| 1497 | src = mputprintf(src, |
| 1498 | " bool negtest_confl_presence_%s = false;\n" |
| 1499 | " if (idx_map[%lu] < 0) {\n" |
| 1500 | " negtest_confl_presence_%s = true;\n" |
| 1501 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1502 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1503 | " \"Conflicting negative testing attributes, PRESENCE attribute " |
| 1504 | "will be ignored\");\n" |
| 1505 | " }\n", |
| 1506 | sdef->elements[i].name, (unsigned long)i, sdef->elements[i].name, |
| 1507 | sdef->elements[i].name); |
| 1508 | /* Check the referenced fields. */ |
| 1509 | for (taglist_idx = 0; |
| 1510 | taglist_idx < sdef->elements[i].raw.presence.nElements; ++taglist_idx) { |
| 1511 | rawAST_coding_field_list *fields = |
| 1512 | sdef->elements[i].raw.presence.fields + taglist_idx; |
| 1513 | for (field_idx = 0; field_idx < fields->nElements; ++field_idx) { |
| 1514 | /* The top level field is enough. >0 index is for subrefs. */ |
| 1515 | if (field_idx == 0) { |
| 1516 | rawAST_coding_fields *field = fields->fields + field_idx; |
| 1517 | src = mputprintf(src, |
| 1518 | " if (idx_map[%d] < 0) {\n" |
| 1519 | " negtest_confl_presence_%s = true;\n" |
| 1520 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1521 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1522 | " \"Conflicting negative testing attributes, PRESENCE attribute " |
| 1523 | "will be ignored\");\n" |
| 1524 | " }\n", |
| 1525 | field->nthfield, sdef->elements[i].name, field->nthfieldname); |
| 1526 | } else { |
| 1527 | /* Subrefs. */ |
| 1528 | break; |
| 1529 | } |
| 1530 | } |
| 1531 | } |
| 1532 | src = mputprintf(src, " if (!negtest_confl_presence_%s && (", |
| 1533 | sdef->elements[i].name); |
| 1534 | if (sdef->elements[i].isOptional) { |
| 1535 | src = mputprintf(src, "field_%s.ispresent() && (", sdef->elements[i].name); |
| 1536 | } |
| 1537 | src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, FALSE); |
| 1538 | if (sdef->elements[i].isOptional) src = mputstr(src, ")"); |
| 1539 | src = mputstr(src, ")) {\n"); |
| 1540 | src = genRawTagChecker(src, &sdef->elements[i].raw.presence); |
| 1541 | src = mputstr(src, " }\n"); |
| 1542 | } |
| 1543 | if (sdef->elements[i].hasRaw && |
| 1544 | sdef->elements[i].raw.crosstaglist.nElements) { |
| 1545 | /* crosstag */ |
| 1546 | int a; |
| 1547 | /* The union field itself. */ |
| 1548 | src = mputprintf(src, |
| 1549 | " if (idx_map[%lu] < 0) {\n" |
| 1550 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1551 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1552 | " \"Conflicting negative testing attributes, CROSSTAG attribute " |
| 1553 | "will be ignored\");\n" |
| 1554 | " } else {\n", |
| 1555 | (unsigned long)i, sdef->elements[i].name); |
| 1556 | if (sdef->elements[i].isOptional) { |
| 1557 | src = mputprintf(src, |
| 1558 | " if (field_%s.ispresent()) {\n", |
| 1559 | sdef->elements[i].name); |
| 1560 | } |
| 1561 | src = mputprintf(src, |
| 1562 | " switch (field_%s%s.get_selection()) {\n", |
| 1563 | sdef->elements[i].name,sdef->elements[i].isOptional ? "()" : ""); |
| 1564 | for (a = 0; a < sdef->elements[i].raw.crosstaglist.nElements; a++) { |
| 1565 | rawAST_coding_taglist *cur_choice = |
| 1566 | sdef->elements[i].raw.crosstaglist.list + a; |
| 1567 | if (cur_choice->nElements > 0) { |
| 1568 | int taglist_idx, field_idx; |
| 1569 | src = mputprintf(src, |
| 1570 | " case %s%s%s: {\n" |
| 1571 | " bool negtest_confl_crosstag = false;\n", |
| 1572 | sdef->elements[i].type, "::ALT_", |
| 1573 | cur_choice->fieldName); |
| 1574 | for (taglist_idx = 0; |
| 1575 | taglist_idx < cur_choice->nElements; ++taglist_idx) { |
| 1576 | rawAST_coding_field_list *fields = cur_choice->fields + taglist_idx; |
| 1577 | for (field_idx = 0; field_idx < fields->nElements; ++field_idx) { |
| 1578 | rawAST_coding_fields *field = fields->fields + field_idx; |
| 1579 | if (field_idx == 0) { |
| 1580 | src = mputprintf(src, |
| 1581 | " if (idx_map[%d] < 0) {\n" |
| 1582 | " negtest_confl_crosstag = true;\n" |
| 1583 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1584 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1585 | " \"Conflicting negative testing attributes, CROSSTAG attribute " |
| 1586 | "will be ignored\");\n" |
| 1587 | " }\n", |
| 1588 | field->nthfield, field->nthfieldname); |
| 1589 | } else { |
| 1590 | break; |
| 1591 | } |
| 1592 | } |
| 1593 | } |
| 1594 | src = mputstr(src, " if (!negtest_confl_crosstag && ("); |
| 1595 | src = genRawFieldChecker(src, cur_choice, FALSE); |
| 1596 | src = mputstr(src, ")) {\n"); |
| 1597 | if (!strcmp(cur_choice->fields[0].value, "OMIT_VALUE")) { |
| 1598 | if (cur_choice->fields[0].nElements != 1) |
| 1599 | NOTSUPP("omit value with multiple fields in CROSSTAG"); |
| 1600 | /* eliminating the corresponding encoded leaf, which will have |
| 1601 | the same effect as if the referred field had been omit */ |
| 1602 | src = mputprintf(src, |
| 1603 | " encoded_length -= myleaf.body.node.nodes[%d]->length;\n" |
| 1604 | " delete myleaf.body.node.nodes[%d];\n" |
| 1605 | " myleaf.body.node.nodes[%d] = NULL;\n", |
| 1606 | cur_choice->fields[0].fields[0].nthfield, |
| 1607 | cur_choice->fields[0].fields[0].nthfield, |
| 1608 | cur_choice->fields[0].fields[0].nthfield); |
| 1609 | } else { |
| 1610 | int ll; |
| 1611 | src = mputprintf(src, |
| 1612 | " RAW_enc_tr_pos pr_pos;\n" |
| 1613 | " pr_pos.level = myleaf.curr_pos.level + %d;\n" |
| 1614 | " int new_pos[] = { ", |
| 1615 | cur_choice->fields[0].nElements); |
| 1616 | for (ll = 0; ll < cur_choice->fields[0].nElements; ll++) { |
| 1617 | if (ll > 0) src = mputstr(src, ", "); |
| 1618 | src = mputprintf(src, "%d", |
| 1619 | cur_choice->fields[0].fields[ll].nthfield); |
| 1620 | } |
| 1621 | src = mputprintf(src, " };\n" |
| 1622 | " pr_pos.pos = init_new_tree_pos(myleaf.curr_pos, %d, " |
| 1623 | "new_pos);\n", |
| 1624 | cur_choice->fields[0].nElements); |
| 1625 | if (cur_choice->fields[0].value[0] == ' ') { |
| 1626 | /* the value is a string literal (the encoder can be called |
| 1627 | on that object directly */ |
| 1628 | src = mputprintf(src, |
| 1629 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" |
| 1630 | " if (temp_leaf != NULL)\n" |
| 1631 | " %s.RAW_encode(%s_descr_, *temp_leaf);\n" |
| 1632 | " else\n" |
| 1633 | " TTCN_EncDec_ErrorContext::error\n" |
| 1634 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged, " |
| 1635 | "but omitted value.\");\n", |
| 1636 | cur_choice->fields[0].value, |
| 1637 | cur_choice->fields[0].fields[ |
| 1638 | cur_choice->fields[0].nElements - 1].typedescr); |
| 1639 | } else { |
| 1640 | /* a temporary object needs to be created for encoding */ |
| 1641 | src = mputprintf(src, |
| 1642 | " %s new_val(%s);\n" |
| 1643 | " RAW_enc_tree* temp_leaf = myleaf.get_node(pr_pos);\n" |
| 1644 | " if (temp_leaf != NULL)\n" |
| 1645 | " new_val.RAW_encode(%s_descr_, *temp_leaf);\n" |
| 1646 | " else\n" |
| 1647 | " TTCN_EncDec_ErrorContext::error\n" |
| 1648 | " (TTCN_EncDec::ET_OMITTED_TAG, \"Encoding a tagged, " |
| 1649 | "but omitted value.\");\n", |
| 1650 | cur_choice->fields[0].fields[ |
| 1651 | cur_choice->fields[0].nElements - 1].type, |
| 1652 | cur_choice->fields[0].value, |
| 1653 | cur_choice->fields[0].fields[ |
| 1654 | cur_choice->fields[0].nElements - 1].typedescr); |
| 1655 | } |
| 1656 | src = mputstr(src, " free_tree_pos(pr_pos.pos);\n"); |
| 1657 | } |
| 1658 | src = mputstr(src, " }\n" |
| 1659 | " break; }\n"); |
| 1660 | } |
| 1661 | } |
| 1662 | src = mputstr(src, " default:;\n" |
| 1663 | " }\n"); |
| 1664 | if (sdef->elements[i].isOptional) src = mputstr(src, " }\n"); |
| 1665 | src = mputstr(src, " }\n"); |
| 1666 | } |
| 1667 | } |
| 1668 | src = mputprintf(src, |
| 1669 | " node_pos = 0;\n" |
| 1670 | " next_optional_idx = 0;\n" |
| 1671 | " for (int field_idx = 0; field_idx < num_fields; ++field_idx) {\n" |
| 1672 | " boolean is_optional_field = my_optional_indexes &&\n" |
| 1673 | " (my_optional_indexes[next_optional_idx] == field_idx);\n" |
| 1674 | " if ((p_err_descr->omit_before != -1) &&\n" |
| 1675 | " (field_idx < p_err_descr->omit_before)) {\n" |
| 1676 | " if (is_optional_field) ++next_optional_idx;\n" |
| 1677 | " continue;\n" |
| 1678 | " }\n" |
| 1679 | " const Erroneous_values_t *err_vals = p_err_descr->get_field_err_values(field_idx);\n" |
| 1680 | " const Erroneous_descriptor_t *emb_descr = p_err_descr->get_field_emb_descr(field_idx);\n" |
| 1681 | " if (err_vals && err_vals->before) {\n" |
| 1682 | " if (err_vals->before->errval == NULL)\n" |
| 1683 | " TTCN_error(\"internal error: erroneous before value missing\");\n" |
| 1684 | " if (err_vals->before->raw) {\n" |
| 1685 | " encoded_length += err_vals->before->errval->" |
| 1686 | "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n" |
| 1687 | " } else {\n" |
| 1688 | " if (err_vals->before->type_descr == NULL)\n" |
| 1689 | " TTCN_error(\"internal error: erroneous before typedescriptor missing\");\n" |
| 1690 | " encoded_length += err_vals->before->errval->RAW_encode(*(err_vals->before->type_descr),\n" |
| 1691 | " *myleaf.body.node.nodes[node_pos++]);\n" |
| 1692 | " }\n" |
| 1693 | " }\n" |
| 1694 | " if (err_vals && err_vals->value) {\n" |
| 1695 | " if (err_vals->value->errval) {\n" |
| 1696 | " e_c.set_msg(\"'%%s'(erroneous value): \", fld_name(field_idx));\n" |
| 1697 | " if (err_vals->value->raw) {\n" |
| 1698 | " encoded_length += err_vals->value->errval->" |
| 1699 | "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n" |
| 1700 | " } else {\n" |
| 1701 | " if (err_vals->value->type_descr == NULL)\n" |
| 1702 | " TTCN_error(\"internal error: erroneous value typedescriptor missing\");\n" |
| 1703 | " encoded_length += err_vals->value->errval->" |
| 1704 | "RAW_encode(*(err_vals->value->type_descr), *myleaf.body.node.nodes[node_pos++]);\n" |
| 1705 | " }\n" |
| 1706 | " }\n" |
| 1707 | " } else {\n" |
| 1708 | " e_c.set_msg(\"'%%s': \", fld_name(field_idx));\n" |
| 1709 | " if (!is_optional_field || get_at(field_idx)->ispresent()) {\n" |
| 1710 | " const Base_Type *curr_field = is_optional_field " |
| 1711 | "? get_at(field_idx)->get_opt_value() : get_at(field_idx);\n" |
| 1712 | " if (emb_descr) {\n" |
| 1713 | " encoded_length += curr_field\n" |
| 1714 | " ->RAW_encode_negtest(emb_descr, *fld_descr(field_idx),\n" |
| 1715 | " *myleaf.body.node.nodes[node_pos]);\n" |
| 1716 | " }\n" |
| 1717 | " } else {\n" |
| 1718 | " // `omitted' field.\n" |
| 1719 | " myleaf.body.node.nodes[node_pos] = NULL;\n" |
| 1720 | " }\n" |
| 1721 | " ++node_pos;\n" |
| 1722 | " }\n" |
| 1723 | " if (err_vals && err_vals->after) {\n" |
| 1724 | " if (err_vals->after->errval == NULL)\n" |
| 1725 | " TTCN_error(\"internal error: erroneous before value missing\");\n" |
| 1726 | " if (err_vals->after->raw) {\n" |
| 1727 | " encoded_length += err_vals->after->errval->" |
| 1728 | "RAW_encode_negtest_raw(*myleaf.body.node.nodes[node_pos++]);\n" |
| 1729 | " } else {\n" |
| 1730 | " if (err_vals->after->type_descr == NULL)\n" |
| 1731 | " TTCN_error(\"internal error: erroneous after typedescriptor missing\");\n" |
| 1732 | " encoded_length += err_vals->after->errval->" |
| 1733 | "RAW_encode(*(err_vals->after->type_descr), *myleaf.body.node.nodes[node_pos++]);\n" |
| 1734 | " }\n" |
| 1735 | " }\n" |
| 1736 | " if (is_optional_field) ++next_optional_idx;\n" |
| 1737 | " if ((p_err_descr->omit_after != -1) &&\n" |
| 1738 | " (field_idx >= p_err_descr->omit_after))\n" |
| 1739 | " break;\n" |
| 1740 | " }\n"); |
| 1741 | /* Presence for the whole record. */ |
| 1742 | if (sdef->hasRaw && sdef->raw.presence.nElements > 0) { |
| 1743 | /* Check the referenced fields. */ |
| 1744 | int taglist_idx, field_idx; |
| 1745 | src = mputstr(src, " bool negtest_confl_presence = false;\n"); |
| 1746 | for (taglist_idx = 0; taglist_idx < sdef->raw.presence.nElements; ++taglist_idx) { |
| 1747 | rawAST_coding_field_list *fields = |
| 1748 | sdef->raw.presence.fields + taglist_idx; |
| 1749 | for (field_idx = 0; field_idx < fields->nElements; ++field_idx) { |
| 1750 | if (field_idx == 0) { |
| 1751 | rawAST_coding_fields *field = fields->fields + field_idx; |
| 1752 | src = mputprintf(src, |
| 1753 | " if (idx_map[%d] < 0) {\n" |
| 1754 | " negtest_confl_presence = true;\n" |
| 1755 | " e_c.set_msg(\"Field '%s': \");\n" |
| 1756 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_NEGTEST_CONFL,\n" |
| 1757 | " \"Conflicting negative testing attributes, PRESENCE attribute " |
| 1758 | "will be ignored\");\n" |
| 1759 | " }\n", |
| 1760 | field->nthfield, field->nthfieldname); |
| 1761 | } else { |
| 1762 | break; |
| 1763 | } |
| 1764 | } |
| 1765 | } |
| 1766 | src = mputstr(src, " if (!negtest_confl_presence && ("); |
| 1767 | src = genRawFieldChecker(src, &sdef->raw.presence, FALSE); |
| 1768 | src = mputstr(src,")) {\n"); |
| 1769 | src = genRawTagChecker(src, &sdef->raw.presence); |
| 1770 | src = mputstr(src," }\n"); |
| 1771 | } |
| 1772 | src = mputstr(src, |
| 1773 | " return myleaf.length = encoded_length;\n" |
| 1774 | "}\n\n"); |
| 1775 | return src; |
| 1776 | } |
| 1777 | |
| 1778 | void gen_xer(const struct_def *sdef, char **pdef, char **psrc) |
| 1779 | { /* XERSTUFF codegen for record/SEQUENCE */ |
| 1780 | size_t i; |
| 1781 | char *def = *pdef, *src = *psrc; |
| 1782 | const char * const name = sdef->name; |
| 1783 | |
| 1784 | /* |
| 1785 | * NOTE! Decisions based on the coding instructions of the components |
| 1786 | * (e.g. number of attributes) can be made at compile time. |
| 1787 | * Decisions on coding instructions of the record itself (e.g. D-F-E, |
| 1788 | * EMBED-VALUES, USE-NIL, USE-ORDER) __must__ be postponed to run-time, |
| 1789 | * because these can be applied to type references, |
| 1790 | * which will not be visible when the code is generated. |
| 1791 | */ |
| 1792 | |
| 1793 | /* Number of fields with ATTRIBUTE, includes ANY-ATTRIBUTES */ |
| 1794 | size_t num_attributes = 0; |
| 1795 | |
| 1796 | /* index of USE-ORDER member, which may be bumped into second place by EMBED-VALUES */ |
| 1797 | size_t uo = (sdef->xerEmbedValuesPossible !=0); |
| 1798 | |
| 1799 | /* start_at is the index of the first "real" member of the record */ |
| 1800 | size_t start_at = uo + (sdef->xerUseOrderPossible != 0); |
| 1801 | |
| 1802 | /* Number of optional non-attributes */ |
| 1803 | size_t n_opt_elements = 0; |
| 1804 | |
| 1805 | const boolean want_namespaces = !sdef->isASN1 /* TODO remove this when ASN.1 gets EXER */; |
| 1806 | |
| 1807 | int aa_index = -1; |
| 1808 | /* Find the number of attributes (compile time) */ |
| 1809 | for (i = 0; i < sdef->nElements; ++i) { |
| 1810 | if (sdef->elements[i].xerAttribute) { |
| 1811 | ++num_attributes; |
| 1812 | } |
| 1813 | else if (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT) { |
| 1814 | ++num_attributes; /* ANY-ATTRIBUTES also included with attributes */ |
| 1815 | aa_index = i; |
| 1816 | /* If the first member is ANY-ATTRIBUTES, then xerEmbedValuesPossible |
| 1817 | * is merely an illusion and USE-ORDER is not possible. */ |
| 1818 | if (i==0) { |
| 1819 | start_at = uo = 0; |
| 1820 | } |
| 1821 | } |
| 1822 | else /* not attribute */ if (sdef->elements[i].isOptional) { |
| 1823 | ++n_opt_elements; |
| 1824 | } |
| 1825 | } |
| 1826 | |
| 1827 | /* Write some helper functions */ |
| 1828 | def = mputstr(def, |
| 1829 | "char **collect_ns(const XERdescriptor_t& p_td, size_t& num_ns, bool& def_ns) const;\n"); |
| 1830 | |
| 1831 | src = mputprintf(src, |
| 1832 | "char ** %s::collect_ns(const XERdescriptor_t& p_td, size_t& num_ns, bool& def_ns) const {\n" |
| 1833 | " size_t num_collected;\n" |
| 1834 | " char **collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n" |
| 1835 | /* The above might throw but then nothing was allocated. */ |
| 1836 | , name); |
| 1837 | |
| 1838 | /* Collect namespaces from the "non-special" members (incl. attributes) */ |
| 1839 | if (start_at < sdef->nElements) src = mputstr(src, |
| 1840 | " try {\n" |
| 1841 | " char **new_ns;\n" |
| 1842 | " size_t num_new;\n" |
| 1843 | " bool def_ns_1 = false;\n"); |
| 1844 | for (i = start_at; i < sdef->nElements; ++i) { |
| 1845 | src = mputprintf(src, |
| 1846 | " new_ns = field_%s.collect_ns(%s_xer_, num_new, def_ns);\n" |
| 1847 | " merge_ns(collected_ns, num_collected, new_ns, num_new);\n" |
| 1848 | " def_ns = def_ns || def_ns_1;\n" /* alas, no ||= */ |
| 1849 | , sdef->elements[i].name, sdef->elements[i].typegen |
| 1850 | ); |
| 1851 | } |
| 1852 | if (sdef->xerUseNilPossible) { |
| 1853 | src = mputprintf(src, |
| 1854 | " if((p_td.xer_bits & USE_NIL) && !field_%s.ispresent()) {\n" /* "nil" attribute to be written*/ |
| 1855 | " collected_ns = (char**)Realloc(collected_ns, sizeof(char*) * ++num_collected);\n" |
| 1856 | " const namespace_t *c_ns = p_td.my_module->get_controlns();\n" |
| 1857 | " collected_ns[num_collected-1] = mprintf(\" xmlns:%%s='%%s'\", c_ns->px, c_ns->ns);\n" |
| 1858 | " }\n" |
| 1859 | , sdef->elements[sdef->nElements-1].name |
| 1860 | ); |
| 1861 | } |
| 1862 | if (start_at < sdef->nElements) src = mputstr(src, |
| 1863 | " }\n" |
| 1864 | " catch (...) {\n" |
| 1865 | /* Probably a TC_Error thrown from field_%s->collect_ns() if e.g. |
| 1866 | * encoding an unbound value. */ |
| 1867 | " while (num_collected > 0) Free(collected_ns[--num_collected]);\n" |
| 1868 | " Free(collected_ns);\n" |
| 1869 | " throw;\n" |
| 1870 | " }\n" |
| 1871 | ); |
| 1872 | |
| 1873 | src = mputstr(src, |
| 1874 | " num_ns = num_collected;\n" |
| 1875 | " return collected_ns;\n" |
| 1876 | "}\n\n" |
| 1877 | ); |
| 1878 | |
| 1879 | src = mputprintf(src, |
| 1880 | "boolean %s::can_start(const char *name, const char *uri, const XERdescriptor_t& xd, unsigned int flavor) {\n" |
| 1881 | " boolean e_xer = is_exer(flavor &= ~XER_RECOF);\n" |
| 1882 | " if (!e_xer || !((xd.xer_bits & UNTAGGED) || (flavor & (USE_NIL|XER_RECOF)))) return check_name(name, xd, e_xer) && (!e_xer || check_namespace(uri, xd));\n" |
| 1883 | , name |
| 1884 | ); |
| 1885 | for (i = start_at; i < sdef->nElements; ++i) { |
| 1886 | src = mputprintf(src, |
| 1887 | " else if (%s::can_start(name, uri, %s_xer_, flavor)) return true;\n" |
| 1888 | /* Here we know for sure it's exer */ |
| 1889 | , sdef->elements[i].type |
| 1890 | , sdef->elements[i].typegen |
| 1891 | ); |
| 1892 | if (!sdef->elements[i].isOptional) break; |
| 1893 | /* The last component with which it can begin is the first non-optional. |
| 1894 | * Does that sentence makes sense to you ? */ |
| 1895 | } |
| 1896 | src = mputstr(src, " return false;\n}\n\n"); |
| 1897 | |
| 1898 | /* * * * * * * * * * XER_encode * * * * * * * * * * * * * * */ |
| 1899 | src = mputprintf(src, |
| 1900 | "int %s::XER_encode(const XERdescriptor_t& p_td, " |
| 1901 | "TTCN_Buffer& p_buf, unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n" |
| 1902 | "{\n" |
| 1903 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" |
| 1904 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" |
| 1905 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" |
| 1906 | " TTCN_EncDec_ErrorContext ec_1;\n" |
| 1907 | " int encoded_length=(int)p_buf.get_len();\n" |
| 1908 | " int e_xer = is_exer(p_flavor);\n" |
| 1909 | " const boolean omit_tag = e_xer && p_indent " |
| 1910 | "&& ((p_td.xer_bits & (UNTAGGED|XER_ATTRIBUTE)) || (p_flavor & (USE_NIL|USE_TYPE_ATTR)));\n" |
| 1911 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) p_flavor |= XER_CANONICAL;\n" |
| 1912 | " int is_indented = !is_canonical(p_flavor);\n" |
| 1913 | , name); |
| 1914 | |
| 1915 | if (want_namespaces && !(num_attributes|sdef->xerUseQName)) src = mputstr(src, |
| 1916 | " const boolean need_control_ns = (p_td.xer_bits & (USE_NIL));\n"); |
| 1917 | |
| 1918 | if (start_at < sdef->nElements) { /* there _are_ non-special members */ |
| 1919 | src = mputstr(src, |
| 1920 | " size_t num_collected = 0;\n" |
| 1921 | " char **collected_ns = NULL;\n" |
| 1922 | " bool def_ns = false;\n" |
| 1923 | " if (e_xer) {\n" |
| 1924 | " if (p_indent == 0) {\n" /* top-level */ |
| 1925 | " collected_ns = collect_ns(p_td, num_collected, def_ns);\n" /* our own ns */ |
| 1926 | " }\n" |
| 1927 | " else if ((p_flavor & DEF_NS_SQUASHED) && p_td.my_module && p_td.ns_index != -1){\n" |
| 1928 | " const namespace_t * ns = p_td.my_module->get_ns(p_td.ns_index);\n" |
| 1929 | " if (*ns->px == '\\0') {\n" |
| 1930 | " collected_ns = Base_Type::collect_ns(p_td, num_collected, def_ns);\n" |
| 1931 | " }\n" |
| 1932 | " }\n" |
| 1933 | " }\n" |
| 1934 | ); |
| 1935 | } |
| 1936 | |
| 1937 | if (want_namespaces) { |
| 1938 | src = mputstr(src, |
| 1939 | " const boolean empty_ns_hack = e_xer && !omit_tag && (p_indent > 0)\n" |
| 1940 | " && (p_td.xer_bits & FORM_UNQUALIFIED)\n" |
| 1941 | " && p_td.my_module && p_td.ns_index != -1\n" |
| 1942 | " && *p_td.my_module->get_ns(p_td.ns_index)->px == '\\0';\n" |
| 1943 | ); |
| 1944 | |
| 1945 | src = mputstr(src, " boolean delay_close = e_xer"); |
| 1946 | if (!(num_attributes | sdef->xerUseQName)) { |
| 1947 | src = mputprintf(src, " && (need_control_ns%s || empty_ns_hack)", |
| 1948 | (start_at < sdef->nElements) ? " || num_collected" : ""); |
| 1949 | } |
| 1950 | src = mputstr(src, ";\n"); |
| 1951 | } |
| 1952 | |
| 1953 | |
| 1954 | { /* write start tag */ |
| 1955 | /* From "name>\n": |
| 1956 | * lose the \n if : not indenting or (single untagged(*) or attributes (*)) AND e_xer |
| 1957 | * lose the > if attributes are present (*) AND e_xer |
| 1958 | */ |
| 1959 | src = mputprintf(src, |
| 1960 | " size_t chopped_chars = 0;\n" |
| 1961 | " if (!omit_tag) {\n" |
| 1962 | " if (is_indented) do_indent(p_buf, p_indent);\n" |
| 1963 | " p_buf.put_c('<');\n" |
| 1964 | " if (e_xer) write_ns_prefix(p_td, p_buf);\n" |
| 1965 | " p_buf.put_s((size_t)p_td.namelens[e_xer]%s-(!is_indented%s), " |
| 1966 | "(cbyte*)p_td.names[e_xer]);\n" |
| 1967 | " }\n" |
| 1968 | " else if (p_flavor & USE_TYPE_ATTR) {\n" |
| 1969 | " size_t buf_len = p_buf.get_len();\n" |
| 1970 | " const unsigned char * const buf_data = p_buf.get_data();\n" |
| 1971 | " if (buf_data[buf_len-1-chopped_chars] == '\\n') ++chopped_chars;\n" |
| 1972 | " if (buf_data[buf_len-1-chopped_chars] == '>' ) ++chopped_chars;\n" |
| 1973 | " if (chopped_chars) {\n" |
| 1974 | " p_buf.increase_length(-chopped_chars);\n" |
| 1975 | " }\n" |
| 1976 | "%s" |
| 1977 | " }\n" |
| 1978 | , (want_namespaces ? "-(delay_close || (e_xer && (p_td.xer_bits & HAS_1UNTAGGED)))" : "") |
| 1979 | , (want_namespaces ? " || delay_close" : "") |
| 1980 | , (want_namespaces ? " delay_close = TRUE;\n" : "")); |
| 1981 | } |
| 1982 | |
| 1983 | src = mputprintf(src, |
| 1984 | " int sub_len=0%s;\n" |
| 1985 | " p_flavor &= XER_MASK;\n", |
| 1986 | num_attributes ? ", tmp_len; (void)tmp_len" : ""); |
| 1987 | |
| 1988 | if (sdef->xerUseQName) { |
| 1989 | src = mputprintf(src, |
| 1990 | " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n" |
| 1991 | " if (field_%s.is_value()) {\n" |
| 1992 | " p_buf.put_s(11, (cbyte*)\" xmlns:b0='\");\n" |
| 1993 | " field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1, 0);\n" |
| 1994 | " p_buf.put_c('\\'');\n" |
| 1995 | " }\n" |
| 1996 | " if (p_td.xer_bits & XER_ATTRIBUTE) begin_attribute(p_td, p_buf);\n" |
| 1997 | " else p_buf.put_c('>');\n" |
| 1998 | " if (field_%s.is_value()) {\n" |
| 1999 | " p_buf.put_s(3, (cbyte*)\"b0:\");\n" |
| 2000 | " sub_len += 3;\n" |
| 2001 | " }\n" |
| 2002 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor | XER_LIST, p_indent+1, 0);\n" |
| 2003 | " if (p_td.xer_bits & XER_ATTRIBUTE) p_buf.put_c('\\'');\n" |
| 2004 | " } else" /* no newline */ |
| 2005 | , sdef->elements[0].name |
| 2006 | , sdef->elements[0].name, sdef->elements[0].typegen |
| 2007 | , sdef->elements[0].name |
| 2008 | , sdef->elements[1].name, sdef->elements[1].typegen |
| 2009 | ); |
| 2010 | } |
| 2011 | src = mputstr(src, " { // !QN\n"); |
| 2012 | |
| 2013 | /* First, the EMBED-VALUES member as an ordinary member if not doing EXER */ |
| 2014 | if (sdef->xerEmbedValuesPossible) { |
| 2015 | src = mputprintf(src, |
| 2016 | " if (!e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" |
| 2017 | " ec_1.set_msg(\"%s': \");\n" |
| 2018 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
| 2019 | " }\n" |
| 2020 | , sdef->elements[0].dispname |
| 2021 | , sdef->elements[0].name, sdef->elements[0].typegen |
| 2022 | ); |
| 2023 | } |
| 2024 | /* Then, the USE-ORDER member as an ordinary member when !EXER */ |
| 2025 | if (sdef->xerUseOrderPossible) { |
| 2026 | src = mputprintf(src, |
| 2027 | " if (!e_xer && (p_td.xer_bits & USE_ORDER)) {\n" |
| 2028 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
| 2029 | " }\n" |
| 2030 | , sdef->elements[uo].name, sdef->elements[uo].typegen |
| 2031 | ); |
| 2032 | } |
| 2033 | |
| 2034 | if (start_at+num_attributes > sdef->nElements) FATAL_ERROR("defRecordClass1"); |
| 2035 | |
| 2036 | if (want_namespaces && (start_at < sdef->nElements)) { |
| 2037 | src = mputstr(src, |
| 2038 | " if (e_xer && num_collected) {\n" |
| 2039 | " size_t num_ns;\n" |
| 2040 | " for (num_ns = 0; num_ns < num_collected; ++num_ns) {\n" |
| 2041 | " p_buf.put_s(strlen(collected_ns[num_ns]), (cbyte*)collected_ns[num_ns]);\n" |
| 2042 | " Free(collected_ns[num_ns]);\n" |
| 2043 | " }\n" |
| 2044 | " Free(collected_ns);\n" |
| 2045 | " }\n\n" |
| 2046 | " if (def_ns) {\n" |
| 2047 | " p_flavor &= ~DEF_NS_SQUASHED;\n" |
| 2048 | " p_flavor |= DEF_NS_PRESENT;\n" |
| 2049 | " }\n" |
| 2050 | " else if (empty_ns_hack) {\n" |
| 2051 | " p_buf.put_s(9, (cbyte*)\" xmlns=''\");\n" |
| 2052 | " p_flavor &= ~DEF_NS_PRESENT;\n" |
| 2053 | " p_flavor |= DEF_NS_SQUASHED;\n" |
| 2054 | " }\n"); |
| 2055 | } |
| 2056 | |
| 2057 | /* Then, all the attributes (not added to sub_len) */ |
| 2058 | for ( i = start_at; i < start_at + num_attributes; ++i ) { |
| 2059 | /* If the first component is a record-of with ANY-ATTRIBUTES, |
| 2060 | * it has been taken care of because it looked like an EMBED-VALUES */ |
| 2061 | if (i==0 && sdef->xerEmbedValuesPossible && (sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) continue ; |
| 2062 | src = mputprintf(src, |
| 2063 | " ec_1.set_msg(\"%s': \");\n" |
| 2064 | " tmp_len = field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
| 2065 | " %ssub_len += tmp_len;\n" /* do not add if attribute and EXER */ |
| 2066 | , sdef->elements[i].dispname |
| 2067 | , sdef->elements[i].name, sdef->elements[i].typegen |
| 2068 | , sdef->elements[i].xerAttribute ? "if (!e_xer) " : "" |
| 2069 | ); |
| 2070 | } |
| 2071 | |
| 2072 | if (sdef->xerUseNilPossible) { |
| 2073 | src = mputprintf(src, |
| 2074 | " bool nil_attribute = e_xer && (p_td.xer_bits & USE_NIL) && !field_%s.ispresent();\n" |
| 2075 | " if (nil_attribute) {\n" |
| 2076 | " const namespace_t *control_ns = p_td.my_module->get_controlns();\n" |
| 2077 | " p_buf.put_c(' ');\n" |
| 2078 | " p_buf.put_s(strlen(control_ns->px), (cbyte*)control_ns->px);\n" |
| 2079 | " p_buf.put_c(':');\n" |
| 2080 | " p_buf.put_s(10, (cbyte*)\"nil='true'\");\n" |
| 2081 | " }\n" |
| 2082 | , sdef->elements[sdef->nElements-1].name |
| 2083 | ); |
| 2084 | } |
| 2085 | |
| 2086 | if (want_namespaces) { |
| 2087 | /* there were some attributes. close the start tag left open */ |
| 2088 | src = mputprintf(src, |
| 2089 | " if (delay_close && (!omit_tag || chopped_chars)) p_buf.put_s(1%s, (cbyte*)\">\\n\");\n", /* close the start tag */ |
| 2090 | (sdef->xerUntaggedOne /*|| sdef->xerUseNil*/) ? "" : "+is_indented" |
| 2091 | ); |
| 2092 | } |
| 2093 | |
| 2094 | if (sdef->xerEmbedValuesPossible) { |
| 2095 | src = mputprintf(src, |
| 2096 | " ec_1.set_msg(\"%s': \");\n" |
| 2097 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" |
| 2098 | /* write the first string (must come AFTER the attributes) */ |
| 2099 | " if (field_%s.size_of() > 0) {\n" |
| 2100 | " sub_len += field_%s[0].XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" |
| 2101 | " }\n" |
| 2102 | " }\n" |
| 2103 | , sdef->elements[0].dispname, sdef->elements[0].name, sdef->elements[0].name); |
| 2104 | if (want_namespaces) { /* here's another chance */ |
| 2105 | src = mputprintf(src, |
| 2106 | " else if ( !(p_td.xer_bits & EMBED_VALUES)) {\n" |
| 2107 | " %sfield_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+1, 0);\n" |
| 2108 | " }\n" |
| 2109 | , ((sdef->elements[0].xerAnyKind & ANY_ATTRIB_BIT) ? "" : "sub_len += " ) |
| 2110 | , sdef->elements[0].name, sdef->elements[0].typegen |
| 2111 | ); |
| 2112 | } |
| 2113 | } |
| 2114 | |
| 2115 | /* Then, all the non-attributes. Structuring the code like this depends on |
| 2116 | * all attributes appearing before all non-attributes (excluding |
| 2117 | * special members for EMBED-VALUES, USE-ORDER, etc.) */ |
| 2118 | if (sdef->xerEmbedValuesPossible) { |
| 2119 | src = mputprintf(src, |
| 2120 | " embed_values_enc_struct_t* emb_val = 0;\n" |
| 2121 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && field_%s.size_of() > 1) {\n" |
| 2122 | " emb_val = new embed_values_enc_struct_t;\n" |
| 2123 | /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated |
| 2124 | * record of universal charstring, so it needs a cast to avoid a compilation error */ |
| 2125 | " emb_val->embval_array%s = (const PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s;\n" |
| 2126 | " emb_val->embval_array%s = NULL;\n" |
| 2127 | " emb_val->embval_index = 1;\n" |
| 2128 | " }\n" |
| 2129 | , sdef->elements[0].name |
| 2130 | , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg" |
| 2131 | , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : "" |
| 2132 | , sdef->elements[0].name |
| 2133 | , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt"); |
| 2134 | } |
| 2135 | |
| 2136 | if (sdef->xerUseOrderPossible) { |
| 2137 | int max_ordered = sdef->nElements - start_at - num_attributes; |
| 2138 | int min_ordered = max_ordered - n_opt_elements; |
| 2139 | size_t offset = 0; |
| 2140 | size_t base = i; |
| 2141 | size_t limit = sdef->nElements; |
| 2142 | /* base and limit are indexes into sdef->elements[] */ |
| 2143 | src = mputprintf(src, |
| 2144 | " int dis_order = e_xer && (p_td.xer_bits & USE_ORDER);\n" |
| 2145 | " int to_send = field_%s.lengthof();\n" |
| 2146 | " int uo_limit = dis_order ? to_send : %lu;\n" |
| 2147 | , sdef->elements[start_at-1].name |
| 2148 | , (unsigned long)(limit - base) |
| 2149 | ); |
| 2150 | if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */ |
| 2151 | base = sdef->nElements; |
| 2152 | limit = sdef->totalElements; |
| 2153 | min_ordered = max_ordered = limit - base; |
| 2154 | src = mputprintf(src, |
| 2155 | " if (!nil_attribute) {\n" |
| 2156 | "%s" |
| 2157 | " if (!e_xer) sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, 0);\n" |
| 2158 | " else" /* no newline */ |
| 2159 | , (sdef->xerUseNilPossible ? " if (!(p_td.xer_bits & USE_ORDER)) p_flavor |= (p_td.xer_bits & USE_NIL);\n" : "") |
| 2160 | /* If USE-ORDER is on, the tag-removing effect of USE-NIL has been |
| 2161 | * performed by calling the sub-fields directly. */ |
| 2162 | , sdef->elements[sdef->nElements-1].name |
| 2163 | , sdef->elements[sdef->nElements-1].typegen |
| 2164 | ); |
| 2165 | } |
| 2166 | |
| 2167 | /* check incorrect data */ |
| 2168 | src = mputprintf(src, |
| 2169 | " {\n" |
| 2170 | " if (to_send < %d || to_send > %d) {\n" |
| 2171 | " ec_1.set_msg(\"%s': \");\n" |
| 2172 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, " |
| 2173 | "\"Wrong number of USE-ORDER, %%d instead of %d..%d\", to_send);\n" |
| 2174 | " uo_limit = -1;\n" /* squash the loop */ |
| 2175 | " }\n" |
| 2176 | " else {\n" /* check duplicates */ |
| 2177 | " int *seen = new int [to_send];\n" |
| 2178 | " int num_seen = 0;\n" |
| 2179 | " for (int ei = 0; ei < to_send; ++ei) {\n" |
| 2180 | " int val = field_%s[ei];\n" |
| 2181 | " for (int x = 0; x < num_seen; ++x) {\n" |
| 2182 | " if (val == seen[x]) { // complain\n" |
| 2183 | " ec_1.set_msg(\"%s': \");\n" |
| 2184 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n" |
| 2185 | " \"Duplicate value for USE-ORDER\");\n" |
| 2186 | " uo_limit = -1; // don't bother sending anything\n" |
| 2187 | " goto trouble;\n" |
| 2188 | " }\n" |
| 2189 | " }\n" |
| 2190 | " seen[num_seen++] = val;\n" |
| 2191 | " }\n" |
| 2192 | "trouble:\n" |
| 2193 | " delete [] seen;" |
| 2194 | " }\n" |
| 2195 | " " |
| 2196 | , min_ordered, max_ordered |
| 2197 | , sdef->elements[start_at-1].dispname |
| 2198 | , min_ordered, max_ordered |
| 2199 | , sdef->elements[start_at-1].name |
| 2200 | , sdef->elements[start_at-1].dispname |
| 2201 | ); |
| 2202 | |
| 2203 | src = mputprintf(src, |
| 2204 | " for (int i = 0; i < uo_limit; ++i) {\n" |
| 2205 | " switch (dis_order ? (int)field_%s[i] : i) {\n" |
| 2206 | , sdef->elements[start_at-1].name |
| 2207 | ); |
| 2208 | for ( i = base; i < limit; ++i ) { |
| 2209 | src = mputprintf(src, |
| 2210 | " case %lu:\n" |
| 2211 | " ec_1.set_msg(\"%s': \");\n" |
| 2212 | " sub_len += field_%s%s%s%s.XER_encode(%s_xer_, p_buf, p_flavor, p_indent+!omit_tag, %s);\n" |
| 2213 | |
| 2214 | , (unsigned long)offset++ |
| 2215 | , sdef->elements[i].dispname |
| 2216 | , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name : sdef->elements[i].name) |
| 2217 | , (sdef->xerUseNilPossible ? "()." : "") |
| 2218 | , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") |
| 2219 | , (sdef->xerUseNilPossible ? "()" : "") |
| 2220 | , sdef->elements[i].typegen |
| 2221 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0" |
| 2222 | ); |
| 2223 | |
| 2224 | src = mputstr(src, " break;\n"); |
| 2225 | } /* next element */ |
| 2226 | src = mputstr(src, |
| 2227 | " default:\n" |
| 2228 | " TTCN_error(\"Runaway value while encoding USE-ORDER\");\n" |
| 2229 | " break;\n" /* cannot happen, complain */ |
| 2230 | " }\n"); |
| 2231 | |
| 2232 | if (sdef->xerEmbedValuesPossible) { |
| 2233 | src = mputprintf(src, |
| 2234 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n" |
| 2235 | " emb_val->embval_index < field_%s.size_of()) { // embed-val\n" |
| 2236 | " field_%s[emb_val->embval_index].XER_encode(\n" |
| 2237 | " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" |
| 2238 | " ++emb_val->embval_index;\n" |
| 2239 | " }\n" |
| 2240 | , sdef->elements[0].name, sdef->elements[0].name); |
| 2241 | } |
| 2242 | |
| 2243 | |
| 2244 | src = mputstr(src, |
| 2245 | " }\n" /* end of loop */ |
| 2246 | " } // exer\n"); |
| 2247 | if (sdef->xerUseNilPossible) { |
| 2248 | src = mputstr(src, " } // nil_attr\n"); |
| 2249 | } |
| 2250 | } |
| 2251 | else /* not USE-ORDER */ |
| 2252 | for ( /* continue with i */; i < sdef->nElements; ++i ) { |
| 2253 | src = mputprintf(src, |
| 2254 | " ec_1.set_msg(\"%s': \");\n" |
| 2255 | , sdef->elements[i].dispname |
| 2256 | ); |
| 2257 | src = mputprintf(src, |
| 2258 | " sub_len += field_%s.XER_encode(%s_xer_, p_buf, p_flavor%s, p_indent+!omit_tag, %s);\n" |
| 2259 | , sdef->elements[i].name, sdef->elements[i].typegen |
| 2260 | , sdef->xerUseNilPossible ? "| (p_td.xer_bits & USE_NIL)" : "" |
| 2261 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0" |
| 2262 | ); |
| 2263 | |
| 2264 | if (sdef->xerEmbedValuesPossible) { |
| 2265 | src = mputprintf(src, |
| 2266 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&\n" |
| 2267 | " emb_val->embval_index < field_%s.size_of()) {\n" |
| 2268 | " field_%s[emb_val->embval_index].XER_encode(\n" |
| 2269 | " UNIVERSAL_CHARSTRING_xer_, p_buf, p_flavor | EMBED_VALUES, p_indent+1, 0);\n" |
| 2270 | " ++emb_val->embval_index;\n" |
| 2271 | " }\n" |
| 2272 | , sdef->elements[0].name, sdef->elements[0].name); |
| 2273 | } |
| 2274 | } /* next field when not USE-ORDER */ |
| 2275 | |
| 2276 | if (sdef->xerEmbedValuesPossible) { |
| 2277 | src = mputprintf(src, |
| 2278 | " if (0 != emb_val) {\n" |
| 2279 | " if (emb_val->embval_index < field_%s.size_of()) {\n" |
| 2280 | " ec_1.set_msg(\"%s': \");\n" |
| 2281 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,\n" |
| 2282 | " \"Too many EMBED-VALUEs specified: %%d (expected %%d or less)\",\n" |
| 2283 | " field_%s.size_of(), emb_val->embval_index);\n" |
| 2284 | " }\n" |
| 2285 | " delete emb_val;\n" |
| 2286 | " }\n" |
| 2287 | , sdef->elements[0].name, sdef->elements[0].name, sdef->elements[0].name); |
| 2288 | } |
| 2289 | |
| 2290 | src = mputstr(src, " } // QN?\n"); |
| 2291 | |
| 2292 | { |
| 2293 | src = mputprintf(src, |
| 2294 | " if (!omit_tag) {\n" |
| 2295 | " if (sub_len) {\n" /* something was written, now an end tag */ |
| 2296 | " if (is_indented && !(e_xer && (p_td.xer_bits & (HAS_1UNTAGGED | USE_QNAME)))) {\n" |
| 2297 | " switch ((int)(e_xer && (p_td.xer_bits & USE_NIL))) {\n" |
| 2298 | " case 1: {\n" |
| 2299 | " const unsigned char *buf_end = p_buf.get_data() + (p_buf.get_len()-1);\n" |
| 2300 | " if (buf_end[-1] != '>' || *buf_end != '\\n') break;\n" |
| 2301 | /* else fall through */ |
| 2302 | " }\n" |
| 2303 | " case 0:\n" |
| 2304 | " do_indent(p_buf, p_indent);\n" |
| 2305 | " break;\n" |
| 2306 | " }\n" |
| 2307 | " }\n" |
| 2308 | " p_buf.put_c('<');\n" |
| 2309 | " p_buf.put_c('/');\n" |
| 2310 | " if (e_xer) write_ns_prefix(p_td, p_buf);\n" |
| 2311 | " p_buf.put_s((size_t)p_td.namelens[e_xer]-!is_indented, (cbyte*)p_td.names[e_xer]);\n" |
| 2312 | " } else {\n" /* need to generate an empty element tag */ |
| 2313 | " p_buf.increase_length(%s-1);\n" /* decrease length */ |
| 2314 | " p_buf.put_s((size_t)2+is_indented, (cbyte*)\"/>\\n\");\n" |
| 2315 | " }}\n" |
| 2316 | , (sdef->xerUntaggedOne /*|| sdef->xerUseNil*/) ? "" : "-is_indented" |
| 2317 | ); |
| 2318 | } |
| 2319 | src = mputstr(src, |
| 2320 | " return (int)p_buf.get_len() - encoded_length;\n" |
| 2321 | "}\n\n"); |
| 2322 | |
| 2323 | #ifndef NDEBUG |
| 2324 | src = mputprintf(src, "// %s has%s%s%s%s%s%s%s%s%s\n" |
| 2325 | "// written by %s in " __FILE__ " at %d\n" |
| 2326 | , name |
| 2327 | , (sdef->xerUntagged ? " UNTAGGED" : "") |
| 2328 | , (sdef->xerUntaggedOne ? "1" : "") |
| 2329 | , (sdef->xerUseNilPossible ? " USE_NIL?" : "") |
| 2330 | , (sdef->xerUseOrderPossible ? " USE_ORDER?" : "") |
| 2331 | , (sdef->xerUseQName ? " USE_QNAME" : "") |
| 2332 | , (sdef->xerUseTypeAttr ? " USE_TYPE_ATTR" : "") |
| 2333 | , (sdef->xerUseUnion ? " USE-UNION" : "") |
| 2334 | , (sdef->xerHasNamespaces ? " namespace" : "") |
| 2335 | , (sdef->xerEmbedValuesPossible ? " EMBED?" : "") |
| 2336 | , __FUNCTION__, __LINE__ |
| 2337 | ); |
| 2338 | #endif |
| 2339 | |
| 2340 | src = mputprintf(src, /* XERSTUFF decodegen for record/SEQUENCE*/ |
| 2341 | "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader," |
| 2342 | " unsigned int p_flavor, embed_values_dec_struct_t*)\n" |
| 2343 | "{\n" |
| 2344 | " bound_flag = TRUE;\n" |
| 2345 | /* Remove XER_LIST, XER_RECOF from p_flavor. This is not required |
| 2346 | * for is_exer (which tests another bit), but for subsequent code. */ |
| 2347 | " int e_xer = is_exer(p_flavor);\n" |
| 2348 | " int xerbits = p_td.xer_bits;\n" |
| 2349 | " if (p_flavor & XER_TOPLEVEL) xerbits &= ~UNTAGGED;\n" |
| 2350 | " const boolean omit_tag = e_xer && ((xerbits & (UNTAGGED|XER_ATTRIBUTE)) " |
| 2351 | "|| (p_flavor & (USE_NIL|USE_TYPE_ATTR)));\n" |
| 2352 | "%s" |
| 2353 | " const boolean parent_tag = e_xer && (p_flavor & (USE_TYPE_ATTR));\n" |
| 2354 | " (void)parent_tag;\n" |
| 2355 | " p_flavor &= XER_MASK;\n" /* also removes "toplevel" bit */ |
| 2356 | " int rd_ok, xml_depth=-1, type;\n" |
| 2357 | " {\n" /* scope for the error contexts */ |
| 2358 | , name |
| 2359 | , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0) |
| 2360 | ? " boolean tag_closed = (p_flavor & PARENT_CLOSED) != 0;\n" : "") |
| 2361 | /* tag_closed needed for non-attribute normal members only, |
| 2362 | * or if EMBED-VALUES is possible, but isn't. */ |
| 2363 | ); |
| 2364 | |
| 2365 | if (sdef->xerUseNilPossible) src = mputstr(src, |
| 2366 | " boolean nil_attribute = FALSE;\n"); |
| 2367 | |
| 2368 | src = mputprintf(src, |
| 2369 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" |
| 2370 | " TTCN_EncDec_ErrorContext ec_1;\n" |
| 2371 | " if (!omit_tag) for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" |
| 2372 | " type = p_reader.NodeType();\n" |
| 2373 | " if (type==XML_READER_TYPE_ELEMENT) {\n" |
| 2374 | " verify_name(p_reader, p_td, e_xer);\n" |
| 2375 | " xml_depth = p_reader.Depth();\n" |
| 2376 | "%s" |
| 2377 | " break;\n" |
| 2378 | " }\n" |
| 2379 | " }\n" |
| 2380 | , (start_at + num_attributes < sdef->nElements || (sdef->xerEmbedValuesPossible && num_attributes==0) |
| 2381 | ? " tag_closed = p_reader.IsEmptyElement();\n": "") |
| 2382 | ); |
| 2383 | |
| 2384 | |
| 2385 | if (sdef->xerUseQName) { |
| 2386 | src = mputprintf(src, |
| 2387 | " if (e_xer && (p_td.xer_bits & USE_QNAME)) {\n" |
| 2388 | " if (p_td.xer_bits & XER_ATTRIBUTE) rd_ok = 1;\n" |
| 2389 | " else for (rd_ok = p_reader.Read(); rd_ok == 1; rd_ok = p_reader.Read()) {\n" |
| 2390 | " type = p_reader.NodeType();\n" |
| 2391 | " if (type == XML_READER_TYPE_TEXT) break;\n" |
| 2392 | " }\n" |
| 2393 | " if (rd_ok==1) {\n" |
| 2394 | " xmlChar *new_val = p_reader.NewValue();\n" |
| 2395 | " xmlChar *v_npfx = (xmlChar*)strchr((char*)new_val, ':');\n" |
| 2396 | " xmlChar *v_pfx;\n" |
| 2397 | " if (v_npfx != NULL) {\n" |
| 2398 | " *v_npfx++ = '\\0';\n" |
| 2399 | " v_pfx = new_val;\n" |
| 2400 | " }\n" |
| 2401 | " else {\n" |
| 2402 | " v_npfx = new_val;\n" |
| 2403 | " v_pfx = NULL;\n" |
| 2404 | " }\n" |
| 2405 | " xmlChar *q_ns = p_reader.LookupNamespace(v_pfx);\n" |
| 2406 | " if (q_ns) field_%s = (const char*)q_ns;\n" |
| 2407 | " else field_%s = OMIT_VALUE;\n" |
| 2408 | " field_%s = (const char*)v_npfx;\n" |
| 2409 | " xmlFree(q_ns);\n" |
| 2410 | " xmlFree(new_val);\n" |
| 2411 | " }\n" |
| 2412 | " } else {\n" |
| 2413 | , sdef->elements[0].name |
| 2414 | , sdef->elements[0].name |
| 2415 | , sdef->elements[1].name |
| 2416 | ); |
| 2417 | } /* QName */ |
| 2418 | |
| 2419 | if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { |
| 2420 | src = mputstr(src, "if (e_xer) {\n"); |
| 2421 | } |
| 2422 | |
| 2423 | /* ******************************************************************** |
| 2424 | * ATTRIBUTES |
| 2425 | ***************************/ |
| 2426 | if (num_attributes || sdef->xerUseNilPossible /* maybe QNAME too ? */) { |
| 2427 | size_t aaa; |
| 2428 | src = mputstr(src, " if (!omit_tag || parent_tag) {\n"); |
| 2429 | |
| 2430 | /* Prepare for attributes not present in the XML. |
| 2431 | * Set all attributes with defaultForEmpty to the D-F-E value. |
| 2432 | * Set all optional components with ATTRIBUTE to omit. |
| 2433 | * |
| 2434 | * If EMBED-VALUES is possible, the first component can't be optional. |
| 2435 | * The same is true for the USE-ORDER component. Hence start_at. */ |
| 2436 | for (aaa = start_at; aaa < start_at + num_attributes; ++aaa) { |
| 2437 | if (sdef->elements[aaa].xerAttribute) { /* "proper" ATTRIBUTE */ |
| 2438 | src = mputprintf(src, |
| 2439 | " if (%s_xer_.dfeValue) field_%s = " |
| 2440 | "*static_cast<const %s*>(%s_xer_.dfeValue);\n" |
| 2441 | , sdef->elements[aaa].typegen, sdef->elements[aaa].name |
| 2442 | , sdef->elements[aaa].type , sdef->elements[aaa].typegen); |
| 2443 | if (sdef->elements[aaa].isOptional) src = mputprintf(src, |
| 2444 | " else field_%s = OMIT_VALUE;\n", sdef->elements[aaa].name); |
| 2445 | } |
| 2446 | else { /* must be the ANY-ATTRIBUTES */ |
| 2447 | src = mputprintf(src, |
| 2448 | " field_%s%s;\n" |
| 2449 | , sdef->elements[aaa].name |
| 2450 | , sdef->elements[aaa].isOptional ? " = OMIT_VALUE" : ".set_size(0)"); |
| 2451 | } |
| 2452 | } |
| 2453 | |
| 2454 | if (num_attributes==0 /* therefore sdef->xerUseNilPossible is true */ ) { |
| 2455 | /* Only the "nil" attribute may be present. If there is no USE-NIL, |
| 2456 | * then there can be no attributes at all. */ |
| 2457 | src = mputstr(src, |
| 2458 | " if (e_xer && (p_td.xer_bits & (USE_NIL|USE_TYPE_ATTR))) {\n"); |
| 2459 | } |
| 2460 | |
| 2461 | if (aa_index > -1) src = mputstr(src, " size_t num_aa = 0;\n"); |
| 2462 | if (sdef->xerUseNilPossible) { |
| 2463 | src = mputstr(src, |
| 2464 | " static const namespace_t *control_ns = p_td.my_module->get_controlns();\n"); |
| 2465 | } |
| 2466 | |
| 2467 | src = mputstr(src, |
| 2468 | " for (rd_ok = p_reader.MoveToFirstAttribute(); rd_ok==1 && " |
| 2469 | "p_reader.NodeType()==XML_READER_TYPE_ATTRIBUTE; " |
| 2470 | "rd_ok = p_reader.AdvanceAttribute()) {\n" |
| 2471 | " if (p_reader.IsNamespaceDecl()) continue;\n"); |
| 2472 | /* if the only attribute is ANY-ATTRIBUTE, it doesn't need attr_name */ |
| 2473 | if (num_attributes==1 && aa_index!=-1 /*&& !sdef->xerUseNilPossible*/) {} |
| 2474 | else { |
| 2475 | src = mputstr(src, |
| 2476 | " const char *attr_name = (const char*)p_reader.LocalName();\n" |
| 2477 | " const char *ns_uri = (const char*)p_reader.NamespaceUri();\n"); |
| 2478 | } |
| 2479 | |
| 2480 | if (sdef->xerUseNilPossible) { |
| 2481 | src = mputprintf(src, |
| 2482 | " const char *prefix = (const char*)p_reader.Prefix();\n" |
| 2483 | /* prefix may be NULL, control_ns->px is never NULL or empty */ |
| 2484 | " if (prefix && !strcmp(prefix, control_ns->px)\n" |
| 2485 | " && !strcmp((const char*)p_reader.LocalName(), \"nil\")){\n" |
| 2486 | " const char *value = (const char*)p_reader.Value();\n" |
| 2487 | " if (!strcmp(value, \"1\") || !strcmp(value, \"true\")) {\n" |
| 2488 | " field_%s = OMIT_VALUE;\n" |
| 2489 | " nil_attribute = TRUE;\n" |
| 2490 | /* found the "nil" attribute */ |
| 2491 | " }\n" |
| 2492 | " } else" |
| 2493 | , sdef->elements[sdef->nElements-1].name); |
| 2494 | } |
| 2495 | |
| 2496 | for (i = start_at; i < start_at + num_attributes; ++i) { |
| 2497 | if (i == aa_index) continue; /* ANY_ATTR. is handled below */ |
| 2498 | src = mputprintf(src, |
| 2499 | " if (check_name(attr_name, %s_xer_, 1) && check_namespace(ns_uri, %s_xer_)) {\n" |
| 2500 | " ec_1.set_msg(\"%s': \");\n" |
| 2501 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), 0);\n" |
| 2502 | " } else" |
| 2503 | , sdef->elements[i].typegen, sdef->elements[i].typegen |
| 2504 | , sdef->elements[i].dispname /* set_msg */ |
| 2505 | , sdef->elements[i].name, sdef->elements[i].typegen |
| 2506 | ); |
| 2507 | } |
| 2508 | |
| 2509 | if (sdef->control_ns_prefix && !(num_attributes==1 && aa_index!=-1)) { |
| 2510 | src = mputprintf(src, |
| 2511 | " if (parent_tag && !strcmp(attr_name, \"type\") " |
| 2512 | "&& !strcmp((const char*)p_reader.Prefix(), \"%s\")) {} else\n" |
| 2513 | , sdef->control_ns_prefix); |
| 2514 | /* xsi:type; already processed by parent with USE-UNION or USE-TYPE */ |
| 2515 | } |
| 2516 | |
| 2517 | |
| 2518 | if (aa_index >= 0) { |
| 2519 | /* we are at a dangling else */ |
| 2520 | src = mputprintf(src, |
| 2521 | " {\n" |
| 2522 | " TTCN_EncDec_ErrorContext ec_0(\"Attribute %%d: \", (int)num_aa);\n" |
| 2523 | " UNIVERSAL_CHARSTRING& new_elem = field_%s%s[num_aa++];\n" |
| 2524 | /* Construct the AnyAttributeFormat (X.693amd1, 18.2.6) */ |
| 2525 | " TTCN_Buffer aabuf;\n" |
| 2526 | " const xmlChar *x_name = p_reader.LocalName();\n" |
| 2527 | " const xmlChar *x_val = p_reader.Value();\n" |
| 2528 | " const xmlChar *x_uri = p_reader.NamespaceUri();\n" |
| 2529 | " if (%s_xer_.xer_bits & (ANY_FROM | ANY_EXCEPT)) {\n" |
| 2530 | " check_namespace_restrictions(%s_xer_, (const char*)x_uri);\n" |
| 2531 | " }\n" |
| 2532 | /* We don't care about p_reader.Prefix() */ |
| 2533 | /* Using strlen to count bytes */ |
| 2534 | " aabuf.put_s(x_uri ? strlen((const char*)x_uri) : 0, x_uri);\n" |
| 2535 | " if (x_uri && *x_uri) aabuf.put_c(' ');\n" |
| 2536 | " aabuf.put_s(x_name ? strlen((const char*)x_name) : 0, x_name);\n" |
| 2537 | " aabuf.put_c('=');\n" |
| 2538 | " aabuf.put_c('\"');\n" |
| 2539 | " aabuf.put_s(x_val ? strlen((const char*)x_val) : 0, x_val);\n" |
| 2540 | " aabuf.put_c('\"');\n" |
| 2541 | " new_elem.decode_utf8(aabuf.get_len(), aabuf.get_data());\n" |
| 2542 | " } \n" |
| 2543 | , sdef->elements[aa_index].name |
| 2544 | , sdef->elements[aa_index].isOptional ? "()" : "" |
| 2545 | , sdef->elements[aa_index].typegen, sdef->elements[aa_index].typegen |
| 2546 | ); |
| 2547 | } |
| 2548 | else { |
| 2549 | /* we are at a dangling else */ |
| 2550 | src = mputstr(src, " {\n"); |
| 2551 | if (sdef->control_ns_prefix) { |
| 2552 | src = mputprintf(src, |
| 2553 | // Lastly check for the xsi:schemaLocation attribute, this does not |
| 2554 | // affect TTCN-3, but it shouldn't cause a DTE |
| 2555 | " if (!p_reader.LocalName() || strcmp((const char*)p_reader.LocalName(), \"schemaLocation\") ||\n" |
| 2556 | " !p_reader.Prefix() || strcmp((const char*)p_reader.Prefix(), \"%s\"))\n" |
| 2557 | , sdef->control_ns_prefix); |
| 2558 | } |
| 2559 | src = mputstr(src, |
| 2560 | " {\n" |
| 2561 | " ec_0.set_msg(\" \"); ec_1.set_msg(\" \");\n" /* we have no component */ |
| 2562 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, " |
| 2563 | "\"Unexpected attribute '%s', ns '%s'\", attr_name, ns_uri ? ns_uri : \"\");\n" |
| 2564 | " }\n" |
| 2565 | " }\n"); |
| 2566 | } |
| 2567 | src = mputstr(src, " }\n"); /* for */ |
| 2568 | |
| 2569 | for (i = start_at; i < start_at + num_attributes; ++i) { |
| 2570 | if (sdef->elements[i].isOptional) continue; /* allowed to be missing */ |
| 2571 | src = mputprintf(src, " if (!field_%s.is_bound()) " |
| 2572 | "TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, " |
| 2573 | "\"Missing attribute '%s'\");\n" |
| 2574 | , sdef->elements[i].name, sdef->elements[i].dispname); |
| 2575 | } |
| 2576 | |
| 2577 | if (num_attributes==0) src = mputstr(src, " }\n"); /* if USE_NIL or USE_TYPE_ATTR */ |
| 2578 | src = mputstr(src, " }\n"); /* process (attributes) in (own or parent) tag */ |
| 2579 | } /* * * * * * * * * end if(attributes...) * * * * * * * * * * * * */ |
| 2580 | |
| 2581 | src = mputstr(src, |
| 2582 | " if ((!omit_tag || parent_tag) && !p_reader.IsEmptyElement()) " |
| 2583 | "rd_ok = p_reader.Read();\n"); |
| 2584 | |
| 2585 | if (sdef->xerEmbedValuesPossible && num_attributes==0) { |
| 2586 | /* EMBED-VALUES possible, but isn't: the first component is a non-special |
| 2587 | * record of strings. This means there are no attributes, unless |
| 2588 | * the first component is an ATTRIBUTE or ANY-ATTRIBUTES. */ |
| 2589 | src = mputprintf(src, |
| 2590 | " if (!(p_td.xer_bits & EMBED_VALUES)) {\n" |
| 2591 | " ec_1.set_msg(\"%s': \");\n" |
| 2592 | " field_%s.XER_decode(%s_xer_, p_reader, " |
| 2593 | "p_flavor | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0), 0);\n" |
| 2594 | " }\n" |
| 2595 | , sdef->elements[0].dispname |
| 2596 | , sdef->elements[0].name, sdef->elements[0].typegen |
| 2597 | ); |
| 2598 | } |
| 2599 | |
| 2600 | if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { |
| 2601 | src = mputstr(src, |
| 2602 | "} else {\n" /* now the non-EXER processing of (would-be) attributes */ |
| 2603 | " if (!p_reader.IsEmptyElement()) p_reader.Read();\n" |
| 2604 | ); |
| 2605 | } |
| 2606 | |
| 2607 | if (sdef->xerUseOrderPossible) { |
| 2608 | src = mputstr(src, |
| 2609 | " if (e_xer && p_td.xer_bits & USE_ORDER) ; else {"); |
| 2610 | } |
| 2611 | |
| 2612 | if (start_at + num_attributes > 0) |
| 2613 | { |
| 2614 | /* No attributes nor USE-NIL: |
| 2615 | * Just decode the specials and would-be attributes. */ |
| 2616 | |
| 2617 | // FIXME: WTF is this? |
| 2618 | //if (sdef->xerEmbedValuesPossible) { |
| 2619 | // /* Only decode the first member if it really is EMBED-VALUES */ |
| 2620 | // src = mputprintf(src, "if (p_td.xer_bits & EMBED_VALUES) "); |
| 2621 | //} |
| 2622 | for (i = 0; i < start_at + num_attributes; ++i) { |
| 2623 | /* Decode the field */ |
| 2624 | src = mputprintf(src, |
| 2625 | " {\n" |
| 2626 | " ec_1.set_msg(\"%s': \");\n" |
| 2627 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor | (p_td.xer_bits & USE_NIL), 0);\n" |
| 2628 | " }\n" |
| 2629 | , sdef->elements[i].dispname |
| 2630 | , sdef->elements[i].name, sdef->elements[i].typegen |
| 2631 | ); |
| 2632 | } /* next field */ |
| 2633 | |
| 2634 | if (sdef->xerUseOrderPossible) { |
| 2635 | src = mputstr(src, " }\n"); |
| 2636 | } |
| 2637 | } |
| 2638 | |
| 2639 | if (num_attributes || sdef->xerEmbedValuesPossible || sdef->xerUseOrderPossible) { |
| 2640 | src = mputstr(src, "}\n"); |
| 2641 | } |
| 2642 | |
| 2643 | if (sdef->xerEmbedValuesPossible) { |
| 2644 | src = mputprintf(src, |
| 2645 | " embed_values_dec_struct_t* emb_val = 0;\n" |
| 2646 | " if (e_xer && (p_td.xer_bits & EMBED_VALUES)) {\n" |
| 2647 | " emb_val = new embed_values_dec_struct_t;\n" |
| 2648 | /* If the first field is a record of ANY-ELEMENTs, then it won't be a pre-generated |
| 2649 | * record of universal charstring, so it needs a cast to avoid a compilation error */ |
| 2650 | " emb_val->embval_array%s = (PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING%s*)&field_%s;\n" |
| 2651 | " emb_val->embval_array%s = NULL;\n" |
| 2652 | " emb_val->embval_index = 0;\n" |
| 2653 | " field_%s.set_size(0);\n" |
| 2654 | " }\n" |
| 2655 | , sdef->elements[0].optimizedMemAlloc ? "_opt" : "_reg" |
| 2656 | , sdef->elements[0].optimizedMemAlloc ? "__OPTIMIZED" : "" |
| 2657 | , sdef->elements[0].name |
| 2658 | , sdef->elements[0].optimizedMemAlloc ? "_reg" : "_opt" |
| 2659 | , sdef->elements[0].name); |
| 2660 | } |
| 2661 | |
| 2662 | if (sdef->xerUseOrderPossible) { |
| 2663 | size_t begin = start_at + num_attributes; /* first non-attribute */ |
| 2664 | size_t end = sdef->nElements; |
| 2665 | size_t n_optionals = 0, n_embed; |
| 2666 | int max_ordered = sdef->nElements - start_at - num_attributes; |
| 2667 | int min_ordered = max_ordered - n_opt_elements; |
| 2668 | if (sdef->xerUseNilPossible) { /* USE-NIL on top of USE-ORDER */ |
| 2669 | begin = sdef->nElements; |
| 2670 | end = sdef->totalElements; |
| 2671 | } |
| 2672 | n_embed = end - begin; |
| 2673 | |
| 2674 | src = mputstr(src, |
| 2675 | " if (e_xer && (p_td.xer_bits & USE_ORDER)) {\n" |
| 2676 | ); |
| 2677 | for (i = begin; i < end; ++i) { |
| 2678 | if (sdef->elements[i].isOptional) { |
| 2679 | src = mputprintf(src, " field_%s = OMIT_VALUE;\n", |
| 2680 | sdef->elements[i].name); |
| 2681 | ++n_optionals; |
| 2682 | } |
| 2683 | } |
| 2684 | |
| 2685 | if (sdef->xerUseNilPossible) { /* USE-NIL and USE-ORDER */ |
| 2686 | src = mputprintf(src, |
| 2687 | " if (nil_attribute) field_%s.set_size(0);\n else" |
| 2688 | , sdef->elements[uo].name); |
| 2689 | } |
| 2690 | |
| 2691 | src = mputprintf(src, |
| 2692 | " {\n" |
| 2693 | " field_%s.set_size(0);\n" |
| 2694 | " if (!tag_closed) {\n" /* Nothing to order if there are no child elements */ |
| 2695 | " int e_val, num_seen = 0, *seen_f = new int[%lu];\n" |
| 2696 | , sdef->elements[uo].name |
| 2697 | , (unsigned long)(n_embed) |
| 2698 | ); |
| 2699 | if (sdef->xerEmbedValuesPossible) { |
| 2700 | // The index of the latest embedded value can change outside of this function |
| 2701 | // (if the field is a untagged record of), in this case the next value should |
| 2702 | // be ignored, as it's already been handled by the record of |
| 2703 | src = mputstr(src, " int last_embval_index = 0;\n"); |
| 2704 | } |
| 2705 | src = mputprintf(src, |
| 2706 | " bool early_exit = false;\n" |
| 2707 | " for (int i=0; i < %lu; ++i) {\n" |
| 2708 | " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" |
| 2709 | , (unsigned long)(n_embed)); |
| 2710 | |
| 2711 | if (sdef->xerEmbedValuesPossible) { |
| 2712 | /* read and store embedValues text if present */ |
| 2713 | src = mputprintf(src, |
| 2714 | " if (0 != emb_val && p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" |
| 2715 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" |
| 2716 | " field_%s[emb_val->embval_index] = emb_ustr;\n" |
| 2717 | " }\n" |
| 2718 | , sdef->elements[0].name); |
| 2719 | } |
| 2720 | |
| 2721 | src = mputstr(src, |
| 2722 | " type = p_reader.NodeType();\n" |
| 2723 | " if (type==XML_READER_TYPE_ELEMENT) break;\n" |
| 2724 | " if (type == XML_READER_TYPE_END_ELEMENT) {\n" |
| 2725 | " early_exit = true;\n" |
| 2726 | " break;\n" |
| 2727 | " }\n" |
| 2728 | " }\n" |
| 2729 | " if (rd_ok != 1 || early_exit) break;\n" |
| 2730 | " const char * x_name = (const char*)p_reader.LocalName();\n" /* Name or LocalName ? */); |
| 2731 | |
| 2732 | if (sdef->xerEmbedValuesPossible) { |
| 2733 | src = mputstr(src, |
| 2734 | " if (0 != emb_val) {\n" |
| 2735 | " if (last_embval_index == emb_val->embval_index) {\n" |
| 2736 | " ++emb_val->embval_index;\n" |
| 2737 | " }\n" |
| 2738 | " last_embval_index = emb_val->embval_index;\n" |
| 2739 | " }\n"); |
| 2740 | } |
| 2741 | |
| 2742 | /* * * * * code for USE-ORDER * * * * */ |
| 2743 | |
| 2744 | for (i = begin; i < end; ++i) { |
| 2745 | // Check non-anyElement fields first |
| 2746 | if (!(sdef->elements[i].xerAnyKind & ANY_ELEM_BIT)) { |
| 2747 | src = mputprintf(src, |
| 2748 | " if (check_name(x_name, %s_xer_, 1)) {\n" |
| 2749 | " ec_1.set_msg(\"%s': \");\n" |
| 2750 | " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, %s);\n" |
| 2751 | , sdef->elements[i].typegen |
| 2752 | , sdef->elements[i].dispname |
| 2753 | , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name) |
| 2754 | , (sdef->xerUseNilPossible ? "()." : "") |
| 2755 | , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") |
| 2756 | , (sdef->xerUseNilPossible ? "()" : "") |
| 2757 | , sdef->elements[i].typegen |
| 2758 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0" |
| 2759 | ); |
| 2760 | src = mputprintf(src, |
| 2761 | " field_%s[i] = e_val = %s::of_type::%s;\n" |
| 2762 | , sdef->elements[uo].name |
| 2763 | , sdef->elements[uo].typegen, sdef->elements[i].name); |
| 2764 | src = mputstr(src, " }\n else"); |
| 2765 | } |
| 2766 | } |
| 2767 | src = mputstr(src, |
| 2768 | " {\n" |
| 2769 | " boolean any_found = false;\n" |
| 2770 | " if (!any_found)"); |
| 2771 | for (i = begin; i < end; ++i) { |
| 2772 | // Check anyElement fields after all other fields |
| 2773 | if (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT) { |
| 2774 | src = mputstr(src, " {\n"); |
| 2775 | src = mputprintf(src, |
| 2776 | " e_val = %s::of_type::%s;\n" |
| 2777 | , sdef->elements[uo].typegen, sdef->elements[i].name); |
| 2778 | src = mputprintf(src, |
| 2779 | " boolean next_any = false;\n" |
| 2780 | " for (int d_f = 0; d_f < num_seen; ++d_f) {\n" |
| 2781 | " if (e_val == seen_f[d_f]) {\n" |
| 2782 | " next_any = true;\n" |
| 2783 | " }\n" |
| 2784 | " }\n" |
| 2785 | " if (!next_any) {\n" |
| 2786 | " ec_1.set_msg(\"%s': \");\n" |
| 2787 | " field_%s%s%s%s.XER_decode(%s_xer_, p_reader, p_flavor, 0);\n" |
| 2788 | " field_%s[i] = e_val;\n" |
| 2789 | " any_found = true;\n" |
| 2790 | " }\n" |
| 2791 | " }\n" |
| 2792 | " if (!any_found)" |
| 2793 | , sdef->elements[i].dispname |
| 2794 | , (sdef->xerUseNilPossible ? sdef->elements[sdef->nElements-1].name: sdef->elements[i].name) |
| 2795 | , (sdef->xerUseNilPossible ? "()." : "") |
| 2796 | , (sdef->xerUseNilPossible ? sdef->elements[i].name : "") |
| 2797 | , (sdef->xerUseNilPossible ? "()" : "") |
| 2798 | , sdef->elements[i].typegen, sdef->elements[uo].name |
| 2799 | ); |
| 2800 | } |
| 2801 | } |
| 2802 | |
| 2803 | src = mputstr(src, |
| 2804 | " {\n" /* take care of the dangling else */ |
| 2805 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,\n" |
| 2806 | " \"Bad XML tag '%s' instead of a valid field\", x_name);\n" |
| 2807 | " break;\n" |
| 2808 | " }\n" |
| 2809 | " }\n" |
| 2810 | " for (int d_f = 0; d_f < num_seen; ++d_f)\n" |
| 2811 | " if (e_val == seen_f[d_f])\n" |
| 2812 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Duplicate field\");\n" |
| 2813 | " seen_f[num_seen++] = e_val;\n" |
| 2814 | " } // next i\n"); |
| 2815 | |
| 2816 | if (sdef->xerEmbedValuesPossible) { |
| 2817 | /* read and store embedValues text if present */ |
| 2818 | src = mputprintf(src, |
| 2819 | " if (0 != emb_val) {\n" |
| 2820 | " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" |
| 2821 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" |
| 2822 | " field_%s[emb_val->embval_index] = emb_ustr;\n" |
| 2823 | " }\n" |
| 2824 | " if (last_embval_index == emb_val->embval_index) {\n" |
| 2825 | " ++emb_val->embval_index;\n" |
| 2826 | " }\n" |
| 2827 | " }\n" |
| 2828 | , sdef->elements[0].name); |
| 2829 | } |
| 2830 | |
| 2831 | src = mputprintf(src, |
| 2832 | " delete [] seen_f;\n" |
| 2833 | " }\n" |
| 2834 | " int n_collected = field_%s.size_of();\n" |
| 2835 | " if (p_td.xer_bits & USE_NIL) {\n" |
| 2836 | " ;\n" |
| 2837 | " } else {\n" |
| 2838 | " if (n_collected < %d || n_collected > %d) {\n" |
| 2839 | " ec_0.set_msg(\" \");\n" |
| 2840 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT, \"Wrong number of elements\");\n" |
| 2841 | " }\n" |
| 2842 | " }\n" |
| 2843 | " } // !tag_closed\n" |
| 2844 | " } else { // !uo\n" |
| 2845 | , sdef->elements[uo].dispname |
| 2846 | , min_ordered, max_ordered |
| 2847 | ); |
| 2848 | } /* end if(UseOrder possible) */ |
| 2849 | |
| 2850 | /* * * * * non-UseOrder code always written, executed when * * * * |
| 2851 | * * * * * UseOrder not possible or in the "else" clause * * * * */ |
| 2852 | |
| 2853 | if (sdef->xerUseNilPossible) { |
| 2854 | /* value absent, nothing more to do */ |
| 2855 | src = mputstr(src, |
| 2856 | " if (nil_attribute) {\n" |
| 2857 | " p_reader.MoveToElement();\n" |
| 2858 | " } else {\n"); |
| 2859 | } |
| 2860 | if (sdef->xerEmbedValuesPossible) { |
| 2861 | // The index of the latest embedded value can change outside of this function |
| 2862 | // (if the field is a untagged record of), in this case the next value should |
| 2863 | // be ignored, as it's already been handled by the record of |
| 2864 | // Omitted fields can also reset this value |
| 2865 | src = mputstr(src, " int last_embval_index = 0;\n"); |
| 2866 | } |
| 2867 | /* for all the non-attribute fields... */ |
| 2868 | for (i = start_at + num_attributes; i < sdef->nElements; ++i) { |
| 2869 | if (sdef->xerEmbedValuesPossible) { |
| 2870 | /* read and store embedValues text if present */ |
| 2871 | src = mputprintf(src, |
| 2872 | " if (0 != emb_val) {\n" |
| 2873 | " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" |
| 2874 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" |
| 2875 | " field_%s[emb_val->embval_index] = emb_ustr;\n" |
| 2876 | " }\n" |
| 2877 | " if (last_embval_index == emb_val->embval_index) {\n" |
| 2878 | " ++emb_val->embval_index;\n" |
| 2879 | " }\n" |
| 2880 | " last_embval_index = emb_val->embval_index;\n" |
| 2881 | " }\n" |
| 2882 | , sdef->elements[0].name); |
| 2883 | } |
| 2884 | /* The DEFAULT-FOR-EMPTY member can not be involved with EMBED-VALUES, |
| 2885 | * so we can use the same pattern: optional "if(...) else" before {} |
| 2886 | * XXX check with single-element record where nElements-1 == 0 !! */ |
| 2887 | if (sdef->kind == RECORD && i == sdef->nElements-1) { |
| 2888 | src = mputprintf(src, |
| 2889 | " if (e_xer && p_td.dfeValue && p_reader.IsEmptyElement()) {\n" |
| 2890 | " field_%s = *static_cast<const %s*>(p_td.dfeValue);\n" |
| 2891 | " }\n" |
| 2892 | " else" |
| 2893 | , sdef->elements[i].name, sdef->elements[i].type); |
| 2894 | } |
| 2895 | /* Decode the field */ |
| 2896 | src = mputprintf(src, |
| 2897 | " {\n" |
| 2898 | " ec_1.set_msg(\"%s': \");\n" |
| 2899 | , sdef->elements[i].dispname); |
| 2900 | |
| 2901 | if ( (sdef->elements[i].xerAnyKind & ANY_ELEM_BIT) |
| 2902 | && !strcmp(sdef->elements[i].type,"UNIVERSAL_CHARSTRING") ) { |
| 2903 | // In case the field is an optional anyElement -> check if it should be omitted |
| 2904 | if (sdef->elements[i].isOptional) { |
| 2905 | src = mputprintf(src, |
| 2906 | " if (field_%s.XER_check_any_elem(p_reader, \"%s\", tag_closed))\n " |
| 2907 | , sdef->elements[i].name |
| 2908 | , (i == sdef->nElements - 1) ? "NULL" : sdef->elements[i + 1].name); |
| 2909 | } else { |
| 2910 | // If the record is emptyElement, there's no way it will have an anyElement field |
| 2911 | src = mputstr(src, " if (tag_closed) p_reader.Read(); \n"); |
| 2912 | } |
| 2913 | } |
| 2914 | |
| 2915 | src = mputprintf(src, |
| 2916 | " field_%s.XER_decode(%s_xer_, p_reader, p_flavor" |
| 2917 | " | (p_td.xer_bits & USE_NIL)| (tag_closed ? PARENT_CLOSED : 0), %s);\n" |
| 2918 | " }\n" |
| 2919 | , sdef->elements[i].name, sdef->elements[i].typegen |
| 2920 | , sdef->xerEmbedValuesPossible ? "emb_val" : "0"); |
| 2921 | if (sdef->xerEmbedValuesPossible) { |
| 2922 | src = mputprintf(src, |
| 2923 | " if (!field_%s.is_present()) {\n" |
| 2924 | // there was no new element, the last embedded value is for the next field |
| 2925 | // (or the end of the record if this is the last field) |
| 2926 | " last_embval_index = -1;\n" |
| 2927 | " }\n" |
| 2928 | , sdef->elements[i].name); |
| 2929 | } |
| 2930 | } /* next field */ |
| 2931 | |
| 2932 | if (sdef->xerEmbedValuesPossible) { |
| 2933 | /* read and store embedValues text if present */ |
| 2934 | src = mputprintf(src, |
| 2935 | " if (0 != emb_val) {\n" |
| 2936 | " if (p_reader.NodeType()==XML_READER_TYPE_TEXT) {\n" |
| 2937 | " UNIVERSAL_CHARSTRING emb_ustr((const char*)p_reader.Value());\n" |
| 2938 | " field_%s[emb_val->embval_index] = emb_ustr;\n" |
| 2939 | " }\n" |
| 2940 | " if (last_embval_index == emb_val->embval_index) {\n" |
| 2941 | " ++emb_val->embval_index;\n" |
| 2942 | " }\n" |
| 2943 | " }\n" |
| 2944 | , sdef->elements[0].name); |
| 2945 | } |
| 2946 | |
| 2947 | if (sdef->xerUseNilPossible) { |
| 2948 | src = mputstr(src, " } // use_nil\n"); |
| 2949 | } |
| 2950 | |
| 2951 | if (sdef->xerUseOrderPossible) { |
| 2952 | src = mputstr(src, " } // uo\n"); |
| 2953 | } |
| 2954 | |
| 2955 | if (sdef->xerEmbedValuesPossible) { |
| 2956 | src = mputprintf(src, |
| 2957 | " if (0 != emb_val) {\n" |
| 2958 | " %s::of_type empty_string(\"\");\n" |
| 2959 | " for (int j_j = 0; j_j < emb_val->embval_index; ++j_j) {\n" |
| 2960 | " if (!field_%s[j_j].is_bound()) field_%s[j_j] = empty_string;\n" |
| 2961 | " }\n" |
| 2962 | " delete emb_val;\n" |
| 2963 | " }\n" |
| 2964 | , sdef->elements[0].type |
| 2965 | , sdef->elements[0].name |
| 2966 | , sdef->elements[0].name |
| 2967 | ); |
| 2968 | } |
| 2969 | |
| 2970 | if (sdef->xerUseQName) { |
| 2971 | src = mputstr(src, " } // qn\n"); |
| 2972 | } |
| 2973 | |
| 2974 | src = mputstr(src, |
| 2975 | " } // errorcontext\n"); /* End scope for error context objects */ |
| 2976 | |
| 2977 | /* Check if every non-optional field has been set */ |
| 2978 | for (i = 0; i < sdef->nElements; ++i) { |
| 2979 | if (!sdef->elements[i].isOptional) { |
| 2980 | src = mputprintf(src, |
| 2981 | " if (!field_%s.is_bound()) {\n" |
| 2982 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,\n" |
| 2983 | " \"No data found for non-optional field '%s'\");\n" |
| 2984 | " }\n" |
| 2985 | , sdef->elements[i].name, sdef->elements[i].dispname); |
| 2986 | } |
| 2987 | } |
| 2988 | src = mputstr(src, |
| 2989 | " if (!omit_tag) {\n" |
| 2990 | " int current_depth;\n" |
| 2991 | " for (rd_ok = p_reader.Ok(); rd_ok == 1; rd_ok = p_reader.Read()) {\n" |
| 2992 | " type = p_reader.NodeType();\n" |
| 2993 | " if ((current_depth = p_reader.Depth()) > xml_depth) {\n" |
| 2994 | " if (XML_READER_TYPE_ELEMENT == type) {\n" |
| 2995 | /* An element deeper than our start tag has not been processed */ |
| 2996 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_TAG,\n" |
| 2997 | " \"Unprocessed XML tag `%s'\", (const char *)p_reader.Name());\n" |
| 2998 | " }\n" |
| 2999 | " continue;\n" |
| 3000 | " }\n" |
| 3001 | " else if (current_depth == xml_depth) {\n" |
| 3002 | " if (XML_READER_TYPE_ELEMENT == type) {\n" |
| 3003 | " verify_name(p_reader, p_td, e_xer);\n" |
| 3004 | " if (p_reader.IsEmptyElement()) {\n" |
| 3005 | " p_reader.Read();\n" /* advance one more time */ |
| 3006 | " break;\n" |
| 3007 | " }\n" |
| 3008 | " }\n" |
| 3009 | " else if (XML_READER_TYPE_END_ELEMENT == type) {\n" |
| 3010 | " verify_end(p_reader, p_td, xml_depth, e_xer);\n" |
| 3011 | " rd_ok = p_reader.Read();\n" |
| 3012 | " break;\n" |
| 3013 | " }\n" |
| 3014 | " }\n" |
| 3015 | " else break;" /* depth is less, we are in trouble... */ |
| 3016 | " }\n" |
| 3017 | " }\n" |
| 3018 | " return 1;\n}\n\n"); |
| 3019 | |
| 3020 | *pdef = def; |
| 3021 | *psrc = src; |
| 3022 | } |
| 3023 | |
| 3024 | void defRecordClass1(const struct_def *sdef, output_struct *output) |
| 3025 | { |
| 3026 | size_t i; |
| 3027 | size_t mandatory_fields_count; |
| 3028 | const char *name = sdef->name, *dispname = sdef->dispname; |
| 3029 | const char* kind_str = sdef->kind == SET ? "set" : "record"; |
| 3030 | char *def = NULL, *src = NULL; |
| 3031 | boolean ber_needed = sdef->isASN1 && enable_ber(); |
| 3032 | boolean raw_needed = sdef->hasRaw && enable_raw(); |
| 3033 | boolean text_needed = sdef->hasText && enable_text(); |
| 3034 | boolean xer_needed = sdef->hasXer && enable_xer(); |
| 3035 | boolean json_needed = sdef->hasJson && enable_json(); |
| 3036 | |
| 3037 | /* class declaration code */ |
| 3038 | output->header.class_decls = mputprintf(output->header.class_decls, |
| 3039 | "class %s;\n", name); |
| 3040 | |
| 3041 | if (sdef->nElements <= 0) { |
| 3042 | defEmptyRecordClass(sdef, output); |
| 3043 | return; |
| 3044 | } |
| 3045 | |
| 3046 | /* class definition and source code */ |
| 3047 | if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) { |
| 3048 | def=mputprintf |
| 3049 | (def, |
| 3050 | #ifndef NDEBUG |
| 3051 | "// written by %s in " __FILE__ " at line %d\n" |
| 3052 | #endif |
| 3053 | "class %s : public Base_Type {\n" |
| 3054 | #ifndef NDEBUG |
| 3055 | , __FUNCTION__, __LINE__ |
| 3056 | #endif |
| 3057 | , name); |
| 3058 | } else { |
| 3059 | def=mputprintf(def, "class %s {\n", name); |
| 3060 | } |
| 3061 | |
| 3062 | /* fields */ |
| 3063 | for (i = 0; i < sdef->nElements; i++) { |
| 3064 | if(sdef->elements[i].isOptional) |
| 3065 | def = mputprintf(def, " OPTIONAL<%s> field_%s;\n", |
| 3066 | sdef->elements[i].type, |
| 3067 | sdef->elements[i].name); |
| 3068 | else |
| 3069 | def = mputprintf(def, " %s field_%s;\n", |
| 3070 | sdef->elements[i].type, sdef->elements[i].name); |
| 3071 | } |
| 3072 | |
| 3073 | /* bound flag */ |
| 3074 | def = mputstr(def, " boolean bound_flag;\n"); |
| 3075 | |
| 3076 | /* default constructor */ |
| 3077 | def = mputprintf(def, "public:\n" |
| 3078 | " %s();\n", name); |
| 3079 | src = mputprintf(src, "%s::%s()\n" |
| 3080 | "{\n" |
| 3081 | " bound_flag = FALSE;\n" |
| 3082 | "}\n\n", name, name); |
| 3083 | |
| 3084 | /* constructor by fields */ |
| 3085 | def = mputprintf(def, " %s(", name); |
| 3086 | src = mputprintf(src, "%s::%s(", name, name); |
| 3087 | |
| 3088 | for (i = 0; i < sdef->nElements; i++) { |
| 3089 | char *tmp = NULL; |
| 3090 | if (i > 0) tmp = mputstr(tmp, ",\n "); |
| 3091 | if (sdef->elements[i].isOptional) |
| 3092 | tmp = mputprintf |
| 3093 | (tmp, |
| 3094 | "const OPTIONAL<%s>& par_%s", |
| 3095 | sdef->elements[i].type, sdef->elements[i].name); |
| 3096 | else |
| 3097 | tmp = mputprintf |
| 3098 | (tmp, |
| 3099 | "const %s& par_%s", |
| 3100 | sdef->elements[i].type, sdef->elements[i].name); |
| 3101 | def = mputstr(def, tmp); |
| 3102 | src = mputstr(src, tmp); |
| 3103 | Free(tmp); |
| 3104 | } |
| 3105 | def = mputstr(def, ");\n"); |
| 3106 | src = mputstr(src, ")\n" |
| 3107 | " : "); |
| 3108 | for (i = 0; i < sdef->nElements; i++) { |
| 3109 | if (i > 0) src = mputstr(src, ",\n"); |
| 3110 | src = mputprintf(src, " field_%s(par_%s)", sdef->elements[i].name, |
| 3111 | sdef->elements[i].name); |
| 3112 | } |
| 3113 | src = mputstr(src, "\n" |
| 3114 | "{\n" |
| 3115 | " bound_flag = TRUE;\n" |
| 3116 | "}\n\n"); |
| 3117 | |
| 3118 | /* copy constructor */ |
| 3119 | def = mputprintf(def, " %s(const %s& other_value);\n", name, name); |
| 3120 | src = mputprintf(src, "%s::%s(const %s& other_value)\n" |
| 3121 | "{\n" |
| 3122 | "if(!other_value.is_bound()) " |
| 3123 | "TTCN_error(\"Copying an unbound value of type %s.\");\n" |
| 3124 | "bound_flag = TRUE;\n", |
| 3125 | name, name, name, dispname); |
| 3126 | for (i = 0; i < sdef->nElements; i++) { |
| 3127 | src = mputprintf(src, |
| 3128 | "if (other_value.%s().is_bound()) field_%s = other_value.%s();\n" |
| 3129 | "else field_%s.clean_up();\n", |
| 3130 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name, |
| 3131 | sdef->elements[i].name); |
| 3132 | } |
| 3133 | src = mputstr(src, "}\n\n"); |
| 3134 | |
| 3135 | /* not a component */ |
| 3136 | def = mputstr(def, " inline boolean is_component() { return FALSE; }\n"); |
| 3137 | |
| 3138 | /* clean_up */ |
| 3139 | def = mputstr(def, " void clean_up();\n"); |
| 3140 | src = mputprintf(src, "void %s::clean_up()\n" |
| 3141 | "{\n", name); |
| 3142 | for (i = 0; i < sdef->nElements; i++) { |
| 3143 | src = mputprintf(src, |
| 3144 | "field_%s.clean_up();\n", sdef->elements[i].name); |
| 3145 | } |
| 3146 | src = mputstr(src, |
| 3147 | "bound_flag = FALSE;\n" |
| 3148 | "}\n\n"); |
| 3149 | |
| 3150 | /* = operator */ |
| 3151 | def = mputprintf(def, " %s& operator=(const %s& other_value);\n", name, name); |
| 3152 | src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n" |
| 3153 | "{\n" |
| 3154 | "if (this != &other_value) {\n" |
| 3155 | " if(!other_value.is_bound()) " |
| 3156 | "TTCN_error(\"Assignment of an unbound value of type %s.\");\n" |
| 3157 | " bound_flag = TRUE;\n", |
| 3158 | name, name, name, dispname); |
| 3159 | for (i = 0; i < sdef->nElements; i++) { |
| 3160 | src = mputprintf(src, |
| 3161 | " if (other_value.%s().is_bound()) field_%s = other_value.%s();\n" |
| 3162 | " else field_%s.clean_up();\n", |
| 3163 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name, |
| 3164 | sdef->elements[i].name); |
| 3165 | } |
| 3166 | src = mputstr(src, |
| 3167 | "}\n" |
| 3168 | "return *this;\n" |
| 3169 | "}\n\n"); |
| 3170 | |
| 3171 | /* == operator */ |
| 3172 | def = mputprintf(def, " boolean operator==(const %s& other_value) " |
| 3173 | "const;\n", name); |
| 3174 | src = mputprintf(src, |
| 3175 | "boolean %s::operator==(const %s& other_value) const\n" |
| 3176 | "{\n" |
| 3177 | "if (!is_bound() && !other_value.is_bound()) return TRUE;\n" |
| 3178 | "return ", name, name); |
| 3179 | for (i = 0; i < sdef->nElements; i++) { |
| 3180 | if (i > 0) src = mputstr(src, "\n && "); |
| 3181 | src = mputprintf(src, "field_%s==other_value.field_%s", |
| 3182 | sdef->elements[i].name, sdef->elements[i].name); |
| 3183 | } |
| 3184 | src = mputstr(src, ";\n}\n\n"); |
| 3185 | |
| 3186 | /* != and () operator */ |
| 3187 | def = mputprintf(def, |
| 3188 | " inline boolean operator!=(const %s& other_value) const\n" |
| 3189 | " { return !(*this == other_value); }\n\n", name); |
| 3190 | |
| 3191 | /* is_bound */ |
| 3192 | def = mputprintf(def, |
| 3193 | " boolean is_bound() const;\n\n"); |
| 3194 | src = mputprintf(src, |
| 3195 | "boolean %s::is_bound() const\n" |
| 3196 | "{\n" |
| 3197 | "if (bound_flag) return TRUE;\n", name); |
| 3198 | for(i=0; i < sdef->nElements; i++) { |
| 3199 | if(sdef->elements[i].isOptional) { |
| 3200 | src = mputprintf(src, |
| 3201 | "if(OPTIONAL_OMIT == field_%s.get_selection() || field_%s.is_bound()) return TRUE;\n", |
| 3202 | sdef->elements[i].name, sdef->elements[i].name); |
| 3203 | } else { |
| 3204 | src = mputprintf(src, |
| 3205 | "if(field_%s.is_bound()) return TRUE;\n", |
| 3206 | sdef->elements[i].name); |
| 3207 | } |
| 3208 | } |
| 3209 | src = mputprintf(src, |
| 3210 | "return FALSE;\n" |
| 3211 | "}\n"); |
| 3212 | |
| 3213 | /* is_present */ |
| 3214 | def = mputstr(def, |
| 3215 | "inline boolean is_present() const { return is_bound(); }\n"); |
| 3216 | |
| 3217 | /* is_value */ |
| 3218 | def = mputprintf(def, |
| 3219 | " boolean is_value() const;\n\n"); |
| 3220 | src = mputprintf(src, |
| 3221 | "boolean %s::is_value() const\n" |
| 3222 | "{\n" |
| 3223 | "if (!is_bound()) return FALSE;\n", name); |
| 3224 | for(i=0; i < sdef->nElements; i++) { |
| 3225 | if(sdef->elements[i].isOptional) { |
| 3226 | src = mputprintf(src, |
| 3227 | "if(OPTIONAL_OMIT != field_%s.get_selection() && !field_%s.is_value()) return FALSE;\n", |
| 3228 | sdef->elements[i].name, sdef->elements[i].name); |
| 3229 | } else { |
| 3230 | src = mputprintf(src, |
| 3231 | "if(!field_%s.is_value()) return FALSE;\n", |
| 3232 | sdef->elements[i].name); |
| 3233 | } |
| 3234 | } |
| 3235 | src = mputprintf(src, |
| 3236 | "return TRUE;\n}\n"); |
| 3237 | |
| 3238 | /* field accessor methods */ |
| 3239 | for (i = 0; i < sdef->nElements; i++) { |
| 3240 | if(sdef->elements[i].isOptional) |
| 3241 | def = mputprintf |
| 3242 | (def, |
| 3243 | " inline OPTIONAL<%s>& %s()\n" |
| 3244 | " {return field_%s;}\n" |
| 3245 | " inline const OPTIONAL<%s>& %s() const\n" |
| 3246 | " {return field_%s;}\n", |
| 3247 | sdef->elements[i].type, sdef->elements[i].name, |
| 3248 | sdef->elements[i].name, |
| 3249 | sdef->elements[i].type, sdef->elements[i].name, |
| 3250 | sdef->elements[i].name); |
| 3251 | else def = mputprintf |
| 3252 | (def, |
| 3253 | " inline %s& %s()\n" |
| 3254 | " {return field_%s;}\n" |
| 3255 | " inline const %s& %s() const\n" |
| 3256 | " {return field_%s;}\n", |
| 3257 | sdef->elements[i].type, sdef->elements[i].name, |
| 3258 | sdef->elements[i].name, sdef->elements[i].type, |
| 3259 | sdef->elements[i].name, sdef->elements[i].name); |
| 3260 | |
| 3261 | } |
| 3262 | |
| 3263 | /* sizeof operation */ |
| 3264 | mandatory_fields_count = 0; |
| 3265 | for (i = 0; i < sdef->nElements; i++) |
| 3266 | if (!sdef->elements[i].isOptional) mandatory_fields_count++; |
| 3267 | |
| 3268 | def = mputstr(def, " int size_of() const;\n"); |
| 3269 | src = mputprintf(src, |
| 3270 | "int %s::size_of() const\n" |
| 3271 | "{\n" |
| 3272 | " if (!is_bound()) " |
| 3273 | "TTCN_error(\"Calculating the size of an unbound record/set value of type %s\");\n" |
| 3274 | , name, dispname); |
| 3275 | if (sdef->nElements == mandatory_fields_count) { |
| 3276 | src = mputprintf(src, " return %lu;\n", (unsigned long) mandatory_fields_count); |
| 3277 | } |
| 3278 | else { |
| 3279 | src = mputprintf(src, " int ret_val = %lu;\n", |
| 3280 | (unsigned long) mandatory_fields_count); |
| 3281 | for (i = 0; i < sdef->nElements; i++) |
| 3282 | if (sdef->elements[i].isOptional) |
| 3283 | src = mputprintf(src, |
| 3284 | " if (field_%s.ispresent()) ret_val++;\n", |
| 3285 | sdef->elements[i].name); |
| 3286 | src = mputstr(src, " return ret_val;\n"); |
| 3287 | } |
| 3288 | src = mputstr(src, "}\n\n"); |
| 3289 | |
| 3290 | /* log function */ |
| 3291 | def = mputstr(def, " void log() const;\n"); |
| 3292 | src = mputprintf(src, |
| 3293 | "void %s::log() const\n{\n" |
| 3294 | "if (!is_bound()) {\n" |
| 3295 | "TTCN_Logger::log_event_unbound();\n" |
| 3296 | "return;\n" |
| 3297 | "}\n", name); |
| 3298 | for (i = 0; i < sdef->nElements; i++) { |
| 3299 | src = mputstr(src, "TTCN_Logger::log_event_str(\""); |
| 3300 | if (i == 0) src = mputc(src, '{'); |
| 3301 | else src = mputc(src, ','); |
| 3302 | src = mputprintf(src, " %s := \");\n" |
| 3303 | "field_%s.log();\n", |
| 3304 | sdef->elements[i].dispname, sdef->elements[i].name); |
| 3305 | } |
| 3306 | src = mputstr(src, "TTCN_Logger::log_event_str(\" }\");\n}\n\n"); |
| 3307 | |
| 3308 | /* set param function */ |
| 3309 | def = mputstr(def, " void set_param(Module_Param& param);\n"); |
| 3310 | src = mputprintf |
| 3311 | (src, |
| 3312 | "void %s::set_param(Module_Param& param)\n{\n" |
| 3313 | " bound_flag = TRUE;\n" |
| 3314 | " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n" |
| 3315 | " param.get_id()->next_name()) {\n" |
| 3316 | // Haven't reached the end of the module parameter name |
| 3317 | // => the name refers to one of the fields, not to the whole record |
| 3318 | " char* param_field = param.get_id()->get_current_name();\n" |
| 3319 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" |
| 3320 | " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n" |
| 3321 | " \" name for %s type `%s'\");\n" |
| 3322 | " }\n" |
| 3323 | " ", name, kind_str, dispname); |
| 3324 | for (i = 0; i < sdef->nElements; i++) { |
| 3325 | src = mputprintf(src, |
| 3326 | "if (strcmp(\"%s\", param_field) == 0) {\n" |
| 3327 | " %s().set_param(param);\n" |
| 3328 | " return;\n" |
| 3329 | " } else ", |
| 3330 | sdef->elements[i].dispname, sdef->elements[i].name); |
| 3331 | } |
| 3332 | src = mputprintf(src, |
| 3333 | "param.error(\"Field `%%s' not found in %s type `%s'\", param_field);\n" |
| 3334 | " }\n" |
| 3335 | " param.basic_check(Module_Param::BC_VALUE, \"%s value\");\n" |
| 3336 | " Module_Param_Ptr mp = ¶m;\n" |
| 3337 | " if (param.get_type() == Module_Param::MP_Reference) {\n" |
| 3338 | " mp = param.get_referenced_param();\n" |
| 3339 | " }\n" |
| 3340 | " switch (mp->get_type()) {\n" |
| 3341 | " case Module_Param::MP_Value_List:\n" |
| 3342 | " if (%lu<mp->get_size()) {\n" |
| 3343 | " param.error(\"%s value of type %s has %lu fields but list value has %%d fields\", (int)mp->get_size());\n" |
| 3344 | " }\n", |
| 3345 | kind_str, dispname, kind_str, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements); |
| 3346 | |
| 3347 | for (i = 0; i < sdef->nElements; ++i) { |
| 3348 | src = mputprintf(src, |
| 3349 | " if (mp->get_size()>%lu && mp->get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*mp->get_elem(%lu));\n", |
| 3350 | (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i); |
| 3351 | } |
| 3352 | src = mputstr(src, |
| 3353 | " break;\n" |
| 3354 | " case Module_Param::MP_Assignment_List: {\n" |
| 3355 | " Vector<bool> value_used(mp->get_size());\n" |
| 3356 | " value_used.resize(mp->get_size(), false);\n"); |
| 3357 | for (i = 0; i < sdef->nElements; ++i) { |
| 3358 | src = mputprintf(src, |
| 3359 | " for (size_t val_idx=0; val_idx<mp->get_size(); val_idx++) {\n" |
| 3360 | " Module_Param* const curr_param = mp->get_elem(val_idx);\n" |
| 3361 | " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n" |
| 3362 | " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n" |
| 3363 | " %s().set_param(*curr_param);\n" |
| 3364 | " }\n" |
| 3365 | " value_used[val_idx]=true;\n" |
| 3366 | " }\n" |
| 3367 | " }\n" |
| 3368 | , sdef->elements[i].dispname, sdef->elements[i].name); |
| 3369 | } |
| 3370 | src = mputprintf(src, |
| 3371 | " for (size_t val_idx=0; val_idx<mp->get_size(); val_idx++) if (!value_used[val_idx]) {\n" |
| 3372 | " mp->get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", mp->get_elem(val_idx)->get_id()->get_name());\n" |
| 3373 | " break;\n" |
| 3374 | " }\n" |
| 3375 | " } break;\n" |
| 3376 | " default:\n" |
| 3377 | " param.type_error(\"%s value\", \"%s\");\n" |
| 3378 | " }\n" |
| 3379 | "}\n\n", dispname, kind_str, dispname); |
| 3380 | |
| 3381 | /* get param function */ |
| 3382 | def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); |
| 3383 | src = mputprintf(src, |
| 3384 | "Module_Param* %s::get_param(Module_Param_Name& param_name) const\n" |
| 3385 | "{\n" |
| 3386 | " if (!is_bound()) {\n" |
| 3387 | " return new Module_Param_Unbound();\n" |
| 3388 | " }\n" |
| 3389 | " if (param_name.next_name()) {\n" |
| 3390 | // Haven't reached the end of the module parameter name |
| 3391 | // => the name refers to one of the fields, not to the whole record |
| 3392 | " char* param_field = param_name.get_current_name();\n" |
| 3393 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" |
| 3394 | " TTCN_error(\"Unexpected array index in module parameter reference, \"\n" |
| 3395 | " \"expected a valid field name for %s type `%s'\");\n" |
| 3396 | " }\n" |
| 3397 | " ", name, kind_str, dispname); |
| 3398 | for (i = 0; i < sdef->nElements; i++) { |
| 3399 | src = mputprintf(src, |
| 3400 | "if (strcmp(\"%s\", param_field) == 0) {\n" |
| 3401 | " return %s().get_param(param_name);\n" |
| 3402 | " } else ", |
| 3403 | sdef->elements[i].dispname, sdef->elements[i].name); |
| 3404 | } |
| 3405 | src = mputprintf(src, |
| 3406 | "TTCN_error(\"Field `%%s' not found in %s type `%s'\", param_field);\n" |
| 3407 | " }\n" |
| 3408 | " Module_Param_Assignment_List* mp = new Module_Param_Assignment_List();\n" |
| 3409 | , kind_str, dispname); |
| 3410 | for (i = 0; i < sdef->nElements; i++) { |
| 3411 | src = mputprintf(src, |
| 3412 | " Module_Param* mp_field_%s = field_%s.get_param(param_name);\n" |
| 3413 | " mp_field_%s->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n" |
| 3414 | " mp->add_elem(mp_field_%s);\n" |
| 3415 | , sdef->elements[i].name, sdef->elements[i].name |
| 3416 | , sdef->elements[i].name, sdef->elements[i].dispname |
| 3417 | , sdef->elements[i].name); |
| 3418 | } |
| 3419 | src = mputstr(src, |
| 3420 | " return mp;\n" |
| 3421 | " }\n\n"); |
| 3422 | |
| 3423 | /* set implicit omit function, recursive */ |
| 3424 | def = mputstr(def, " void set_implicit_omit();\n"); |
| 3425 | src = mputprintf(src, "void %s::set_implicit_omit()\n{\n", name); |
| 3426 | for (i = 0; i < sdef->nElements; i++) { |
| 3427 | if (sdef->elements[i].isOptional) { |
| 3428 | src = mputprintf(src, |
| 3429 | "if (!%s().is_bound()) %s() = OMIT_VALUE;\n" |
| 3430 | "else %s().set_implicit_omit();\n", |
| 3431 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); |
| 3432 | } else { |
| 3433 | src = mputprintf(src, |
| 3434 | "if (%s().is_bound()) %s().set_implicit_omit();\n", |
| 3435 | sdef->elements[i].name, sdef->elements[i].name); |
| 3436 | } |
| 3437 | } |
| 3438 | src = mputstr(src, "}\n\n"); |
| 3439 | |
| 3440 | /* text encoder function */ |
| 3441 | def = mputstr(def, " void encode_text(Text_Buf& text_buf) const;\n"); |
| 3442 | src = mputprintf(src, |
| 3443 | "void %s::encode_text(Text_Buf& text_buf) const\n{\n" |
| 3444 | "if (!is_bound()) " |
| 3445 | "TTCN_error(\"Text encoder: Encoding an unbound record/set value of type %s.\");\n" |
| 3446 | , name, dispname); |
| 3447 | for (i = 0; i < sdef->nElements; i++) { |
| 3448 | src = mputprintf(src, "field_%s.encode_text(text_buf);\n", |
| 3449 | sdef->elements[i].name); |
| 3450 | } |
| 3451 | src = mputstr(src, "}\n\n"); |
| 3452 | |
| 3453 | /* text decoder function */ |
| 3454 | def = mputstr(def, " void decode_text(Text_Buf& text_buf);\n"); |
| 3455 | src = mputprintf(src, |
| 3456 | "void %s::decode_text(Text_Buf& text_buf)\n{\n" |
| 3457 | "bound_flag = TRUE;\n", name); |
| 3458 | for (i = 0; i < sdef->nElements; i++) { |
| 3459 | src = mputprintf(src, "field_%s.decode_text(text_buf);\n", |
| 3460 | sdef->elements[i].name); |
| 3461 | } |
| 3462 | src = mputstr(src, "}\n\n"); |
| 3463 | |
| 3464 | /* The common "classname::encode()" and "classname::decode()" functions */ |
| 3465 | if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) |
| 3466 | def_encdec(name, &def, &src, ber_needed, raw_needed, |
| 3467 | text_needed, xer_needed, json_needed, FALSE); |
| 3468 | |
| 3469 | /* BER functions */ |
| 3470 | if(ber_needed) { |
| 3471 | /* BER_encode_TLV() */ |
| 3472 | src=mputprintf |
| 3473 | (src, |
| 3474 | "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td," |
| 3475 | " unsigned p_coding) const\n" |
| 3476 | "{\n" |
| 3477 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" |
| 3478 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" |
| 3479 | " BER_chk_descr(p_td);\n" |
| 3480 | " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n" |
| 3481 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" |
| 3482 | " TTCN_EncDec_ErrorContext ec_1;\n" |
| 3483 | , name |
| 3484 | ); |
| 3485 | for(i=0; i<sdef->nElements; i++) { |
| 3486 | if(!default_as_optional && sdef->elements[i].isDefault) { /* is DEFAULT */ |
| 3487 | src=mputprintf |
| 3488 | (src, |
| 3489 | " if(field_%s!=%s) {\n" |
| 3490 | " ec_1.set_msg(\"%s': \");\n" |
| 3491 | " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_," |
| 3492 | " p_coding));\n" |
| 3493 | " }\n" |
| 3494 | , sdef->elements[i].name, sdef->elements[i].defvalname |
| 3495 | , sdef->elements[i].dispname |
| 3496 | , sdef->elements[i].name, sdef->elements[i].typedescrname |
| 3497 | ); |
| 3498 | } |
| 3499 | else { /* is not DEFAULT */ |
| 3500 | src=mputprintf |
| 3501 | (src, |
| 3502 | " ec_1.set_msg(\"%s': \");\n" |
| 3503 | " new_tlv->add_TLV(field_%s.BER_encode_TLV(%s_descr_," |
| 3504 | " p_coding));\n" |
| 3505 | , sdef->elements[i].dispname |
| 3506 | , sdef->elements[i].name, sdef->elements[i].typedescrname |
| 3507 | ); |
| 3508 | } /* !isDefault */ |
| 3509 | } /* for i */ |
| 3510 | if(sdef->kind==SET) { |
| 3511 | src=mputstr |
| 3512 | (src, |
| 3513 | " if(p_coding==BER_ENCODE_DER)\n" |
| 3514 | " new_tlv->sort_tlvs_tag();\n" |
| 3515 | ); |
| 3516 | } |
| 3517 | src=mputstr |
| 3518 | (src, |
| 3519 | " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n" |
| 3520 | " return new_tlv;\n" |
| 3521 | "}\n" |
| 3522 | "\n" |
| 3523 | ); |
| 3524 | |
| 3525 | /* BER_decode_TLV() */ |
| 3526 | src=mputprintf |
| 3527 | (src, |
| 3528 | "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td," |
| 3529 | " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n" |
| 3530 | "{\n" |
| 3531 | " bound_flag = TRUE;\n" |
| 3532 | " BER_chk_descr(p_td);\n" |
| 3533 | " ASN_BER_TLV_t stripped_tlv;\n" |
| 3534 | " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n" |
| 3535 | " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n" |
| 3536 | " stripped_tlv.chk_constructed_flag(TRUE);\n" |
| 3537 | " size_t V_pos=0;\n" |
| 3538 | " ASN_BER_TLV_t tmp_tlv;\n" |
| 3539 | , name, sdef->dispname |
| 3540 | ); |
| 3541 | |
| 3542 | if(sdef->kind==RECORD) |
| 3543 | { /* SEQUENCE decoding */ |
| 3544 | src=mputstr |
| 3545 | (src, |
| 3546 | " boolean tlv_present=FALSE;\n" |
| 3547 | " {\n" |
| 3548 | " TTCN_EncDec_ErrorContext ec_1(\"Component '\");\n" |
| 3549 | " TTCN_EncDec_ErrorContext ec_2;\n" |
| 3550 | ); |
| 3551 | for(i=0; i<sdef->nElements; i++) { |
| 3552 | src=mputprintf |
| 3553 | (src, |
| 3554 | " ec_2.set_msg(\"%s': \");\n" |
| 3555 | " if(!tlv_present) tlv_present=BER_decode_constdTLV_next" |
| 3556 | "(stripped_tlv, V_pos, L_form, tmp_tlv);\n" |
| 3557 | , sdef->elements[i].dispname |
| 3558 | ); |
| 3559 | if(sdef->elements[i].isDefault) { /* is DEFAULT */ |
| 3560 | src=mputprintf |
| 3561 | (src, |
| 3562 | " if(!tlv_present || !field_%s.BER_decode_isMyMsg(%s_descr_," |
| 3563 | " tmp_tlv))\n" |
| 3564 | " field_%s=%s;\n" |
| 3565 | " else {\n" |
| 3566 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv," |
| 3567 | " L_form);\n" |
| 3568 | " tlv_present=FALSE;\n" |
| 3569 | " }\n" |
| 3570 | , sdef->elements[i].name, sdef->elements[i].typedescrname |
| 3571 | , sdef->elements[i].name, sdef->elements[i].defvalname |
| 3572 | , sdef->elements[i].name, sdef->elements[i].typedescrname |
| 3573 | ); |
| 3574 | } |
| 3575 | else if(sdef->elements[i].isOptional) { /* is OPTIONAL */ |
| 3576 | src=mputprintf |
| 3577 | (src, |
| 3578 | " if(!tlv_present) field_%s=OMIT_VALUE;\n" |
| 3579 | " else {\n" |
| 3580 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n" |
| 3581 | " if(field_%s.ispresent()) tlv_present=FALSE;\n" |
| 3582 | " }\n" |
| 3583 | , sdef->elements[i].name |
| 3584 | , sdef->elements[i].name, sdef->elements[i].typedescrname |
| 3585 | , sdef->elements[i].name |
| 3586 | ); |
| 3587 | } |
| 3588 | else { /* is not DEFAULT OPTIONAL */ |
| 3589 | src=mputprintf |
| 3590 | (src, |
| 3591 | " if(!tlv_present){\n" |
| 3592 | " ec_2.error(TTCN_EncDec::ET_INCOMPL_MSG,\"Invalid or incomplete message was received.\");\n" |
| 3593 | " return FALSE;\n" |
| 3594 | " }\n" |
| 3595 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n" |
| 3596 | " tlv_present=FALSE;\n" |
| 3597 | , sdef->elements[i].name, sdef->elements[i].typedescrname |
| 3598 | ); |
| 3599 | } /* !isDefault */ |
| 3600 | } /* for i */ |
| 3601 | src=mputstr |
| 3602 | (src, |
| 3603 | " }\n" |
| 3604 | " BER_decode_constdTLV_end(stripped_tlv, V_pos, L_form, tmp_tlv," |
| 3605 | " tlv_present);\n" |
| 3606 | ); |
| 3607 | } /* SEQUENCE decoding */ |
| 3608 | else { /* SET decoding */ |
| 3609 | src=mputprintf |
| 3610 | (src, |
| 3611 | " const char *fld_name[%lu]={" |
| 3612 | , (unsigned long) sdef->nElements |
| 3613 | ); |
| 3614 | for(i=0; i<sdef->nElements; i++) |
| 3615 | src=mputprintf |
| 3616 | (src, |
| 3617 | "%s\"%s\"" |
| 3618 | , i?", ":"" |
| 3619 | , sdef->elements[i].dispname |
| 3620 | ); |
| 3621 | /* field indicator: |
| 3622 | * 0x01: value arrived |
| 3623 | * 0x02: is optional / not used :) |
| 3624 | * 0x04: has default / not used :) |
| 3625 | */ |
| 3626 | src=mputprintf |
| 3627 | (src, |
| 3628 | "};\n" |
| 3629 | " unsigned char fld_indctr[%lu]={" |
| 3630 | , (unsigned long) sdef->nElements |
| 3631 | ); |
| 3632 | for(i=0; i<sdef->nElements; i++) |
| 3633 | src=mputprintf |
| 3634 | (src, |
| 3635 | "%s0" |
| 3636 | , i?", ":"" |
| 3637 | ); |
| 3638 | src=mputstr |
| 3639 | (src, |
| 3640 | "};\n" |
| 3641 | " size_t fld_curr;\n" |
| 3642 | " while(BER_decode_constdTLV_next(stripped_tlv, V_pos," |
| 3643 | " L_form, tmp_tlv)) {\n" |
| 3644 | ); |
| 3645 | for(i=0; i<sdef->nElements; i++) |
| 3646 | src=mputprintf |
| 3647 | (src, |
| 3648 | " %sif(field_%s.BER_decode_isMyMsg(%s_descr_, tmp_tlv)) {\n" |
| 3649 | " fld_curr=%lu;\n" |
| 3650 | " TTCN_EncDec_ErrorContext ec_1(\"Component '%%s': \"," |
| 3651 | " fld_name[%lu]);\n" |
| 3652 | " field_%s.BER_decode_TLV(%s_descr_, tmp_tlv, L_form);\n" |
| 3653 | " }\n" |
| 3654 | , i?"else ":"" |
| 3655 | , sdef->elements[i].name, sdef->elements[i].typedescrname |
| 3656 | , (unsigned long) i, (unsigned long) i |
| 3657 | , sdef->elements[i].name, sdef->elements[i].typedescrname |
| 3658 | ); |
| 3659 | src=mputprintf |
| 3660 | (src, |
| 3661 | " else {\n" |
| 3662 | " /* ellipsis or error... */\n" |
| 3663 | " fld_curr=static_cast<size_t>(-1);\n" |
| 3664 | " }\n" |
| 3665 | " if(fld_curr!=static_cast<size_t>(-1)) {\n" |
| 3666 | " if(fld_indctr[fld_curr])\n" |
| 3667 | " ec_0.error(TTCN_EncDec::ET_DEC_DUPFLD, \"Duplicated" |
| 3668 | " value for component '%%s'.\", fld_name[fld_curr]);\n" |
| 3669 | " fld_indctr[fld_curr]=1;\n" |
| 3670 | " }\n" /* if != -1 */ |
| 3671 | " }\n" /* while */ |
| 3672 | " for(fld_curr=0; fld_curr<%lu; fld_curr++) {\n" |
| 3673 | " if(fld_indctr[fld_curr]) continue;\n" |
| 3674 | " switch(fld_curr) {\n" |
| 3675 | , (unsigned long) sdef->nElements |
| 3676 | ); |
| 3677 | for(i=0; i<sdef->nElements; i++) { |
| 3678 | if(sdef->elements[i].isDefault) |
| 3679 | src=mputprintf |
| 3680 | (src, |
| 3681 | " case %lu:\n" |
| 3682 | " field_%s=%s;\n" |
| 3683 | " break;\n" |
| 3684 | , (unsigned long) i |
| 3685 | , sdef->elements[i].name, sdef->elements[i].defvalname |
| 3686 | ); |
| 3687 | else if(sdef->elements[i].isOptional) |
| 3688 | src=mputprintf |
| 3689 | (src, |
| 3690 | " case %lu:\n" |
| 3691 | " field_%s=OMIT_VALUE;\n" |
| 3692 | " break;\n" |
| 3693 | , (unsigned long) i |
| 3694 | , sdef->elements[i].name |
| 3695 | ); |
| 3696 | } /* for i */ |
| 3697 | src=mputstr |
| 3698 | (src, |
| 3699 | " default:\n" |
| 3700 | " ec_0.error(TTCN_EncDec::ET_DEC_MISSFLD, \"Missing" |
| 3701 | " value for component '%s'.\", fld_name[fld_curr]);\n" |
| 3702 | " }\n" /* switch */ |
| 3703 | " }\n" /* for fld_curr */ |
| 3704 | ); |
| 3705 | } /* SET decoding */ |
| 3706 | |
| 3707 | if(sdef->opentype_outermost) { |
| 3708 | src=mputstr |
| 3709 | (src, |
| 3710 | " TTCN_EncDec_ErrorContext ec_1(\"While decoding opentypes: \");\n" |
| 3711 | " TTCN_Type_list p_typelist;\n" |
| 3712 | " BER_decode_opentypes(p_typelist, L_form);\n" |
| 3713 | ); |
| 3714 | } /* if sdef->opentype_outermost */ |
| 3715 | src=mputstr |
| 3716 | (src, |
| 3717 | " return TRUE;\n" |
| 3718 | "}\n" |
| 3719 | "\n" |
| 3720 | ); |
| 3721 | |
| 3722 | if(sdef->has_opentypes) { |
| 3723 | /* BER_decode_opentypes() */ |
| 3724 | def=mputstr |
| 3725 | (def, |
| 3726 | "void BER_decode_opentypes(TTCN_Type_list& p_typelist," |
| 3727 | " unsigned L_form);\n"); |
| 3728 | src=mputprintf |
| 3729 | (src, |
| 3730 | "void %s::BER_decode_opentypes(TTCN_Type_list& p_typelist," |
| 3731 | " unsigned L_form)\n" |
| 3732 | "{\n" |
| 3733 | " bound_flag = TRUE;\n" |
| 3734 | " p_typelist.push(this);\n" |
| 3735 | " TTCN_EncDec_ErrorContext ec_0(\"Component '\");\n" |
| 3736 | " TTCN_EncDec_ErrorContext ec_1;\n" |
| 3737 | , name |
| 3738 | ); |
| 3739 | for(i=0; i<sdef->nElements; i++) { |
| 3740 | src=mputprintf |
| 3741 | (src, |
| 3742 | " ec_1.set_msg(\"%s': \");\n" |
| 3743 | " field_%s.BER_decode_opentypes(p_typelist, L_form);\n" |
| 3744 | , sdef->elements[i].dispname |
| 3745 | , sdef->elements[i].name |
| 3746 | ); |
| 3747 | } /* for i */ |
| 3748 | src=mputstr |
| 3749 | (src, |
| 3750 | " p_typelist.pop();\n" |
| 3751 | "}\n" |
| 3752 | "\n" |
| 3753 | ); |
| 3754 | } /* if sdef->has_opentypes */ |
| 3755 | |
| 3756 | } /* if ber_needed */ |
| 3757 | |
| 3758 | if(text_needed){ |
| 3759 | int man_num=0; |
| 3760 | int opt_number=0; |
| 3761 | int seof=0; |
| 3762 | size_t last_man_index=0; |
| 3763 | for(i=0;i<sdef->nElements;i++){ |
| 3764 | if(sdef->elements[i].isOptional) opt_number++; |
| 3765 | else {man_num++;last_man_index=i+1;} |
| 3766 | if(sdef->elements[i].of_type) seof++; |
| 3767 | } |
| 3768 | |
| 3769 | src=mputprintf(src, |
| 3770 | "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td," |
| 3771 | " TTCN_Buffer& p_buf) const{\n" |
| 3772 | " if (!is_bound()) TTCN_EncDec_ErrorContext::error" |
| 3773 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" |
| 3774 | " bool need_separator=false;\n" |
| 3775 | " int encoded_length=0;\n" |
| 3776 | " if(p_td.text->begin_encode){\n" |
| 3777 | " p_buf.put_cs(*p_td.text->begin_encode);\n" |
| 3778 | " encoded_length+=p_td.text->begin_encode->lengthof();\n" |
| 3779 | " }\n" |
| 3780 | ,name |
| 3781 | ); |
| 3782 | |
| 3783 | for(i=0;i<sdef->nElements;i++){ |
| 3784 | if(sdef->elements[i].isOptional){ |
| 3785 | src=mputprintf(src, |
| 3786 | " if(field_%s.ispresent()){\n" |
| 3787 | ,sdef->elements[i].name |
| 3788 | ); |
| 3789 | } |
| 3790 | src=mputprintf(src, |
| 3791 | " if(need_separator && p_td.text->separator_encode){\n" |
| 3792 | " p_buf.put_cs(*p_td.text->separator_encode);\n" |
| 3793 | " encoded_length+=p_td.text->separator_encode->lengthof();\n" |
| 3794 | " }\n" |
| 3795 | " encoded_length+=field_%s%s.TEXT_encode(%s_descr_,p_buf);\n" |
| 3796 | " need_separator=true;\n" |
| 3797 | ,sdef->elements[i].name |
| 3798 | ,sdef->elements[i].isOptional?"()":"",sdef->elements[i].typedescrname |
| 3799 | ); |
| 3800 | if(sdef->elements[i].isOptional){ |
| 3801 | src=mputstr(src, |
| 3802 | " }\n" |
| 3803 | ); |
| 3804 | } |
| 3805 | } |
| 3806 | |
| 3807 | src=mputstr(src, |
| 3808 | " if(p_td.text->end_encode){\n" |
| 3809 | " p_buf.put_cs(*p_td.text->end_encode);\n" |
| 3810 | " encoded_length+=p_td.text->end_encode->lengthof();\n" |
| 3811 | " }\n" |
| 3812 | " return encoded_length;\n" |
| 3813 | "}\n" |
| 3814 | ); |
| 3815 | |
| 3816 | if(sdef->kind==SET){ /* set decoder start*/ |
| 3817 | src = mputprintf(src, |
| 3818 | "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td," |
| 3819 | " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n" |
| 3820 | " bound_flag = TRUE;\n" |
| 3821 | " int decoded_length=0;\n" |
| 3822 | " int decoded_field_length=0;\n" |
| 3823 | " size_t pos=p_buf.get_pos();\n" |
| 3824 | " boolean sep_found=FALSE;\n" |
| 3825 | " int ml=0;\n" |
| 3826 | " int sep_length=0;\n" |
| 3827 | " int mand_field_num=%d;\n" |
| 3828 | " int opt_field_num=%d;\n" |
| 3829 | " int loop_detector=1;\n" |
| 3830 | " int last_field_num=-1;\n" |
| 3831 | " int field_map[%lu];\n" |
| 3832 | " memset(field_map, 0, sizeof(field_map));\n" |
| 3833 | " if(p_td.text->begin_decode){\n" |
| 3834 | " int tl;\n" |
| 3835 | " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n" |
| 3836 | " if(no_err)return -1;\n" |
| 3837 | " TTCN_EncDec_ErrorContext::error\n" |
| 3838 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" |
| 3839 | " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)" |
| 3840 | ", p_td.name);\n" |
| 3841 | " return 0;\n" |
| 3842 | " }\n" |
| 3843 | " decoded_length+=tl;\n" |
| 3844 | " p_buf.increase_pos(tl);\n" |
| 3845 | " }\n" |
| 3846 | " if(p_td.text->end_decode){\n" |
| 3847 | " limit.add_token(p_td.text->end_decode);\n" |
| 3848 | " ml++;\n" |
| 3849 | " }\n" |
| 3850 | " if(p_td.text->separator_decode){\n" |
| 3851 | " limit.add_token(p_td.text->separator_decode);\n" |
| 3852 | " ml++;\n" |
| 3853 | " }\n" |
| 3854 | ,name,man_num,opt_number,(unsigned long) sdef->nElements |
| 3855 | ); |
| 3856 | |
| 3857 | if(seof){ |
| 3858 | int first=0; |
| 3859 | src=mputstr(src, |
| 3860 | " int has_repeatable=0;\n" |
| 3861 | " if(" |
| 3862 | ); |
| 3863 | for(i=0;i<sdef->nElements;i++){ |
| 3864 | if(sdef->elements[i].of_type){ |
| 3865 | src=mputprintf(src, |
| 3866 | "%s%s_descr_.text->val.parameters->decoding_params.repeatable" |
| 3867 | ,first?" && ":"" |
| 3868 | ,sdef->elements[i].typedescrname |
| 3869 | ); |
| 3870 | first=1; |
| 3871 | } |
| 3872 | } |
| 3873 | src=mputstr(src, |
| 3874 | ") has_repeatable=1;\n" |
| 3875 | ); |
| 3876 | |
| 3877 | } |
| 3878 | for(i=0;i<sdef->nElements;i++){ |
| 3879 | if(sdef->elements[i].isOptional){ |
| 3880 | src=mputprintf(src, |
| 3881 | " field_%s=OMIT_VALUE;\n" |
| 3882 | ,sdef->elements[i].name |
| 3883 | ); |
| 3884 | } |
| 3885 | } |
| 3886 | src = mputprintf(src, |
| 3887 | " while(mand_field_num+opt_field_num%s){\n" |
| 3888 | " loop_detector=1;\n" |
| 3889 | " while(TRUE){\n" |
| 3890 | ,seof?"+has_repeatable":"" |
| 3891 | ); |
| 3892 | |
| 3893 | for(i=0;i<sdef->nElements;i++){ |
| 3894 | if(sdef->elements[i].of_type){ |
| 3895 | src=mputprintf(src, |
| 3896 | " if( (%s_descr_.text->val.parameters->decoding_params.repeatable" |
| 3897 | " && field_map[%lu]<3) || !field_map[%lu]){\n" |
| 3898 | " pos=p_buf.get_pos();\n" |
| 3899 | " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf," |
| 3900 | "limit,true,!field_map[%lu]);\n" |
| 3901 | " if(decoded_field_length<0){\n" |
| 3902 | " p_buf.set_pos(pos);\n" |
| 3903 | ,sdef->elements[i].typedescrname,(unsigned long) i,(unsigned long) i |
| 3904 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" |
| 3905 | ,sdef->elements[i].typedescrname |
| 3906 | ,(unsigned long) i |
| 3907 | ); |
| 3908 | |
| 3909 | if(sdef->elements[i].isOptional){ |
| 3910 | src=mputprintf(src, |
| 3911 | " if(!field_map[%lu]) field_%s=OMIT_VALUE;\n" |
| 3912 | ,(unsigned long) i |
| 3913 | ,sdef->elements[i].name |
| 3914 | ); |
| 3915 | } |
| 3916 | src=mputprintf(src, |
| 3917 | " }else{\n" |
| 3918 | " loop_detector=0;\n" |
| 3919 | " if(!field_map[%lu]) {%s--;field_map[%lu]=1;}\n" |
| 3920 | " else field_map[%lu]=2;\n" |
| 3921 | " last_field_num=%lu;\n" |
| 3922 | " break;\n" |
| 3923 | " }\n" |
| 3924 | " }\n" |
| 3925 | ,(unsigned long) i |
| 3926 | ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num" |
| 3927 | ,(unsigned long) i,(unsigned long) i,(unsigned long) i |
| 3928 | ); |
| 3929 | } else { |
| 3930 | src=mputprintf(src, |
| 3931 | " if(!field_map[%lu]){\n" |
| 3932 | " pos=p_buf.get_pos();\n" |
| 3933 | " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf," |
| 3934 | "limit,true);\n" |
| 3935 | " if(decoded_field_length<0){\n" |
| 3936 | " p_buf.set_pos(pos);\n" |
| 3937 | "%s%s%s" |
| 3938 | " }else{\n" |
| 3939 | " loop_detector=0;\n" |
| 3940 | " field_map[%lu]=1;\n" |
| 3941 | " %s--;\n" |
| 3942 | " last_field_num=%lu;\n" |
| 3943 | " break;\n" |
| 3944 | " }\n" |
| 3945 | " }\n" |
| 3946 | ,(unsigned long) i |
| 3947 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" |
| 3948 | ,sdef->elements[i].typedescrname |
| 3949 | ,sdef->elements[i].isOptional?" field_":"" |
| 3950 | ,sdef->elements[i].isOptional?sdef->elements[i].name:"" |
| 3951 | ,sdef->elements[i].isOptional?"=OMIT_VALUE;\n":"",(unsigned long) i |
| 3952 | ,sdef->elements[i].isOptional?"opt_field_num":"mand_field_num" |
| 3953 | ,(unsigned long) i |
| 3954 | ); |
| 3955 | } |
| 3956 | } |
| 3957 | |
| 3958 | src = mputstr(src, |
| 3959 | " break;\n" |
| 3960 | " }\n" |
| 3961 | " if(loop_detector) break;\n" |
| 3962 | " if(p_td.text->separator_decode){\n" |
| 3963 | " int tl;\n" |
| 3964 | " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n" |
| 3965 | " if(p_td.text->end_decode){\n" |
| 3966 | " int tl;\n" |
| 3967 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" |
| 3968 | " sep_found=FALSE;\n" |
| 3969 | " break;\n" |
| 3970 | " }\n" |
| 3971 | " } else if(limit.has_token(ml)){\n" |
| 3972 | " int tl;\n" |
| 3973 | " if((tl=limit.match(p_buf,ml))==0){\n" |
| 3974 | " sep_found=FALSE;\n" |
| 3975 | " break;\n" |
| 3976 | " }\n" |
| 3977 | " } else break;\n" |
| 3978 | " p_buf.set_pos(pos);\n" |
| 3979 | " decoded_length-=decoded_field_length;\n" |
| 3980 | " field_map[last_field_num]+=2;\n" |
| 3981 | ); |
| 3982 | |
| 3983 | if(opt_number){ |
| 3984 | src=mputstr(src, |
| 3985 | "switch(last_field_num){\n" |
| 3986 | ); |
| 3987 | for(i=0;i<sdef->nElements;i++){ |
| 3988 | if(sdef->elements[i].of_type){ |
| 3989 | if(sdef->elements[i].isOptional){ |
| 3990 | src=mputprintf(src, |
| 3991 | " case %lu:\n" |
| 3992 | " if(field_map[%lu]==3){\n" |
| 3993 | " field_%s=OMIT_VALUE;\n" |
| 3994 | " opt_field_num++;\n" |
| 3995 | " }\n" |
| 3996 | " break;\n" |
| 3997 | ,(unsigned long) i,(unsigned long) i,sdef->elements[i].name |
| 3998 | ); |
| 3999 | } else { |
| 4000 | src=mputprintf(src, |
| 4001 | " case %lu:\n" |
| 4002 | " if(field_map[%lu]==3){\n" |
| 4003 | " mand_field_num++;\n" |
| 4004 | " }\n" |
| 4005 | " break;\n" |
| 4006 | ,(unsigned long) i,(unsigned long) i |
| 4007 | ); |
| 4008 | } |
| 4009 | } else if(sdef->elements[i].isOptional){ |
| 4010 | src=mputprintf(src, |
| 4011 | " case %lu:\n" |
| 4012 | " field_%s=OMIT_VALUE;\n" |
| 4013 | " opt_field_num++;\n" |
| 4014 | " break;\n" |
| 4015 | ,(unsigned long) i,sdef->elements[i].name |
| 4016 | ); |
| 4017 | } |
| 4018 | } |
| 4019 | src=mputstr(src, |
| 4020 | " default:\n" |
| 4021 | " mand_field_num++;\n" |
| 4022 | " break;\n" |
| 4023 | "}\n" |
| 4024 | ); |
| 4025 | } |
| 4026 | |
| 4027 | src = mputprintf(src, |
| 4028 | " } else {\n" |
| 4029 | " sep_length=tl;\n" |
| 4030 | " decoded_length+=tl;\n" |
| 4031 | " p_buf.increase_pos(tl);\n" |
| 4032 | " for(int a=0;a<%lu;a++) if(field_map[a]>2) field_map[a]-=3;\n" |
| 4033 | " sep_found=TRUE;}\n" |
| 4034 | " } else if(p_td.text->end_decode){\n" |
| 4035 | " int tl;\n" |
| 4036 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" |
| 4037 | " decoded_length+=tl;\n" |
| 4038 | " p_buf.increase_pos(tl);\n" |
| 4039 | " limit.remove_tokens(ml);\n" |
| 4040 | " if(mand_field_num) return -1;\n" |
| 4041 | " return decoded_length;\n" |
| 4042 | " }\n" |
| 4043 | " } else if(limit.has_token(ml)){\n" |
| 4044 | " int tl;\n" |
| 4045 | " if((tl=limit.match(p_buf,ml))==0){\n" |
| 4046 | " sep_found=FALSE;\n" |
| 4047 | " break;\n" |
| 4048 | " }\n" |
| 4049 | " }\n" |
| 4050 | " }\n" |
| 4051 | " limit.remove_tokens(ml);\n" |
| 4052 | " if(sep_found){\n" |
| 4053 | " if(mand_field_num){\n" |
| 4054 | " if(no_err)return -1;\n" |
| 4055 | " TTCN_EncDec_ErrorContext::error" |
| 4056 | "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding '%%s': \"," |
| 4057 | "p_td.name);\n" |
| 4058 | " return decoded_length;\n" |
| 4059 | " } else {\n" |
| 4060 | " decoded_length-=sep_length;\n" |
| 4061 | " p_buf.set_pos(p_buf.get_pos()-sep_length);\n" |
| 4062 | " }\n" |
| 4063 | " }\n" |
| 4064 | " if(p_td.text->end_decode){\n" |
| 4065 | " int tl;\n" |
| 4066 | " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" |
| 4067 | " if(no_err)return -1;\n" |
| 4068 | " TTCN_EncDec_ErrorContext::error" |
| 4069 | "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" |
| 4070 | " not found for '%%s': \",(const char*)*(p_td.text->end_decode)" |
| 4071 | ",p_td.name);\n" |
| 4072 | " return decoded_length;\n" |
| 4073 | " }\n" |
| 4074 | " decoded_length+=tl;\n" |
| 4075 | " p_buf.increase_pos(tl);\n" |
| 4076 | " }\n" |
| 4077 | " if(mand_field_num) return -1;\n" |
| 4078 | " return decoded_length;\n" |
| 4079 | "}\n" |
| 4080 | ,(unsigned long) sdef->nElements |
| 4081 | ); |
| 4082 | } else { /* record decoder start */ |
| 4083 | src = mputprintf(src, |
| 4084 | "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td," |
| 4085 | " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n" |
| 4086 | " bound_flag = TRUE;\n" |
| 4087 | " int decoded_length=0;\n" |
| 4088 | " int decoded_field_length=0;\n" |
| 4089 | "%s" |
| 4090 | " boolean sep_found=FALSE;\n" |
| 4091 | " int sep_length=0;\n" |
| 4092 | " int ml=0;\n" |
| 4093 | " if(p_td.text->begin_decode){\n" |
| 4094 | " int tl;\n" |
| 4095 | " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n" |
| 4096 | " if(no_err)return -1;\n" |
| 4097 | " TTCN_EncDec_ErrorContext::error\n" |
| 4098 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" |
| 4099 | " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)" |
| 4100 | ", p_td.name);\n" |
| 4101 | " return 0;\n" |
| 4102 | " }\n" |
| 4103 | " decoded_length+=tl;\n" |
| 4104 | " p_buf.increase_pos(tl);\n" |
| 4105 | " }\n" |
| 4106 | " if(p_td.text->end_decode){\n" |
| 4107 | " limit.add_token(p_td.text->end_decode);\n" |
| 4108 | " ml++;\n" |
| 4109 | " }\n" |
| 4110 | " if(p_td.text->separator_decode){\n" |
| 4111 | " limit.add_token(p_td.text->separator_decode);\n" |
| 4112 | " ml++;\n" |
| 4113 | " }\n" |
| 4114 | ,name,opt_number?" size_t pos=p_buf.get_pos();\n":"" |
| 4115 | ); |
| 4116 | for(i=0;i<sdef->nElements;i++){ |
| 4117 | if(sdef->elements[i].isOptional){ |
| 4118 | src=mputprintf(src, |
| 4119 | " field_%s=OMIT_VALUE;\n" |
| 4120 | ,sdef->elements[i].name |
| 4121 | ); |
| 4122 | } } |
| 4123 | src=mputstr(src, |
| 4124 | " while(TRUE){\n" |
| 4125 | ); |
| 4126 | for(i=0;i<sdef->nElements;i++){ |
| 4127 | if(sdef->elements[i].isOptional){ |
| 4128 | src=mputstr(src, |
| 4129 | " pos=p_buf.get_pos();\n" |
| 4130 | ); |
| 4131 | } |
| 4132 | src=mputprintf(src, |
| 4133 | " decoded_field_length=field_%s%s.TEXT_decode(%s_descr_,p_buf" |
| 4134 | ",limit,TRUE);\n" |
| 4135 | " if(decoded_field_length<0){\n" |
| 4136 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" |
| 4137 | ,sdef->elements[i].typedescrname |
| 4138 | ); |
| 4139 | if(sdef->elements[i].isOptional){ |
| 4140 | src=mputprintf(src, |
| 4141 | " field_%s=OMIT_VALUE;\n" |
| 4142 | " p_buf.set_pos(pos);\n" |
| 4143 | " } else {\n" |
| 4144 | ,sdef->elements[i].name |
| 4145 | ); |
| 4146 | } else { |
| 4147 | src=mputprintf(src, |
| 4148 | " limit.remove_tokens(ml);\n" |
| 4149 | " if(no_err)return -1;\n" |
| 4150 | " TTCN_EncDec_ErrorContext::error" |
| 4151 | "(TTCN_EncDec::ET_TOKEN_ERR, \"Error during decoding " |
| 4152 | "field '%s' for '%%s': \", p_td.name);\n" |
| 4153 | " return decoded_length;\n" |
| 4154 | " } else {\n" |
| 4155 | ,sdef->elements[i].name |
| 4156 | ); |
| 4157 | } |
| 4158 | src=mputstr(src, |
| 4159 | " decoded_length+=decoded_field_length;\n" |
| 4160 | ); |
| 4161 | if(last_man_index>(i+1)){ |
| 4162 | src=mputstr(src, |
| 4163 | " if(p_td.text->separator_decode){\n" |
| 4164 | " int tl;\n" |
| 4165 | " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n" |
| 4166 | ); |
| 4167 | |
| 4168 | if(sdef->elements[i].isOptional){ |
| 4169 | src=mputprintf(src, |
| 4170 | " field_%s=OMIT_VALUE;\n" |
| 4171 | " p_buf.set_pos(pos);\n" |
| 4172 | " decoded_length-=decoded_field_length;\n" |
| 4173 | ,sdef->elements[i].name |
| 4174 | ); |
| 4175 | } else { |
| 4176 | src=mputstr(src, |
| 4177 | " limit.remove_tokens(ml);\n" |
| 4178 | " if(no_err)return -1;\n" |
| 4179 | " TTCN_EncDec_ErrorContext::error" |
| 4180 | "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'" |
| 4181 | " not found for '%s': \",(const char*)*(p_td.text->" |
| 4182 | "separator_decode),p_td.name);\n" |
| 4183 | " return decoded_length;\n" |
| 4184 | ); |
| 4185 | } |
| 4186 | |
| 4187 | src=mputstr(src, |
| 4188 | " } else {\n" |
| 4189 | " decoded_length+=tl;\n" |
| 4190 | " p_buf.increase_pos(tl);\n" |
| 4191 | " sep_length=tl;\n" |
| 4192 | " sep_found=TRUE;}\n" |
| 4193 | " } else sep_found=FALSE;\n" |
| 4194 | ); |
| 4195 | } else if(i==(sdef->nElements-1)){ |
| 4196 | src=mputstr(src, |
| 4197 | " sep_found=FALSE;\n" |
| 4198 | ); |
| 4199 | } else { |
| 4200 | src=mputstr(src, |
| 4201 | " if(p_td.text->separator_decode){\n" |
| 4202 | " int tl;\n" |
| 4203 | " if((tl=p_td.text->separator_decode->match_begin(p_buf))<0){\n" |
| 4204 | ); |
| 4205 | if(sdef->elements[i].isOptional){ |
| 4206 | src=mputprintf(src, |
| 4207 | " if(p_td.text->end_decode){\n" |
| 4208 | " int tl;\n" |
| 4209 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" |
| 4210 | " decoded_length+=tl;\n" |
| 4211 | " p_buf.increase_pos(tl);\n" |
| 4212 | " limit.remove_tokens(ml);\n" |
| 4213 | " return decoded_length;\n" |
| 4214 | " }\n" |
| 4215 | " } else if(limit.has_token(ml)){\n" |
| 4216 | " if((tl=limit.match(p_buf,ml))==0){\n" |
| 4217 | " sep_found=FALSE;\n" |
| 4218 | " break;\n" |
| 4219 | " }\n" |
| 4220 | " } else break;\n" |
| 4221 | " field_%s=OMIT_VALUE;\n" |
| 4222 | " p_buf.set_pos(pos);\n" |
| 4223 | " decoded_length-=decoded_field_length;\n" |
| 4224 | ,sdef->elements[i].name |
| 4225 | ); |
| 4226 | } else { |
| 4227 | src=mputstr(src, |
| 4228 | " sep_found=FALSE;\n" |
| 4229 | " break;\n" |
| 4230 | ); |
| 4231 | } |
| 4232 | src=mputstr(src, |
| 4233 | " } else {\n" |
| 4234 | " decoded_length+=tl;\n" |
| 4235 | " p_buf.increase_pos(tl);\n" |
| 4236 | " sep_length=tl;\n" |
| 4237 | " sep_found=TRUE;}\n" |
| 4238 | " } else {\n" |
| 4239 | " sep_found=FALSE;\n" |
| 4240 | " if(p_td.text->end_decode){\n" |
| 4241 | " int tl;\n" |
| 4242 | " if((tl=p_td.text->end_decode->match_begin(p_buf))!=-1){\n" |
| 4243 | " decoded_length+=tl;\n" |
| 4244 | " p_buf.increase_pos(tl);\n" |
| 4245 | " limit.remove_tokens(ml);\n" |
| 4246 | " return decoded_length;\n" |
| 4247 | " }\n" |
| 4248 | " } else if(limit.has_token(ml)){\n" |
| 4249 | " int tl;\n" |
| 4250 | " if((tl=limit.match(p_buf,ml))==0){\n" |
| 4251 | " sep_found=FALSE;\n" |
| 4252 | " break;\n" |
| 4253 | " }\n" |
| 4254 | " }\n" |
| 4255 | " }\n" |
| 4256 | ); |
| 4257 | } |
| 4258 | src=mputstr(src, |
| 4259 | " }\n" |
| 4260 | ); |
| 4261 | } |
| 4262 | |
| 4263 | src = mputstr(src, |
| 4264 | " break;\n" |
| 4265 | " }\n" |
| 4266 | " limit.remove_tokens(ml);\n" |
| 4267 | " if(sep_found){\n" |
| 4268 | " p_buf.set_pos(p_buf.get_pos()-sep_length);\n" |
| 4269 | " decoded_length-=sep_length;\n" |
| 4270 | " }\n" |
| 4271 | " if(p_td.text->end_decode){\n" |
| 4272 | " int tl;\n" |
| 4273 | " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" |
| 4274 | " if(no_err)return -1;\n" |
| 4275 | " TTCN_EncDec_ErrorContext::error" |
| 4276 | "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'" |
| 4277 | " not found for '%s': \",(const char*)*(p_td.text->end_decode)" |
| 4278 | ",p_td.name);\n" |
| 4279 | " return decoded_length;\n" |
| 4280 | " }\n" |
| 4281 | " decoded_length+=tl;\n" |
| 4282 | " p_buf.increase_pos(tl);\n" |
| 4283 | " }\n" |
| 4284 | " return decoded_length;\n" |
| 4285 | "}\n" |
| 4286 | ); |
| 4287 | } |
| 4288 | } /* text_needed */ |
| 4289 | |
| 4290 | /* RAW functions */ |
| 4291 | if(raw_needed){ |
| 4292 | struct raw_option_struct *raw_options; |
| 4293 | boolean haslengthto, haspointer, hascrosstag, has_ext_bit; |
| 4294 | raw_options = (struct raw_option_struct*) |
| 4295 | Malloc(sdef->nElements * sizeof(*raw_options)); |
| 4296 | |
| 4297 | set_raw_options(sdef, raw_options, &haslengthto, |
| 4298 | &haspointer, &hascrosstag, &has_ext_bit); |
| 4299 | |
| 4300 | src = generate_raw_coding(src, sdef, raw_options, haspointer, hascrosstag, |
| 4301 | has_ext_bit); |
| 4302 | |
| 4303 | for (i = 0; i < sdef->nElements; i++) { |
| 4304 | Free(raw_options[i].lengthoffield); |
| 4305 | Free(raw_options[i].dependent_fields); |
| 4306 | } |
| 4307 | Free(raw_options); |
| 4308 | } /* if raw_needed */ |
| 4309 | |
| 4310 | if (xer_needed) gen_xer(sdef, &def, &src); |
| 4311 | |
| 4312 | if (json_needed) { |
| 4313 | // JSON encode, RT1 |
| 4314 | src = mputprintf(src, |
| 4315 | "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n" |
| 4316 | "{\n" |
| 4317 | " if (!is_bound()) {\n" |
| 4318 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" |
| 4319 | " \"Encoding an unbound value of type %s.\");\n" |
| 4320 | " return -1;\n" |
| 4321 | " }\n\n" |
| 4322 | " int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);\n\n" |
| 4323 | , name, dispname); |
| 4324 | for (i = 0; i < sdef->nElements; ++i) { |
| 4325 | if (sdef->elements[i].isOptional && !sdef->elements[i].jsonOmitAsNull && |
| 4326 | !sdef->elements[i].jsonMetainfoUnbound) { |
| 4327 | src = mputprintf(src, |
| 4328 | " if (field_%s.is_present())\n" |
| 4329 | , sdef->elements[i].name); |
| 4330 | } |
| 4331 | src = mputprintf(src, |
| 4332 | " {\n" |
| 4333 | " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"%s\");\n " |
| 4334 | , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname); |
| 4335 | if (sdef->elements[i].jsonMetainfoUnbound) { |
| 4336 | src = mputprintf(src, |
| 4337 | "if (!field_%s.is_bound()) {\n" |
| 4338 | " enc_len += p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL);\n" |
| 4339 | " enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, \"metainfo %s\");\n" |
| 4340 | " enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, \"\\\"unbound\\\"\");\n" |
| 4341 | " }\n" |
| 4342 | " else " |
| 4343 | , sdef->elements[i].name |
| 4344 | , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname); |
| 4345 | } |
| 4346 | src = mputprintf(src, |
| 4347 | "enc_len += field_%s.JSON_encode(%s_descr_, p_tok);\n" |
| 4348 | " }\n\n" |
| 4349 | , sdef->elements[i].name, sdef->elements[i].typedescrname); |
| 4350 | } |
| 4351 | src = mputstr(src, |
| 4352 | " enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n" |
| 4353 | " return enc_len;\n" |
| 4354 | "}\n\n"); |
| 4355 | |
| 4356 | // JSON decode, RT1 |
| 4357 | src = mputprintf(src, |
| 4358 | "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n" |
| 4359 | "{\n" |
| 4360 | " json_token_t j_token = JSON_TOKEN_NONE;\n" |
| 4361 | " int dec_len = p_tok.get_next_token(&j_token, NULL, NULL);\n" |
| 4362 | " if (JSON_TOKEN_ERROR == j_token) {\n" |
| 4363 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n" |
| 4364 | " return JSON_ERROR_FATAL;\n" |
| 4365 | " }\n" |
| 4366 | " else if (JSON_TOKEN_OBJECT_START != j_token) {\n" |
| 4367 | " return JSON_ERROR_INVALID_TOKEN;\n" |
| 4368 | " }\n" |
| 4369 | " bound_flag = TRUE;\n\n" |
| 4370 | , name); |
| 4371 | boolean has_metainfo_enabled = FALSE; |
| 4372 | for (i = 0; i < sdef->nElements; ++i) { |
| 4373 | if (sdef->elements[i].jsonMetainfoUnbound) { |
| 4374 | // initialize meta info states |
| 4375 | src = mputprintf(src, |
| 4376 | " int metainfo_%s = JSON_METAINFO_NONE;\n" |
| 4377 | , sdef->elements[i].name); |
| 4378 | has_metainfo_enabled = TRUE; |
| 4379 | } |
| 4380 | } |
| 4381 | src = mputstr(src, |
| 4382 | // Read name - value token pairs until we reach some other token |
| 4383 | "\n while (true) {\n" |
| 4384 | " char* fld_name = 0;\n" |
| 4385 | " size_t name_len = 0;\n" |
| 4386 | " size_t buf_pos = p_tok.get_buf_pos();\n" |
| 4387 | " dec_len += p_tok.get_next_token(&j_token, &fld_name, &name_len);\n" |
| 4388 | " if (JSON_TOKEN_ERROR == j_token) {\n" |
| 4389 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_NAME_TOKEN_ERROR);\n" |
| 4390 | " return JSON_ERROR_FATAL;\n" |
| 4391 | " }\n" |
| 4392 | // undo the last action on the buffer |
| 4393 | " else if (JSON_TOKEN_NAME != j_token) {\n" |
| 4394 | " p_tok.set_buf_pos(buf_pos);\n" |
| 4395 | " break;\n" |
| 4396 | " }\n" |
| 4397 | " else {\n "); |
| 4398 | if (has_metainfo_enabled) { |
| 4399 | // check for meta info |
| 4400 | src = mputstr(src, |
| 4401 | "boolean is_metainfo = FALSE;\n" |
| 4402 | " if (name_len > 9 && 0 == strncmp(fld_name, \"metainfo \", 9)) {\n" |
| 4403 | " fld_name += 9;\n" |
| 4404 | " name_len -= 9;\n" |
| 4405 | " is_metainfo = TRUE;\n" |
| 4406 | " }\n "); |
| 4407 | } |
| 4408 | for (i = 0; i < sdef->nElements; ++i) { |
| 4409 | src = mputprintf(src, |
| 4410 | // check field name |
| 4411 | "if (%d == name_len && 0 == strncmp(fld_name, \"%s\", name_len)) {\n" |
| 4412 | , (int)strlen(sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname) |
| 4413 | , sdef->elements[i].jsonAlias ? sdef->elements[i].jsonAlias : sdef->elements[i].dispname); |
| 4414 | if (has_metainfo_enabled) { |
| 4415 | src = mputstr(src, " if (is_metainfo) {\n"); |
| 4416 | if (sdef->elements[i].jsonMetainfoUnbound) { |
| 4417 | src = mputprintf(src, |
| 4418 | // check meta info |
| 4419 | " char* info_value = 0;\n" |
| 4420 | " size_t info_len = 0;\n" |
| 4421 | " dec_len += p_tok.get_next_token(&j_token, &info_value, &info_len);\n" |
| 4422 | " if (JSON_TOKEN_STRING == j_token && 9 == info_len &&\n" |
| 4423 | " 0 == strncmp(info_value, \"\\\"unbound\\\"\", 9)) {\n" |
| 4424 | " metainfo_%s = JSON_METAINFO_UNBOUND;\n" |
| 4425 | " }\n" |
| 4426 | " else {\n" |
| 4427 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_VALUE_ERROR, \"%s\");\n" |
| 4428 | " return JSON_ERROR_FATAL;\n" |
| 4429 | " }\n" |
| 4430 | , sdef->elements[i].name, sdef->elements[i].dispname); |
| 4431 | } |
| 4432 | else { |
| 4433 | src = mputprintf(src, |
| 4434 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_NOT_APPLICABLE, \"%s\");\n" |
| 4435 | " return JSON_ERROR_FATAL;\n" |
| 4436 | , sdef->elements[i].dispname); |
| 4437 | } |
| 4438 | src = mputstr(src, |
| 4439 | " }\n" |
| 4440 | " else {\n"); |
| 4441 | if (sdef->elements[i].jsonMetainfoUnbound) { |
| 4442 | src = mputstr(src, " buf_pos = p_tok.get_buf_pos();\n"); |
| 4443 | } |
| 4444 | } |
| 4445 | src = mputprintf(src, |
| 4446 | " int ret_val = field_%s.JSON_decode(%s_descr_, p_tok, p_silent);\n" |
| 4447 | " if (0 > ret_val) {\n" |
| 4448 | " if (JSON_ERROR_INVALID_TOKEN == ret_val) {\n" |
| 4449 | , sdef->elements[i].name, sdef->elements[i].typedescrname); |
| 4450 | if (sdef->elements[i].jsonMetainfoUnbound) { |
| 4451 | src = mputprintf(src, |
| 4452 | // undo the last action on the buffer, check if the invalid token was a null token |
| 4453 | " p_tok.set_buf_pos(buf_pos);\n" |
| 4454 | " p_tok.get_next_token(&j_token, NULL, NULL);\n" |
| 4455 | " if (JSON_TOKEN_LITERAL_NULL == j_token) {\n" |
| 4456 | " if (JSON_METAINFO_NONE == metainfo_%s) {\n" |
| 4457 | // delay reporting an error for now, there might be meta info later |
| 4458 | " metainfo_%s = JSON_METAINFO_NEEDED;\n" |
| 4459 | " continue;\n" |
| 4460 | " }\n" |
| 4461 | " else if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n" |
| 4462 | // meta info already found |
| 4463 | " continue;\n" |
| 4464 | " }\n" |
| 4465 | " }\n" |
| 4466 | , sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); |
| 4467 | } |
| 4468 | src = mputprintf(src, |
| 4469 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n" |
| 4470 | " }\n" |
| 4471 | " return JSON_ERROR_FATAL;\n" |
| 4472 | " }\n" |
| 4473 | " dec_len += ret_val;\n" |
| 4474 | , sdef->elements[i].dispname); |
| 4475 | if (has_metainfo_enabled) { |
| 4476 | src = mputstr(src, " }\n"); |
| 4477 | } |
| 4478 | src = mputstr(src, |
| 4479 | " }\n" |
| 4480 | " else "); |
| 4481 | } |
| 4482 | src = mputprintf(src, |
| 4483 | "{\n" |
| 4484 | // invalid field name |
| 4485 | " char* fld_name2 = mcopystrn(fld_name, name_len);\n" |
| 4486 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, %sJSON_DEC_INVALID_NAME_ERROR, fld_name2);\n" |
| 4487 | // if this is set to a warning, skip the value of the field |
| 4488 | " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n" |
| 4489 | " if (JSON_TOKEN_NUMBER != j_token && JSON_TOKEN_STRING != j_token &&\n" |
| 4490 | " JSON_TOKEN_LITERAL_TRUE != j_token && JSON_TOKEN_LITERAL_FALSE != j_token &&\n" |
| 4491 | " JSON_TOKEN_LITERAL_NULL != j_token) {\n" |
| 4492 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name2);\n" |
| 4493 | " Free(fld_name2);\n" |
| 4494 | " return JSON_ERROR_FATAL;\n" |
| 4495 | " }\n" |
| 4496 | " Free(fld_name2);\n" |
| 4497 | " }\n" |
| 4498 | " }\n" |
| 4499 | " }\n\n" |
| 4500 | " dec_len += p_tok.get_next_token(&j_token, NULL, NULL);\n" |
| 4501 | " if (JSON_TOKEN_OBJECT_END != j_token) {\n" |
| 4502 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_OBJECT_END_TOKEN_ERROR, \"\");\n" |
| 4503 | " return JSON_ERROR_FATAL;\n" |
| 4504 | " }\n\n " |
| 4505 | , has_metainfo_enabled ? "is_metainfo ?\n JSON_DEC_METAINFO_NAME_ERROR : " : ""); |
| 4506 | // Check if every field has been set and handle meta info |
| 4507 | for (i = 0; i < sdef->nElements; ++i) { |
| 4508 | if (sdef->elements[i].jsonMetainfoUnbound) { |
| 4509 | src = mputprintf(src, |
| 4510 | "if (JSON_METAINFO_UNBOUND == metainfo_%s) {\n" |
| 4511 | " field_%s.clean_up();\n" |
| 4512 | " }\n" |
| 4513 | " else if (JSON_METAINFO_NEEDED == metainfo_%s) {\n" |
| 4514 | // no meta info was found for this field, report the delayed error |
| 4515 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, \"%s\");\n" |
| 4516 | " }\n" |
| 4517 | " else " |
| 4518 | , sdef->elements[i].name, sdef->elements[i].name |
| 4519 | , sdef->elements[i].name, sdef->elements[i].dispname); |
| 4520 | } |
| 4521 | src = mputprintf(src, |
| 4522 | "if (!field_%s.is_bound()) {\n" |
| 4523 | , sdef->elements[i].name); |
| 4524 | if (sdef->elements[i].jsonDefaultValue) { |
| 4525 | src = mputprintf(src, |
| 4526 | " field_%s.JSON_decode(%s_descr_, DUMMY_BUFFER, p_silent);\n" |
| 4527 | , sdef->elements[i].name, sdef->elements[i].typedescrname); |
| 4528 | } |
| 4529 | else if (sdef->elements[i].isOptional) { |
| 4530 | src = mputprintf(src, |
| 4531 | " field_%s = OMIT_VALUE;\n" |
| 4532 | , sdef->elements[i].name); |
| 4533 | } else { |
| 4534 | src = mputprintf(src, |
| 4535 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_MISSING_FIELD_ERROR, \"%s\");\n" |
| 4536 | " return JSON_ERROR_FATAL;\n" |
| 4537 | , sdef->elements[i].dispname); |
| 4538 | } |
| 4539 | src = mputstr(src, |
| 4540 | " }\n"); |
| 4541 | } |
| 4542 | src = mputstr(src, |
| 4543 | "\n return dec_len;\n" |
| 4544 | "}\n\n"); |
| 4545 | } |
| 4546 | |
| 4547 | /* end of class definition */ |
| 4548 | def = mputstr(def, "};\n\n"); |
| 4549 | |
| 4550 | output->header.class_defs = mputstr(output->header.class_defs, def); |
| 4551 | Free(def); |
| 4552 | |
| 4553 | output->source.methods = mputstr(output->source.methods, src); |
| 4554 | Free(src); |
| 4555 | } |
| 4556 | |
| 4557 | |
| 4558 | static char *genRawFieldDecodeLimit(char *src, const struct_def *sdef, |
| 4559 | int i, const struct raw_option_struct *raw_options) |
| 4560 | { |
| 4561 | /* number of arguments passed to min_of_ints() */ |
| 4562 | int nof_args = 1; |
| 4563 | int j; |
| 4564 | for (j = 0; j < raw_options[i].lengthof; j++) { |
| 4565 | int field_index = raw_options[i].lengthoffield[j]; |
| 4566 | if (i > field_index && sdef->elements[field_index].raw.unit!=-1) |
| 4567 | nof_args++; |
| 4568 | } |
| 4569 | if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[ |
| 4570 | raw_options[i].extbitgroup-1].ext_bit != XDEFNO) nof_args++; |
| 4571 | if (nof_args > 1) { |
| 4572 | src = mputprintf(src, "min_of_ints(%d, limit", nof_args); |
| 4573 | for (j = 0; j < raw_options[i].lengthof; j++) { |
| 4574 | int field_index = raw_options[i].lengthoffield[j]; |
| 4575 | if (i > field_index && sdef->elements[field_index].raw.unit != -1) |
| 4576 | src = mputprintf(src, ", value_of_length_field%d", field_index); |
| 4577 | } |
| 4578 | if (raw_options[i].extbitgroup && sdef->raw.ext_bit_groups[ |
| 4579 | raw_options[i].extbitgroup-1].ext_bit != XDEFNO) |
| 4580 | src = mputstr(src, ", group_limit"); |
| 4581 | src = mputc(src, ')'); |
| 4582 | } else { |
| 4583 | src = mputstr(src, "limit"); |
| 4584 | } |
| 4585 | return src; |
| 4586 | } |
| 4587 | |
| 4588 | static char *genRawDecodeRecordField(char *src, const struct_def *sdef, |
| 4589 | int i, const struct raw_option_struct *raw_options, boolean delayed_decode, |
| 4590 | int *prev_ext_group) |
| 4591 | { |
| 4592 | int a; |
| 4593 | if(raw_options[i].ptrbase) |
| 4594 | src=mputprintf(src, |
| 4595 | " start_pos_of_field%d=p_buf.get_pos_bit();\n" |
| 4596 | ,i |
| 4597 | ); |
| 4598 | if (*prev_ext_group != raw_options[i].extbitgroup) { |
| 4599 | *prev_ext_group = raw_options[i].extbitgroup; |
| 4600 | if(prev_ext_group && |
| 4601 | sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){ |
| 4602 | if(raw_options[i].pointerof) /* pointed field */ |
| 4603 | src=mputprintf(src, |
| 4604 | " {size_t old_pos=p_buf.get_pos_bit();\n" |
| 4605 | " if(start_of_field%d!=-1 && start_pos_of_field%d!=-1){\n" |
| 4606 | " start_of_field%d=start_pos_of_field%d" |
| 4607 | "+(int)field_%s%s*%d+%d;\n" |
| 4608 | " p_buf.set_pos_bit(start_of_field%d);\n" |
| 4609 | " limit=end_of_available_data-start_of_field%d;\n" |
| 4610 | ,i |
| 4611 | ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase |
| 4612 | ,i |
| 4613 | ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase |
| 4614 | ,sdef->elements[raw_options[i].pointerof-1].name |
| 4615 | ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":"" |
| 4616 | ,sdef->elements[raw_options[i].pointerof-1].raw.unit |
| 4617 | ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset |
| 4618 | ,i,i |
| 4619 | ); |
| 4620 | src=mputprintf(src, |
| 4621 | " {\n" |
| 4622 | " cbyte* data=p_buf.get_read_data();\n" |
| 4623 | " int count=1;\n" |
| 4624 | " int rot=local_top_order==ORDER_LSB?0:7;\n" |
| 4625 | " while(((data[count-1]>>rot)&0x01)==%d && count*8<" |
| 4626 | "(int)limit) count++;\n" |
| 4627 | " if(limit) group_limit=count*8;\n" |
| 4628 | " }\n" |
| 4629 | ,sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit== |
| 4630 | XDEFYES?0:1 |
| 4631 | ); |
| 4632 | if(raw_options[i].pointerof) /* pointed field */ |
| 4633 | src=mputstr(src, |
| 4634 | " } else group_limit=0;\n" |
| 4635 | " p_buf.set_pos_bit(old_pos);\n" |
| 4636 | " limit=end_of_available_data-old_pos;}\n" |
| 4637 | ); |
| 4638 | } |
| 4639 | } |
| 4640 | if(sdef->elements[i].hasRaw && /* check the crosstag */ |
| 4641 | sdef->elements[i].raw.crosstaglist.nElements){ |
| 4642 | /* field index of the otherwise rule */ |
| 4643 | int other = -1; |
| 4644 | boolean first_value = TRUE; |
| 4645 | int j; |
| 4646 | for (j = 0; j < sdef->elements[i].raw.crosstaglist.nElements; j++) { |
| 4647 | rawAST_coding_taglist* cur_choice = |
| 4648 | sdef->elements[i].raw.crosstaglist.list + j; |
| 4649 | if (cur_choice->nElements > 0) { |
| 4650 | /* this is a normal rule */ |
| 4651 | if (first_value) { |
| 4652 | src = mputstr(src, " if ("); |
| 4653 | first_value = FALSE; |
| 4654 | } else src = mputstr(src, " else if ("); |
| 4655 | src = genRawFieldChecker(src, cur_choice, TRUE); |
| 4656 | /* set selected_field in the if's body */ |
| 4657 | src = mputprintf(src, ") selected_field = %d;\n", |
| 4658 | cur_choice->fieldnum); |
| 4659 | } else { |
| 4660 | /* this is an otherwise rule */ |
| 4661 | other = cur_choice->fieldnum; |
| 4662 | } |
| 4663 | } |
| 4664 | /* set selected_field to the field index of the otherwise rule or -1 */ |
| 4665 | src = mputprintf(src, " else selected_field = %d;\n", other); |
| 4666 | } |
| 4667 | /* check the presence of optional field*/ |
| 4668 | if(sdef->elements[i].isOptional){ |
| 4669 | /* check if enough bits to decode the field*/ |
| 4670 | src = mputstr(src, " if (limit > 0"); |
| 4671 | for (a = 0; a < raw_options[i].lengthof; a++){ |
| 4672 | int field_index = raw_options[i].lengthoffield[a]; |
| 4673 | if (i > field_index) src = mputprintf(src, |
| 4674 | " && value_of_length_field%d > 0", field_index); |
| 4675 | } |
| 4676 | if (raw_options[i].extbitgroup && |
| 4677 | sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){ |
| 4678 | src = mputstr(src, " && group_limit > 0"); |
| 4679 | } |
| 4680 | if(raw_options[i].pointerof){ /* valid pointer?*/ |
| 4681 | src=mputprintf(src, |
| 4682 | " && start_of_field%d!=-1 && start_pos_of_field%d!=-1" |
| 4683 | ,i,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase |
| 4684 | ); |
| 4685 | } |
| 4686 | if(sdef->elements[i].hasRaw && |
| 4687 | sdef->elements[i].raw.presence.nElements) |
| 4688 | { |
| 4689 | src = mputstr(src, " && "); |
| 4690 | if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, '('); |
| 4691 | src = genRawFieldChecker(src, &sdef->elements[i].raw.presence, TRUE); |
| 4692 | if (sdef->elements[i].raw.presence.nElements > 1) src = mputc(src, ')'); |
| 4693 | } |
| 4694 | if(sdef->elements[i].hasRaw && |
| 4695 | sdef->elements[i].raw.crosstaglist.nElements) |
| 4696 | { |
| 4697 | src=mputstr(src, |
| 4698 | "&& selected_field!=-1" |
| 4699 | ); |
| 4700 | } |
| 4701 | src=mputstr(src, |
| 4702 | "){\n" |
| 4703 | ); |
| 4704 | } |
| 4705 | if(raw_options[i].pointerof){ /* pointed field */ |
| 4706 | src=mputprintf(src, |
| 4707 | " start_of_field%d=start_pos_of_field%d" |
| 4708 | "+(int)field_%s%s*%d+%d;\n" |
| 4709 | ,i |
| 4710 | ,sdef->elements[raw_options[i].pointerof-1].raw.pointerbase |
| 4711 | ,sdef->elements[raw_options[i].pointerof-1].name |
| 4712 | ,sdef->elements[raw_options[i].pointerof-1].isOptional?"()":"" |
| 4713 | ,sdef->elements[raw_options[i].pointerof-1].raw.unit |
| 4714 | ,sdef->elements[raw_options[i].pointerof-1].raw.ptroffset |
| 4715 | ); |
| 4716 | src=mputprintf(src, |
| 4717 | " p_buf.set_pos_bit(start_of_field%d);\n" |
| 4718 | " limit=end_of_available_data-start_of_field%d;\n" |
| 4719 | ,i,i |
| 4720 | ); |
| 4721 | } |
| 4722 | /* decoding of normal field */ |
| 4723 | if (sdef->elements[i].isOptional) src = mputstr(src, |
| 4724 | " size_t fl_start_pos = p_buf.get_pos_bit();\n"); |
| 4725 | src = mputprintf(src, |
| 4726 | " decoded_field_length = field_%s%s.RAW_decode(%s_descr_, p_buf, ", |
| 4727 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", |
| 4728 | sdef->elements[i].typedescrname); |
| 4729 | if (delayed_decode) { |
| 4730 | /* the fixed field length is used as limit in case of delayed decoding */ |
| 4731 | src = mputprintf(src, "%d", sdef->elements[i].raw.length); |
| 4732 | } else { |
| 4733 | src = genRawFieldDecodeLimit(src, sdef, i, raw_options); |
| 4734 | } |
| 4735 | src = mputprintf(src, ", local_top_order, %s", |
| 4736 | sdef->elements[i].isOptional ? "TRUE" : "no_err"); |
| 4737 | if (sdef->elements[i].hasRaw && |
| 4738 | sdef->elements[i].raw.crosstaglist.nElements > 0) |
| 4739 | src = mputstr(src, ", selected_field"); |
| 4740 | for (a = 0; a < raw_options[i].lengthof; a++) { |
| 4741 | int field_index = raw_options[i].lengthoffield[a]; |
| 4742 | /* number of elements in 'record of' or 'set of' */ |
| 4743 | if (sdef->elements[field_index].raw.unit == -1) { |
| 4744 | src = mputprintf(src, ", value_of_length_field%d", field_index); |
| 4745 | break; |
| 4746 | } |
| 4747 | } |
| 4748 | src = mputstr(src, ");\n"); |
| 4749 | if (delayed_decode) { |
| 4750 | src = mputprintf(src, " if (decoded_field_length != %d) return -1;\n", |
| 4751 | sdef->elements[i].raw.length); |
| 4752 | } else if (sdef->elements[i].isOptional) { |
| 4753 | src = mputprintf(src, " if (decoded_field_length < 1) {\n" |
| 4754 | " field_%s = OMIT_VALUE;\n" /* transform errors into omit */ |
| 4755 | " p_buf.set_pos_bit(fl_start_pos);\n" |
| 4756 | " } else {\n", sdef->elements[i].name); |
| 4757 | } else { |
| 4758 | src = mputstr(src, " if (decoded_field_length < 0) return decoded_field_length;\n"); |
| 4759 | } |
| 4760 | if(raw_options[i].tag_type && sdef->raw.taglist.list[raw_options[i].tag_type-1].nElements){ |
| 4761 | rawAST_coding_taglist* cur_choice= |
| 4762 | sdef->raw.taglist.list+raw_options[i].tag_type-1; |
| 4763 | src=mputstr(src, |
| 4764 | " if("); |
| 4765 | src=genRawFieldChecker(src,cur_choice,FALSE); |
| 4766 | src=mputstr(src, |
| 4767 | ")"); |
| 4768 | if(sdef->elements[i].isOptional){ |
| 4769 | src=mputprintf(src, |
| 4770 | "{\n field_%s=OMIT_VALUE;\n" |
| 4771 | " p_buf.set_pos_bit(fl_start_pos);\n }\n" |
| 4772 | " else {\n" |
| 4773 | ,sdef->elements[i].name |
| 4774 | ); |
| 4775 | }else src=mputstr(src, " return -1;\n"); |
| 4776 | } |
| 4777 | if (!delayed_decode) { |
| 4778 | src=mputstr(src, |
| 4779 | " decoded_length+=decoded_field_length;\n" |
| 4780 | " limit-=decoded_field_length;\n" |
| 4781 | " last_decoded_pos=bigger(last_decoded_pos, p_buf.get_pos_bit());\n" |
| 4782 | ); |
| 4783 | } |
| 4784 | if(raw_options[i].extbitgroup && |
| 4785 | sdef->raw.ext_bit_groups[raw_options[i].extbitgroup-1].ext_bit!=XDEFNO){ |
| 4786 | src=mputstr(src, |
| 4787 | "group_limit-=decoded_field_length;\n" |
| 4788 | ); |
| 4789 | } |
| 4790 | if(raw_options[i].lengthto){ /* if the field is lengthto store the value*/ |
| 4791 | if(sdef->elements[i].raw.lengthindex){ |
| 4792 | if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){ |
| 4793 | src=mputprintf(src, |
| 4794 | " if(field_%s%s.%s().ispresent()){\n" |
| 4795 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" |
| 4796 | ,sdef->elements[i].raw.lengthindex->nthfieldname |
| 4797 | ); |
| 4798 | } |
| 4799 | src=mputprintf(src, |
| 4800 | " value_of_length_field%d+=(int)field_%s%s.%s%s()*%d;\n" |
| 4801 | ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" |
| 4802 | ,sdef->elements[i].raw.lengthindex->nthfieldname |
| 4803 | ,sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD?"()":"" |
| 4804 | ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit |
| 4805 | ); |
| 4806 | if(sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD){ |
| 4807 | src=mputstr(src, |
| 4808 | " }\n" |
| 4809 | ); |
| 4810 | } |
| 4811 | } |
| 4812 | else if(sdef->elements[i].raw.union_member_num){ |
| 4813 | int m; |
| 4814 | src = mputprintf(src, " switch (field_%s%s.get_selection()) {\n", |
| 4815 | sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : ""); |
| 4816 | for (m = 1; m < sdef->elements[i].raw.union_member_num + 1; m++) { |
| 4817 | src = mputprintf(src, " case %s%s%s:\n" |
| 4818 | " value_of_length_field%d += (int)field_%s%s.%s() * %d;\n" |
| 4819 | " break;\n", sdef->elements[i].raw.member_name[0], |
| 4820 | "::ALT_", |
| 4821 | sdef->elements[i].raw.member_name[m], i, sdef->elements[i].name, |
| 4822 | sdef->elements[i].isOptional ? "()" : "", |
| 4823 | sdef->elements[i].raw.member_name[m], |
| 4824 | sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit); |
| 4825 | } |
| 4826 | src = mputprintf(src, " default:\n" |
| 4827 | " value_of_length_field%d = 0;\n" |
| 4828 | " }\n", i); |
| 4829 | } |
| 4830 | else{ |
| 4831 | src=mputprintf(src, |
| 4832 | " value_of_length_field%d+=(int)field_%s%s*%d;\n" |
| 4833 | ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" |
| 4834 | ,sdef->elements[i].raw.unit==-1?1:sdef->elements[i].raw.unit |
| 4835 | ); |
| 4836 | } |
| 4837 | } |
| 4838 | if(raw_options[i].pointerto){ /* store the start of pointed field*/ |
| 4839 | src=mputprintf(src, |
| 4840 | " start_of_field%d=(int)field_%s%s+%d?1:-1;\n" |
| 4841 | ,sdef->elements[i].raw.pointerto |
| 4842 | ,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" |
| 4843 | ,sdef->elements[i].raw.ptroffset |
| 4844 | ); |
| 4845 | } |
| 4846 | if (!delayed_decode) { |
| 4847 | /* mark the used bits in length area*/ |
| 4848 | for (a = 0; a < raw_options[i].lengthof; a++) { |
| 4849 | int field_index = raw_options[i].lengthoffield[a]; |
| 4850 | src = mputprintf(src, |
| 4851 | " value_of_length_field%d -= decoded_field_length;\n", field_index); |
| 4852 | if (i == field_index) src = mputprintf(src, |
| 4853 | " if (value_of_length_field%d < 0) return -1;\n", field_index); |
| 4854 | } |
| 4855 | } |
| 4856 | if(sdef->elements[i].isOptional){ |
| 4857 | src=mputprintf(src, |
| 4858 | " }\n }\n%s" |
| 4859 | " else field_%s=OMIT_VALUE;\n" |
| 4860 | ,raw_options[i].tag_type?" }\n":"",sdef->elements[i].name |
| 4861 | ); |
| 4862 | } |
| 4863 | return src; |
| 4864 | } |
| 4865 | |
| 4866 | #ifdef __SUNPRO_C |
| 4867 | #define SUNPRO_PUBLIC "public:\n" |
| 4868 | #define SUNPRO_PRIVATE "private:\n" |
| 4869 | #else |
| 4870 | #define SUNPRO_PUBLIC |
| 4871 | #define SUNPRO_PRIVATE |
| 4872 | #endif |
| 4873 | |
| 4874 | void defRecordTemplate1(const struct_def *sdef, output_struct *output) |
| 4875 | { |
| 4876 | int i; |
| 4877 | const char *name = sdef->name, *dispname = sdef->dispname; |
| 4878 | const char* kind_str = sdef->kind == SET ? "set" : "record"; |
| 4879 | char *def = NULL, *src = NULL; |
| 4880 | |
| 4881 | size_t mandatory_fields_count; |
| 4882 | |
| 4883 | /* class declaration */ |
| 4884 | output->header.class_decls = mputprintf(output->header.class_decls, |
| 4885 | "class %s_template;\n", name); |
| 4886 | |
| 4887 | if(sdef->nElements <= 0) { |
| 4888 | defEmptyRecordTemplate(name, dispname, output); |
| 4889 | return; |
| 4890 | } |
| 4891 | |
| 4892 | /* template class definition */ |
| 4893 | def = mputprintf(def, "class %s_template : public Base_Template {\n", name); |
| 4894 | |
| 4895 | /* data members */ |
| 4896 | def = mputprintf(def, |
| 4897 | SUNPRO_PUBLIC |
| 4898 | "struct single_value_struct;\n" |
| 4899 | SUNPRO_PRIVATE |
| 4900 | "union {\n" |
| 4901 | "single_value_struct *single_value;\n" |
| 4902 | "struct {\n" |
| 4903 | "unsigned int n_values;\n" |
| 4904 | "%s_template *list_value;\n" |
| 4905 | "} value_list;\n" |
| 4906 | "};\n\n", name); |
| 4907 | /* the definition of single_value_struct must be put into the source file |
| 4908 | * because the types of optional fields may be incomplete in this position |
| 4909 | * of header file (e.g. due to type recursion) */ |
| 4910 | src = mputprintf(src, "struct %s_template::single_value_struct {\n", name); |
| 4911 | for (i = 0; i < sdef->nElements; i++) { |
| 4912 | src = mputprintf(src, "%s_template field_%s;\n", |
| 4913 | sdef->elements[i].type, sdef->elements[i].name); |
| 4914 | } |
| 4915 | src = mputstr(src, "};\n\n"); |
| 4916 | |
| 4917 | /* set_specific function (used in field access members) */ |
| 4918 | def = mputstr(def, "void set_specific();\n"); |
| 4919 | src = mputprintf(src, "void %s_template::set_specific()\n" |
| 4920 | "{\n" |
| 4921 | "if (template_selection != SPECIFIC_VALUE) {\n" |
| 4922 | "template_sel old_selection = template_selection;\n" |
| 4923 | "clean_up();\n" |
| 4924 | "single_value = new single_value_struct;\n" |
| 4925 | "set_selection(SPECIFIC_VALUE);\n" |
| 4926 | "if (old_selection == ANY_VALUE || old_selection == ANY_OR_OMIT) {\n", |
| 4927 | name); |
| 4928 | for (i = 0; i < sdef->nElements; i++) { |
| 4929 | src = mputprintf(src, "single_value->field_%s = %s;\n", |
| 4930 | sdef->elements[i].name, |
| 4931 | sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE"); |
| 4932 | } |
| 4933 | src = mputstr(src, "}\n" |
| 4934 | "}\n" |
| 4935 | "}\n\n"); |
| 4936 | |
| 4937 | /* copy_value function */ |
| 4938 | def = mputprintf(def, "void copy_value(const %s& other_value);\n", name); |
| 4939 | src = mputprintf(src, |
| 4940 | "void %s_template::copy_value(const %s& other_value)\n" |
| 4941 | "{\n" |
| 4942 | "single_value = new single_value_struct;\n", name, name); |
| 4943 | for (i = 0; i < sdef->nElements; i++) { |
| 4944 | src = mputprintf(src, |
| 4945 | "if (other_value.%s().is_bound()) {\n", sdef->elements[i].name); |
| 4946 | if (sdef->elements[i].isOptional) { |
| 4947 | /* If the value is present, "reach into" the OPTIONAL with operator() |
| 4948 | * and pass the contained object to the template's constructor. |
| 4949 | * Else set the template to omit. */ |
| 4950 | src = mputprintf(src, |
| 4951 | " if (other_value.%s().ispresent()) single_value->field_%s = " |
| 4952 | "other_value.%s()();\n" |
| 4953 | " else single_value->field_%s = OMIT_VALUE;\n", |
| 4954 | sdef->elements[i].name, sdef->elements[i].name, |
| 4955 | sdef->elements[i].name, sdef->elements[i].name); |
| 4956 | } else { |
| 4957 | src = mputprintf(src, |
| 4958 | " single_value->field_%s = other_value.%s();\n", |
| 4959 | sdef->elements[i].name, sdef->elements[i].name); |
| 4960 | } |
| 4961 | src = mputprintf(src, "} else {\n" |
| 4962 | " single_value->field_%s.clean_up();\n" |
| 4963 | "}\n", sdef->elements[i].name); |
| 4964 | } |
| 4965 | src = mputstr(src, "set_selection(SPECIFIC_VALUE);\n" |
| 4966 | "}\n\n"); |
| 4967 | |
| 4968 | /* copy_template function */ |
| 4969 | def = mputprintf(def, "void copy_template(const %s_template& " |
| 4970 | "other_value);\n\n", name); |
| 4971 | src = mputprintf(src, |
| 4972 | "void %s_template::copy_template(const %s_template& other_value)\n" |
| 4973 | "{\n" |
| 4974 | "switch (other_value.template_selection) {\n" |
| 4975 | "case SPECIFIC_VALUE:\n", name, name); |
| 4976 | src = mputstr(src, |
| 4977 | "single_value = new single_value_struct;\n"); |
| 4978 | for (i = 0; i < sdef->nElements; i++) { |
| 4979 | src = mputprintf(src, |
| 4980 | "if (UNINITIALIZED_TEMPLATE != other_value.%s().get_selection()) {\n", |
| 4981 | sdef->elements[i].name); |
| 4982 | src = mputprintf(src, |
| 4983 | "single_value->field_%s = other_value.%s();\n", |
| 4984 | sdef->elements[i].name, sdef->elements[i].name); |
| 4985 | src = mputprintf(src, "} else {\n" |
| 4986 | "single_value->field_%s.clean_up();\n" |
| 4987 | "}\n", sdef->elements[i].name); |
| 4988 | } |
| 4989 | src = mputprintf(src, |
| 4990 | "case OMIT_VALUE:\n" |
| 4991 | "case ANY_VALUE:\n" |
| 4992 | "case ANY_OR_OMIT:\n" |
| 4993 | "break;\n" |
| 4994 | "case VALUE_LIST:\n" |
| 4995 | "case COMPLEMENTED_LIST:\n" |
| 4996 | "value_list.n_values = other_value.value_list.n_values;\n" |
| 4997 | "value_list.list_value = new %s_template[value_list.n_values];\n" |
| 4998 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 4999 | "list_count++)\n" |
| 5000 | "value_list.list_value[list_count].copy_template(" |
| 5001 | "other_value.value_list.list_value[list_count]);\n" |
| 5002 | "break;\n" |
| 5003 | "default:\n" |
| 5004 | "TTCN_error(\"Copying an uninitialized/unsupported template of type " |
| 5005 | "%s.\");\n" |
| 5006 | "break;\n" |
| 5007 | "}\n" |
| 5008 | "set_selection(other_value);\n" |
| 5009 | "}\n\n", name, dispname); |
| 5010 | |
| 5011 | /* default constructor */ |
| 5012 | def = mputprintf(def, "public:\n" |
| 5013 | "%s_template();\n", name); |
| 5014 | src = mputprintf(src, "%s_template::%s_template()\n" |
| 5015 | "{\n" |
| 5016 | "}\n\n", name, name); |
| 5017 | |
| 5018 | /* constructor t1_template(template_sel other_value) */ |
| 5019 | def = mputprintf(def, "%s_template(template_sel other_value);\n", name); |
| 5020 | src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n" |
| 5021 | " : Base_Template(other_value)\n" |
| 5022 | "{\n" |
| 5023 | "check_single_selection(other_value);\n" |
| 5024 | "}\n\n", name, name); |
| 5025 | |
| 5026 | /* constructor t1_template(const t1& other_value) */ |
| 5027 | def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name); |
| 5028 | src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n" |
| 5029 | "{\n" |
| 5030 | "copy_value(other_value);\n" |
| 5031 | "}\n\n", name, name, name); |
| 5032 | |
| 5033 | /* constructor t1_template(const OPTIONAL<t1>& other_value) */ |
| 5034 | def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n", |
| 5035 | name, name); |
| 5036 | src = mputprintf(src, |
| 5037 | "%s_template::%s_template(const OPTIONAL<%s>& other_value)\n" |
| 5038 | "{\n" |
| 5039 | "switch (other_value.get_selection()) {\n" |
| 5040 | "case OPTIONAL_PRESENT:\n" |
| 5041 | "copy_value((const %s&)other_value);\n" |
| 5042 | "break;\n" |
| 5043 | "case OPTIONAL_OMIT:\n" |
| 5044 | "set_selection(OMIT_VALUE);\n" |
| 5045 | "break;\n" |
| 5046 | "default:\n" |
| 5047 | "TTCN_error(\"Creating a template of type %s from an unbound optional " |
| 5048 | "field.\");\n" |
| 5049 | "}\n" |
| 5050 | "}\n\n", name, name, name, name, dispname); |
| 5051 | |
| 5052 | /* copy constructor */ |
| 5053 | def = mputprintf(def, "%s_template(const %s_template& other_value);\n", |
| 5054 | name, name); |
| 5055 | src = mputprintf(src, "%s_template::%s_template(const %s_template& " |
| 5056 | "other_value)\n" |
| 5057 | ": Base_Template()\n" /* yes, the base class _default_ constructor */ |
| 5058 | "{\n" |
| 5059 | "copy_template(other_value);\n" |
| 5060 | "}\n\n", name, name, name); |
| 5061 | |
| 5062 | /* destructor */ |
| 5063 | def = mputprintf(def, "~%s_template();\n", name); |
| 5064 | src = mputprintf(src, "%s_template::~%s_template()\n" |
| 5065 | "{\n" |
| 5066 | "clean_up();\n" |
| 5067 | "}\n\n", name, name); |
| 5068 | |
| 5069 | /* assignment operator <- template_sel */ |
| 5070 | def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n", |
| 5071 | name); |
| 5072 | src = mputprintf(src, |
| 5073 | "%s_template& %s_template::operator=(template_sel other_value)\n" |
| 5074 | "{\n" |
| 5075 | "check_single_selection(other_value);\n" |
| 5076 | "clean_up();\n" |
| 5077 | "set_selection(other_value);\n" |
| 5078 | "return *this;\n" |
| 5079 | "}\n\n", name, name); |
| 5080 | |
| 5081 | /* assignment operator <- value */ |
| 5082 | def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n", |
| 5083 | name, name); |
| 5084 | |
| 5085 | src = mputprintf(src, |
| 5086 | "%s_template& %s_template::operator=(const %s& other_value)\n" |
| 5087 | "{\n" |
| 5088 | "clean_up();\n" |
| 5089 | "copy_value(other_value);\n" |
| 5090 | "return *this;\n" |
| 5091 | "}\n\n", name, name, name); |
| 5092 | |
| 5093 | /* assignment operator <- optional value */ |
| 5094 | def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& " |
| 5095 | "other_value);\n", name, name); |
| 5096 | |
| 5097 | src = mputprintf(src, |
| 5098 | "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n" |
| 5099 | "{\n" |
| 5100 | "clean_up();\n" |
| 5101 | "switch (other_value.get_selection()) {\n" |
| 5102 | "case OPTIONAL_PRESENT:\n" |
| 5103 | "copy_value((const %s&)other_value);\n" |
| 5104 | "break;\n" |
| 5105 | "case OPTIONAL_OMIT:\n" |
| 5106 | "set_selection(OMIT_VALUE);\n" |
| 5107 | "break;\n" |
| 5108 | "default:\n" |
| 5109 | "TTCN_error(\"Assignment of an unbound optional field to a template " |
| 5110 | "of type %s.\");\n" |
| 5111 | "}\n" |
| 5112 | "return *this;\n" |
| 5113 | "}\n\n", name, name, name, name, dispname); |
| 5114 | |
| 5115 | /* assignment operator <- template*/ |
| 5116 | def = mputprintf(def, |
| 5117 | "%s_template& operator=(const %s_template& other_value);\n", |
| 5118 | name, name); |
| 5119 | |
| 5120 | src = mputprintf(src, |
| 5121 | "%s_template& %s_template::operator=(const %s_template& other_value)\n" |
| 5122 | "{\n" |
| 5123 | "if (&other_value != this) {\n" |
| 5124 | "clean_up();\n" |
| 5125 | "copy_template(other_value);\n" |
| 5126 | "}\n" |
| 5127 | "return *this;\n" |
| 5128 | "}\n\n", name, name, name); |
| 5129 | |
| 5130 | /* match operation (template matching) */ |
| 5131 | def = mputprintf(def, "boolean match(const %s& other_value, boolean legacy " |
| 5132 | "= FALSE) const;\n", name); |
| 5133 | |
| 5134 | src = mputprintf(src, |
| 5135 | "boolean %s_template::match(const %s& other_value, boolean legacy) const\n" |
| 5136 | "{\n" |
| 5137 | "if (!other_value.is_bound()) return FALSE;\n" |
| 5138 | "switch (template_selection) {\n" |
| 5139 | "case ANY_VALUE:\n" |
| 5140 | "case ANY_OR_OMIT:\n" |
| 5141 | "return TRUE;\n" |
| 5142 | "case OMIT_VALUE:\n" |
| 5143 | "return FALSE;\n" |
| 5144 | "case SPECIFIC_VALUE:\n", name, name); |
| 5145 | for (i = 0; i < sdef->nElements; i++) { |
| 5146 | src = mputprintf(src,"if(!other_value.%s().is_bound()) return FALSE;\n", sdef->elements[i].name); |
| 5147 | if (sdef->elements[i].isOptional) src = mputprintf(src, |
| 5148 | "if((other_value.%s().ispresent() ? " |
| 5149 | "!single_value->field_%s.match((const %s&)other_value.%s(), legacy) : " |
| 5150 | "!single_value->field_%s.match_omit(legacy)))", |
| 5151 | sdef->elements[i].name, sdef->elements[i].name, |
| 5152 | sdef->elements[i].type, sdef->elements[i].name, |
| 5153 | sdef->elements[i].name); |
| 5154 | else src = mputprintf(src, |
| 5155 | "if(!single_value->field_%s.match(other_value.%s(), legacy))", |
| 5156 | sdef->elements[i].name, sdef->elements[i].name); |
| 5157 | src = mputstr(src, "return FALSE;\n"); |
| 5158 | } |
| 5159 | src = mputprintf(src, |
| 5160 | "return TRUE;\n" |
| 5161 | "case VALUE_LIST:\n" |
| 5162 | "case COMPLEMENTED_LIST:\n" |
| 5163 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 5164 | "list_count++)\n" |
| 5165 | "if (value_list.list_value[list_count].match(other_value, legacy)) " |
| 5166 | "return template_selection == VALUE_LIST;\n" |
| 5167 | "return template_selection == COMPLEMENTED_LIST;\n" |
| 5168 | "default:\n" |
| 5169 | "TTCN_error(\"Matching an uninitialized/unsupported template of " |
| 5170 | "type %s.\");\n" |
| 5171 | "}\n" |
| 5172 | "return FALSE;\n" |
| 5173 | "}\n\n", dispname); |
| 5174 | |
| 5175 | /* is_bound */ |
| 5176 | def = mputstr(def, "boolean is_bound() const;\n"); |
| 5177 | |
| 5178 | src = mputprintf(src, "boolean %s_template::is_bound() const\n" |
| 5179 | "{\n" |
| 5180 | "if (template_selection == UNINITIALIZED_TEMPLATE && !is_ifpresent) " |
| 5181 | "return FALSE;\n", name); |
| 5182 | src = mputstr(src, "if (template_selection != SPECIFIC_VALUE) return TRUE;\n"); |
| 5183 | for (i = 0; i < sdef->nElements; i++) { |
| 5184 | if (sdef->elements[i].isOptional) { |
| 5185 | src = mputprintf(src, |
| 5186 | "if (single_value->field_%s.is_omit() ||" |
| 5187 | " single_value->field_%s.is_bound()) return TRUE;\n", |
| 5188 | sdef->elements[i].name, sdef->elements[i].name); |
| 5189 | } else { |
| 5190 | src = mputprintf(src, |
| 5191 | "if (single_value->field_%s.is_bound()) return TRUE;\n", |
| 5192 | sdef->elements[i].name); |
| 5193 | } |
| 5194 | } |
| 5195 | src = mputstr(src, "return FALSE;\n" |
| 5196 | "}\n\n"); |
| 5197 | |
| 5198 | /* is_value */ |
| 5199 | def = mputstr(def, "boolean is_value() const;\n"); |
| 5200 | |
| 5201 | src = mputprintf(src, "boolean %s_template::is_value() const\n" |
| 5202 | "{\n" |
| 5203 | "if (template_selection != SPECIFIC_VALUE || is_ifpresent) " |
| 5204 | "return FALSE;\n", name); |
| 5205 | for (i = 0; i < sdef->nElements; i++) { |
| 5206 | if (sdef->elements[i].isOptional) { |
| 5207 | src = mputprintf(src, |
| 5208 | "if (!single_value->field_%s.is_omit() &&" |
| 5209 | " !single_value->field_%s.is_value()) return FALSE;\n", |
| 5210 | sdef->elements[i].name, sdef->elements[i].name); |
| 5211 | } else { |
| 5212 | src = mputprintf(src, |
| 5213 | "if (!single_value->field_%s.is_value()) return FALSE;\n", |
| 5214 | sdef->elements[i].name); |
| 5215 | } |
| 5216 | } |
| 5217 | src = mputstr(src, "return TRUE;\n" |
| 5218 | "}\n\n"); |
| 5219 | |
| 5220 | /* clean_up function */ |
| 5221 | def = mputstr(def, "void clean_up();\n"); |
| 5222 | src = mputprintf(src, |
| 5223 | "void %s_template::clean_up()\n" |
| 5224 | "{\n" |
| 5225 | "switch (template_selection) {\n" |
| 5226 | "case SPECIFIC_VALUE:\n" |
| 5227 | "delete single_value;\n" |
| 5228 | "break;\n" |
| 5229 | "case VALUE_LIST:\n" |
| 5230 | "case COMPLEMENTED_LIST:\n" |
| 5231 | "delete [] value_list.list_value;\n" |
| 5232 | "default:\n" |
| 5233 | "break;\n" |
| 5234 | "}\n" |
| 5235 | "template_selection = UNINITIALIZED_TEMPLATE;\n" |
| 5236 | "}\n\n", name); |
| 5237 | |
| 5238 | /* valueof operation */ |
| 5239 | def = mputprintf(def, "%s valueof() const;\n", name); |
| 5240 | |
| 5241 | src = mputprintf(src, "%s %s_template::valueof() const\n" |
| 5242 | "{\n" |
| 5243 | "if (template_selection != SPECIFIC_VALUE || is_ifpresent)\n" |
| 5244 | "TTCN_error(\"Performing valueof or send operation on a non-specific " |
| 5245 | "template of type %s.\");\n" |
| 5246 | "%s ret_val;\n", name, name, dispname, name); |
| 5247 | for (i = 0; i < sdef->nElements; i++) { |
| 5248 | if (sdef->elements[i].isOptional) { |
| 5249 | src = mputprintf(src, |
| 5250 | "if (single_value->field_%s.is_omit()) " |
| 5251 | "ret_val.%s() = OMIT_VALUE;\n" |
| 5252 | "else ", |
| 5253 | sdef->elements[i].name, sdef->elements[i].name); |
| 5254 | } |
| 5255 | src = mputprintf(src, "if (single_value->field_%s.is_bound()) {\n" |
| 5256 | "ret_val.%s() = single_value->field_%s.valueof();\n" |
| 5257 | "}\n", |
| 5258 | sdef->elements[i].name, sdef->elements[i].name, sdef->elements[i].name); |
| 5259 | } |
| 5260 | src = mputstr(src, "return ret_val;\n" |
| 5261 | "}\n\n"); |
| 5262 | |
| 5263 | /* void set_type(template_sel, int) function */ |
| 5264 | def = mputstr(def, |
| 5265 | "void set_type(template_sel template_type, " |
| 5266 | "unsigned int list_length);\n"); |
| 5267 | |
| 5268 | src = mputprintf(src, |
| 5269 | "void %s_template::set_type(template_sel template_type, " |
| 5270 | "unsigned int list_length)\n" |
| 5271 | "{\n" |
| 5272 | "if (template_type != VALUE_LIST " |
| 5273 | "&& template_type != COMPLEMENTED_LIST)\n" |
| 5274 | "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n" |
| 5275 | "clean_up();\n" |
| 5276 | "set_selection(template_type);\n" |
| 5277 | "value_list.n_values = list_length;\n" |
| 5278 | "value_list.list_value = new %s_template[list_length];\n" |
| 5279 | "}\n\n", name, dispname, name); |
| 5280 | |
| 5281 | /* list_item(int) function */ |
| 5282 | |
| 5283 | def = mputprintf(def, |
| 5284 | "%s_template& list_item(unsigned int list_index) const;\n", name); |
| 5285 | |
| 5286 | src = mputprintf(src, |
| 5287 | "%s_template& %s_template::list_item(unsigned int list_index) const\n" |
| 5288 | "{\n" |
| 5289 | "if (template_selection != VALUE_LIST " |
| 5290 | "&& template_selection != COMPLEMENTED_LIST)\n" |
| 5291 | "TTCN_error(\"Accessing a list element of a non-list template of " |
| 5292 | "type %s.\");\n" |
| 5293 | "if (list_index >= value_list.n_values)\n" |
| 5294 | "TTCN_error(\"Index overflow in a value list template of type " |
| 5295 | "%s.\");\n" |
| 5296 | "return value_list.list_value[list_index];\n" |
| 5297 | "}\n\n", name, name, dispname, dispname); |
| 5298 | |
| 5299 | /* template field access functions (non-const & const) */ |
| 5300 | for (i = 0; i < sdef->nElements; i++) { |
| 5301 | def = mputprintf(def, "%s_template& %s();\n", |
| 5302 | sdef->elements[i].type, sdef->elements[i].name); |
| 5303 | src = mputprintf(src, "%s_template& %s_template::%s()\n" |
| 5304 | "{\n" |
| 5305 | "set_specific();\n" |
| 5306 | "return single_value->field_%s;\n" |
| 5307 | "}\n\n", |
| 5308 | sdef->elements[i].type, name, sdef->elements[i].name, |
| 5309 | sdef->elements[i].name); |
| 5310 | def = mputprintf(def, "const %s_template& %s() const;\n", |
| 5311 | sdef->elements[i].type, sdef->elements[i].name); |
| 5312 | src = mputprintf(src, "const %s_template& %s_template::%s() const\n" |
| 5313 | "{\n" |
| 5314 | "if (template_selection != SPECIFIC_VALUE)\n" |
| 5315 | "TTCN_error(\"Accessing field %s of a non-specific " |
| 5316 | "template of type %s.\");\n" |
| 5317 | "return single_value->field_%s;\n" |
| 5318 | "}\n\n", |
| 5319 | sdef->elements[i].type, name, sdef->elements[i].name, |
| 5320 | sdef->elements[i].dispname, dispname, sdef->elements[i].name); |
| 5321 | } |
| 5322 | |
| 5323 | /* sizeof operation */ |
| 5324 | def = mputstr(def, "int size_of() const;\n"); |
| 5325 | src = mputprintf(src, |
| 5326 | "int %s_template::size_of() const\n" |
| 5327 | "{\n" |
| 5328 | " if (is_ifpresent) TTCN_error(\"Performing sizeof() operation on a " |
| 5329 | "template of type %s which has an ifpresent attribute.\");\n" |
| 5330 | " switch (template_selection)\n" |
| 5331 | " {\n" |
| 5332 | " case SPECIFIC_VALUE:\n", |
| 5333 | name, dispname); |
| 5334 | mandatory_fields_count = 0; |
| 5335 | for (i = 0; i < sdef->nElements; i++) |
| 5336 | if (!sdef->elements[i].isOptional) mandatory_fields_count++; |
| 5337 | if(sdef->nElements == mandatory_fields_count){ |
| 5338 | src = mputprintf(src," return %lu;\n", |
| 5339 | (unsigned long) mandatory_fields_count); |
| 5340 | }else{ |
| 5341 | src = mputprintf(src, |
| 5342 | " {" |
| 5343 | " int ret_val = %lu;\n", (unsigned long) mandatory_fields_count); |
| 5344 | for (i = 0; i < sdef->nElements; i++) |
| 5345 | if (sdef->elements[i].isOptional) |
| 5346 | src = mputprintf(src, |
| 5347 | " if (single_value->field_%s.is_present()) ret_val++;\n", |
| 5348 | sdef->elements[i].name); |
| 5349 | src = mputstr(src, |
| 5350 | " return ret_val;\n" |
| 5351 | " }\n"); |
| 5352 | } |
| 5353 | src = mputprintf(src, |
| 5354 | |
| 5355 | " case VALUE_LIST:\n" |
| 5356 | " {\n" |
| 5357 | " if (value_list.n_values<1)\n" |
| 5358 | " TTCN_error(\"Internal error: Performing sizeof() operation on a " |
| 5359 | "template of type %s containing an empty list.\");\n" |
| 5360 | " int item_size = value_list.list_value[0].size_of();\n" |
| 5361 | " for (unsigned int l_idx = 1; l_idx < value_list.n_values; l_idx++)\n" |
| 5362 | " {\n" |
| 5363 | " if (value_list.list_value[l_idx].size_of()!=item_size)\n" |
| 5364 | " TTCN_error(\"Performing sizeof() operation on a template " |
| 5365 | "of type %s containing a value list with different sizes.\");\n" |
| 5366 | " }\n" |
| 5367 | " return item_size;\n" |
| 5368 | " }\n" |
| 5369 | " case OMIT_VALUE:\n" |
| 5370 | " TTCN_error(\"Performing sizeof() operation on a template of type %s " |
| 5371 | "containing omit value.\");\n" |
| 5372 | " case ANY_VALUE:\n" |
| 5373 | " case ANY_OR_OMIT:\n" |
| 5374 | " TTCN_error(\"Performing sizeof() operation on a template of type %s " |
| 5375 | "containing */? value.\");\n" |
| 5376 | " case COMPLEMENTED_LIST:\n" |
| 5377 | " TTCN_error(\"Performing sizeof() operation on a template of type %s " |
| 5378 | "containing complemented list.\");\n" |
| 5379 | " default:\n" |
| 5380 | " TTCN_error(\"Performing sizeof() operation on an " |
| 5381 | "uninitialized/unsupported template of type %s.\");\n" |
| 5382 | " }\n" |
| 5383 | " return 0;\n" |
| 5384 | "}\n\n", |
| 5385 | dispname,dispname,dispname,dispname,dispname,dispname); |
| 5386 | |
| 5387 | /* log function */ |
| 5388 | def = mputstr(def, "void log() const;\n"); |
| 5389 | src = mputprintf(src, |
| 5390 | "void %s_template::log() const\n" |
| 5391 | "{\n" |
| 5392 | "switch (template_selection) {\n" |
| 5393 | "case SPECIFIC_VALUE:\n", name); |
| 5394 | for (i = 0; i < sdef->nElements; i++) { |
| 5395 | src = mputstr(src, "TTCN_Logger::log_event_str(\""); |
| 5396 | if (i == 0) src = mputc(src, '{'); |
| 5397 | else src = mputc(src, ','); |
| 5398 | src = mputprintf(src, " %s := \");\n" |
| 5399 | "single_value->field_%s.log();\n", |
| 5400 | sdef->elements[i].dispname, sdef->elements[i].name); |
| 5401 | } |
| 5402 | src = mputstr(src, |
| 5403 | "TTCN_Logger::log_event_str(\" }\");\n" |
| 5404 | "break;\n" |
| 5405 | "case COMPLEMENTED_LIST:\n" |
| 5406 | "TTCN_Logger::log_event_str(\"complement \");\n" |
| 5407 | "case VALUE_LIST:\n" |
| 5408 | "TTCN_Logger::log_char('(');\n" |
| 5409 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 5410 | "list_count++) {\n" |
| 5411 | "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n" |
| 5412 | "value_list.list_value[list_count].log();\n" |
| 5413 | "}\n" |
| 5414 | "TTCN_Logger::log_char(')');\n" |
| 5415 | "break;\n" |
| 5416 | "default:\n" |
| 5417 | "log_generic();\n" |
| 5418 | "}\n" |
| 5419 | "log_ifpresent();\n" |
| 5420 | "}\n\n"); |
| 5421 | |
| 5422 | /* log_match function */ |
| 5423 | def = mputprintf(def, "void log_match(const %s& match_value, " |
| 5424 | "boolean legacy = FALSE) const;\n", name); |
| 5425 | src = mputprintf(src, |
| 5426 | "void %s_template::log_match(const %s& match_value, boolean legacy) const\n" |
| 5427 | "{\n" |
| 5428 | "if(TTCN_Logger::VERBOSITY_COMPACT" |
| 5429 | " == TTCN_Logger::get_matching_verbosity()){\n" |
| 5430 | "if(match(match_value, legacy)){\n" |
| 5431 | "TTCN_Logger::print_logmatch_buffer();\n" |
| 5432 | "TTCN_Logger::log_event_str(\" matched\");\n" |
| 5433 | "} else{\n" |
| 5434 | "if (template_selection == SPECIFIC_VALUE) {\n" |
| 5435 | "size_t previous_size = TTCN_Logger::get_logmatch_buffer_len();\n" |
| 5436 | , name, name); |
| 5437 | for (i = 0; i < sdef->nElements; i++) { |
| 5438 | if (sdef->elements[i].isOptional){ |
| 5439 | src = mputprintf(src, |
| 5440 | "if (match_value.%s().ispresent()){\n" |
| 5441 | "if(!single_value->field_%s.match(match_value.%s(), legacy)){\n" |
| 5442 | "TTCN_Logger::log_logmatch_info(\".%s\");\n" |
| 5443 | "single_value->field_%s.log_match(match_value.%s(), legacy);\n" |
| 5444 | "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n" |
| 5445 | "}\n" |
| 5446 | "} else {\n" |
| 5447 | "if (!single_value->field_%s.match_omit(legacy)){\n " |
| 5448 | "TTCN_Logger::log_logmatch_info(\".%s := omit with \");\n" |
| 5449 | "TTCN_Logger::print_logmatch_buffer();\n" |
| 5450 | "single_value->field_%s.log();\n" |
| 5451 | "TTCN_Logger::log_event_str(\" unmatched\");\n" |
| 5452 | "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n" |
| 5453 | "}\n" |
| 5454 | "}\n" |
| 5455 | , sdef->elements[i].name, sdef->elements[i].name, |
| 5456 | sdef->elements[i].name, sdef->elements[i].dispname, |
| 5457 | sdef->elements[i].name, sdef->elements[i].name, |
| 5458 | sdef->elements[i].name, sdef->elements[i].dispname, |
| 5459 | sdef->elements[i].name); |
| 5460 | }else{ |
| 5461 | src = mputprintf(src, |
| 5462 | "if(!single_value->field_%s.match(match_value.%s(), legacy)){\n" |
| 5463 | "TTCN_Logger::log_logmatch_info(\".%s\");\n" |
| 5464 | "single_value->field_%s.log_match(match_value.%s(), legacy);\n" |
| 5465 | "TTCN_Logger::set_logmatch_buffer_len(previous_size);\n" |
| 5466 | "}\n",sdef->elements[i].name, sdef->elements[i].name, |
| 5467 | sdef->elements[i].dispname, sdef->elements[i].name, |
| 5468 | sdef->elements[i].name); |
| 5469 | } |
| 5470 | } |
| 5471 | |
| 5472 | src = mputstr(src,"}else {\n" |
| 5473 | "TTCN_Logger::print_logmatch_buffer();\n" |
| 5474 | "match_value.log();\n" |
| 5475 | "TTCN_Logger::log_event_str(\" with \");\n" |
| 5476 | "log();\n" |
| 5477 | "TTCN_Logger::log_event_str(\" unmatched\");\n" |
| 5478 | "}\n" |
| 5479 | "}\n" |
| 5480 | "return;\n" |
| 5481 | "}\n" |
| 5482 | "if (template_selection == SPECIFIC_VALUE) {\n"); |
| 5483 | for (i = 0; i < sdef->nElements; i++) { |
| 5484 | src = mputstr(src, "TTCN_Logger::log_event_str(\""); |
| 5485 | if (i == 0) src = mputc(src, '{'); |
| 5486 | else src = mputc(src, ','); |
| 5487 | src = mputprintf(src, " %s := \");\n", sdef->elements[i].dispname); |
| 5488 | if (sdef->elements[i].isOptional) src = mputprintf(src, |
| 5489 | "if (match_value.%s().ispresent()) " |
| 5490 | "single_value->field_%s.log_match(match_value.%s(), legacy);\n" |
| 5491 | "else {\n" |
| 5492 | "TTCN_Logger::log_event_str(\"omit with \");\n" |
| 5493 | "single_value->field_%s.log();\n" |
| 5494 | "if (single_value->field_%s.match_omit(legacy)) " |
| 5495 | "TTCN_Logger::log_event_str(\" matched\");\n" |
| 5496 | "else TTCN_Logger::log_event_str(\" unmatched\");\n" |
| 5497 | "}\n", |
| 5498 | sdef->elements[i].name, sdef->elements[i].name, |
| 5499 | sdef->elements[i].name, sdef->elements[i].name, |
| 5500 | sdef->elements[i].name); |
| 5501 | else src = mputprintf(src, |
| 5502 | "single_value->field_%s.log_match(match_value.%s(), legacy);\n", |
| 5503 | sdef->elements[i].name, sdef->elements[i].name); |
| 5504 | } |
| 5505 | src = mputstr(src, |
| 5506 | "TTCN_Logger::log_event_str(\" }\");\n" |
| 5507 | "} else {\n" |
| 5508 | "match_value.log();\n" |
| 5509 | "TTCN_Logger::log_event_str(\" with \");\n" |
| 5510 | "log();\n" |
| 5511 | "if (match(match_value, legacy)) TTCN_Logger::log_event_str(\" matched\");\n" |
| 5512 | "else TTCN_Logger::log_event_str(\" unmatched\");\n" |
| 5513 | "}\n" |
| 5514 | "}\n\n"); |
| 5515 | |
| 5516 | /*encode_text function*/ |
| 5517 | def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); |
| 5518 | src = mputprintf(src, |
| 5519 | "void %s_template::encode_text(Text_Buf& text_buf) const\n" |
| 5520 | "{\n" |
| 5521 | "encode_text_base(text_buf);\n" |
| 5522 | "switch (template_selection) {\n" |
| 5523 | "case SPECIFIC_VALUE:\n", name); |
| 5524 | for (i = 0; i < sdef->nElements; i++) { |
| 5525 | src = mputprintf(src, "single_value->field_%s.encode_text(text_buf);\n", |
| 5526 | sdef->elements[i].name); |
| 5527 | } |
| 5528 | src = mputprintf(src, |
| 5529 | "case OMIT_VALUE:\n" |
| 5530 | "case ANY_VALUE:\n" |
| 5531 | "case ANY_OR_OMIT:\n" |
| 5532 | "break;\n" |
| 5533 | "case VALUE_LIST:\n" |
| 5534 | "case COMPLEMENTED_LIST:\n" |
| 5535 | "text_buf.push_int(value_list.n_values);\n" |
| 5536 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 5537 | "list_count++)\n" |
| 5538 | "value_list.list_value[list_count].encode_text(text_buf);\n" |
| 5539 | "break;\n" |
| 5540 | "default:\n" |
| 5541 | "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported " |
| 5542 | "template of type %s.\");\n" |
| 5543 | "}\n" |
| 5544 | "}\n\n", dispname); |
| 5545 | |
| 5546 | /*decode_text function*/ |
| 5547 | def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); |
| 5548 | src = mputprintf(src, |
| 5549 | "void %s_template::decode_text(Text_Buf& text_buf)\n" |
| 5550 | "{\n" |
| 5551 | "clean_up();\n" |
| 5552 | "decode_text_base(text_buf);\n" |
| 5553 | "switch (template_selection) {\n" |
| 5554 | "case SPECIFIC_VALUE:\n" |
| 5555 | "single_value = new single_value_struct;\n", name); |
| 5556 | for (i = 0; i < sdef->nElements; i++) { |
| 5557 | src = mputprintf(src, "single_value->field_%s.decode_text(text_buf);\n", |
| 5558 | sdef->elements[i].name); |
| 5559 | } |
| 5560 | src = mputprintf(src, |
| 5561 | "case OMIT_VALUE:\n" |
| 5562 | "case ANY_VALUE:\n" |
| 5563 | "case ANY_OR_OMIT:\n" |
| 5564 | "break;\n" |
| 5565 | "case VALUE_LIST:\n" |
| 5566 | "case COMPLEMENTED_LIST:\n" |
| 5567 | "value_list.n_values = text_buf.pull_int().get_val();\n" |
| 5568 | "value_list.list_value = new %s_template[value_list.n_values];\n" |
| 5569 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 5570 | "list_count++)\n" |
| 5571 | "value_list.list_value[list_count].decode_text(text_buf);\n" |
| 5572 | "break;\n" |
| 5573 | "default:\n" |
| 5574 | "TTCN_error(\"Text decoder: An unknown/unsupported selection was " |
| 5575 | "received in a template of type %s.\");\n" |
| 5576 | "}\n" |
| 5577 | "}\n\n", name, dispname); |
| 5578 | |
| 5579 | /* set_param() */ |
| 5580 | def = mputstr(def, "void set_param(Module_Param& param);\n"); |
| 5581 | src = mputprintf(src, |
| 5582 | "void %s_template::set_param(Module_Param& param)\n" |
| 5583 | "{\n" |
| 5584 | " if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&\n" |
| 5585 | " param.get_id()->next_name()) {\n" |
| 5586 | // Haven't reached the end of the module parameter name |
| 5587 | // => the name refers to one of the fields, not to the whole record |
| 5588 | " char* param_field = param.get_id()->get_current_name();\n" |
| 5589 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" |
| 5590 | " param.error(\"Unexpected array index in module parameter, expected a valid field\"\n" |
| 5591 | " \" name for %s template type `%s'\");\n" |
| 5592 | " }\n" |
| 5593 | " ", name, kind_str, dispname); |
| 5594 | for (i = 0; i < sdef->nElements; i++) { |
| 5595 | src = mputprintf(src, |
| 5596 | "if (strcmp(\"%s\", param_field) == 0) {\n" |
| 5597 | " %s().set_param(param);\n" |
| 5598 | " return;\n" |
| 5599 | " } else ", |
| 5600 | sdef->elements[i].dispname, sdef->elements[i].name); |
| 5601 | } |
| 5602 | src = mputprintf(src, |
| 5603 | "param.error(\"Field `%%s' not found in %s template type `%s'\", param_field);\n" |
| 5604 | " }\n" |
| 5605 | " param.basic_check(Module_Param::BC_TEMPLATE, \"%s template\");\n" |
| 5606 | " Module_Param_Ptr mp = ¶m;\n" |
| 5607 | " if (param.get_type() == Module_Param::MP_Reference) {\n" |
| 5608 | " mp = param.get_referenced_param();\n" |
| 5609 | " }\n" |
| 5610 | " switch (mp->get_type()) {\n" |
| 5611 | " case Module_Param::MP_Omit:\n" |
| 5612 | " *this = OMIT_VALUE;\n" |
| 5613 | " break;\n" |
| 5614 | " case Module_Param::MP_Any:\n" |
| 5615 | " *this = ANY_VALUE;\n" |
| 5616 | " break;\n" |
| 5617 | " case Module_Param::MP_AnyOrNone:\n" |
| 5618 | " *this = ANY_OR_OMIT;\n" |
| 5619 | " break;\n" |
| 5620 | " case Module_Param::MP_List_Template:\n" |
| 5621 | " case Module_Param::MP_ComplementList_Template: {\n" |
| 5622 | " %s_template temp;\n" |
| 5623 | " temp.set_type(mp->get_type()==Module_Param::MP_List_Template ? " |
| 5624 | "VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());\n" |
| 5625 | " for (size_t p_i=0; p_i<mp->get_size(); p_i++) {\n" |
| 5626 | " temp.list_item(p_i).set_param(*mp->get_elem(p_i));\n" |
| 5627 | " }\n" |
| 5628 | " *this = temp;\n" |
| 5629 | " break; }\n" |
| 5630 | " case Module_Param::MP_Value_List:\n" |
| 5631 | " if (%lu<mp->get_size()) {\n" |
| 5632 | " param.error(\"%s template of type %s has %lu fields but list value has %%d fields\", (int)mp->get_size());\n" |
| 5633 | " }\n", |
| 5634 | kind_str, dispname, kind_str, name, (unsigned long)sdef->nElements, kind_str, dispname, (unsigned long)sdef->nElements); |
| 5635 | for (i = 0; i < sdef->nElements; ++i) { |
| 5636 | src = mputprintf(src, |
| 5637 | " if (mp->get_size()>%lu && mp->get_elem(%lu)->get_type()!=Module_Param::MP_NotUsed) %s().set_param(*mp->get_elem(%lu));\n", |
| 5638 | (unsigned long)i, (unsigned long)i, sdef->elements[i].name, (unsigned long)i); |
| 5639 | } |
| 5640 | src = mputstr(src, |
| 5641 | " break;\n" |
| 5642 | " case Module_Param::MP_Assignment_List: {\n" |
| 5643 | " Vector<bool> value_used(mp->get_size());\n" |
| 5644 | " value_used.resize(mp->get_size(), false);\n"); |
| 5645 | for (i = 0; i < sdef->nElements; ++i) { |
| 5646 | src = mputprintf(src, |
| 5647 | " for (size_t val_idx=0; val_idx<mp->get_size(); val_idx++) {\n" |
| 5648 | " Module_Param* const curr_param = mp->get_elem(val_idx);\n" |
| 5649 | " if (!strcmp(curr_param->get_id()->get_name(), \"%s\")) {\n" |
| 5650 | " if (curr_param->get_type()!=Module_Param::MP_NotUsed) {\n" |
| 5651 | " %s().set_param(*curr_param);\n" |
| 5652 | " }\n" |
| 5653 | " value_used[val_idx]=true;\n" |
| 5654 | " }\n" |
| 5655 | " }\n" |
| 5656 | , sdef->elements[i].dispname, sdef->elements[i].name); |
| 5657 | } |
| 5658 | src = mputprintf(src, |
| 5659 | " for (size_t val_idx=0; val_idx<mp->get_size(); val_idx++) if (!value_used[val_idx]) {\n" |
| 5660 | " mp->get_elem(val_idx)->error(\"Non existent field name in type %s: %%s\", mp->get_elem(val_idx)->get_id()->get_name());\n" |
| 5661 | " break;\n" |
| 5662 | " }\n" |
| 5663 | " } break;\n" |
| 5664 | " default:\n" |
| 5665 | " param.type_error(\"%s template\", \"%s\");\n" |
| 5666 | " }\n" |
| 5667 | " is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();\n" |
| 5668 | "}\n\n", dispname, kind_str, dispname); |
| 5669 | |
| 5670 | /* get_param() */ |
| 5671 | def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); |
| 5672 | src = mputprintf(src, |
| 5673 | "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n" |
| 5674 | "{\n" |
| 5675 | " if (param_name.next_name()) {\n" |
| 5676 | // Haven't reached the end of the module parameter name |
| 5677 | // => the name refers to one of the fields, not to the whole record |
| 5678 | " char* param_field = param_name.get_current_name();\n" |
| 5679 | " if (param_field[0] >= '0' && param_field[0] <= '9') {\n" |
| 5680 | " TTCN_error(\"Unexpected array index in module parameter reference, \"\n" |
| 5681 | " \"expected a valid field name for %s template type `%s'\");\n" |
| 5682 | " }\n" |
| 5683 | " ", name, kind_str, dispname); |
| 5684 | for (i = 0; i < sdef->nElements; i++) { |
| 5685 | src = mputprintf(src, |
| 5686 | "if (strcmp(\"%s\", param_field) == 0) {\n" |
| 5687 | " return %s().get_param(param_name);\n" |
| 5688 | " } else ", |
| 5689 | sdef->elements[i].dispname, sdef->elements[i].name); |
| 5690 | } |
| 5691 | src = mputprintf(src, |
| 5692 | "TTCN_error(\"Field `%%s' not found in %s type `%s'\", param_field);\n" |
| 5693 | " }\n" |
| 5694 | " Module_Param* mp = NULL;\n" |
| 5695 | " switch (template_selection) {\n" |
| 5696 | " case UNINITIALIZED_TEMPLATE:\n" |
| 5697 | " mp = new Module_Param_Unbound();\n" |
| 5698 | " break;\n" |
| 5699 | " case OMIT_VALUE:\n" |
| 5700 | " mp = new Module_Param_Omit();\n" |
| 5701 | " break;\n" |
| 5702 | " case ANY_VALUE:\n" |
| 5703 | " mp = new Module_Param_Any();\n" |
| 5704 | " break;\n" |
| 5705 | " case ANY_OR_OMIT:\n" |
| 5706 | " mp = new Module_Param_AnyOrNone();\n" |
| 5707 | " break;\n" |
| 5708 | " case SPECIFIC_VALUE: {\n" |
| 5709 | " mp = new Module_Param_Assignment_List();\n" |
| 5710 | , kind_str, dispname); |
| 5711 | for (i = 0; i < sdef->nElements; i++) { |
| 5712 | src = mputprintf(src, |
| 5713 | " Module_Param* mp_field_%s = single_value->field_%s.get_param(param_name);\n" |
| 5714 | " mp_field_%s->set_id(new Module_Param_FieldName(mcopystr(\"%s\")));\n" |
| 5715 | " mp->add_elem(mp_field_%s);\n" |
| 5716 | , sdef->elements[i].name, sdef->elements[i].name |
| 5717 | , sdef->elements[i].name, sdef->elements[i].dispname |
| 5718 | , sdef->elements[i].name); |
| 5719 | } |
| 5720 | src = mputstr(src, |
| 5721 | " break; }\n" |
| 5722 | " case VALUE_LIST:\n" |
| 5723 | " case COMPLEMENTED_LIST: {\n" |
| 5724 | " if (template_selection == VALUE_LIST) {\n" |
| 5725 | " mp = new Module_Param_List_Template();\n" |
| 5726 | " }\n" |
| 5727 | " else {\n" |
| 5728 | " mp = new Module_Param_ComplementList_Template();\n" |
| 5729 | " }\n" |
| 5730 | " for (size_t i = 0; i < value_list.n_values; ++i) {\n" |
| 5731 | " mp->add_elem(value_list.list_value[i].get_param(param_name));\n" |
| 5732 | " }\n" |
| 5733 | " break; }\n" |
| 5734 | " default:\n" |
| 5735 | " break;\n" |
| 5736 | " }\n" |
| 5737 | " if (is_ifpresent) {\n" |
| 5738 | " mp->set_ifpresent();\n" |
| 5739 | " }\n" |
| 5740 | " return mp;\n" |
| 5741 | "}\n\n"); |
| 5742 | |
| 5743 | /* check template restriction */ |
| 5744 | def = mputstr(def, "void check_restriction(template_res t_res, " |
| 5745 | "const char* t_name=NULL, boolean legacy = FALSE) const;\n"); |
| 5746 | src = mputprintf(src, |
| 5747 | "void %s_template::check_restriction(" |
| 5748 | "template_res t_res, const char* t_name, boolean legacy) const\n" |
| 5749 | "{\n" |
| 5750 | "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n" |
| 5751 | "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n" |
| 5752 | "case TR_OMIT:\n" |
| 5753 | "if (template_selection==OMIT_VALUE) return;\n" |
| 5754 | "case TR_VALUE:\n" |
| 5755 | "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n", |
| 5756 | name); |
| 5757 | for (i = 0; i < sdef->nElements; i++) { |
| 5758 | src = mputprintf(src, "single_value->field_%s.check_restriction(" |
| 5759 | "t_res, t_name ? t_name : \"%s\");\n", |
| 5760 | sdef->elements[i].name, dispname); |
| 5761 | } |
| 5762 | src = mputprintf(src, |
| 5763 | "return;\n" |
| 5764 | "case TR_PRESENT:\n" |
| 5765 | "if (!match_omit(legacy)) return;\n" |
| 5766 | "break;\n" |
| 5767 | "default:\n" |
| 5768 | "return;\n" |
| 5769 | "}\n" |
| 5770 | "TTCN_error(\"Restriction `%%s' on template of type %%s " |
| 5771 | "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n" |
| 5772 | "}\n\n", dispname); |
| 5773 | |
| 5774 | defCommonRecordTemplate(name, &def, &src); |
| 5775 | |
| 5776 | def = mputstr(def, "};\n\n"); |
| 5777 | |
| 5778 | output->header.class_defs = mputstr(output->header.class_defs, def); |
| 5779 | Free(def); |
| 5780 | |
| 5781 | output->source.methods = mputstr(output->source.methods, src); |
| 5782 | Free(src); |
| 5783 | } |
| 5784 | |
| 5785 | static void defEmptyRecordClass(const struct_def *sdef, |
| 5786 | output_struct *output) |
| 5787 | { |
| 5788 | const char *name = sdef->name, *dispname = sdef->dispname; |
| 5789 | char *def = NULL, *src = NULL; |
| 5790 | boolean ber_needed = sdef->isASN1 && enable_ber(); |
| 5791 | boolean raw_needed = sdef->hasRaw && enable_raw(); |
| 5792 | boolean text_needed = sdef->hasText && enable_text(); |
| 5793 | boolean xer_needed = sdef->hasXer && enable_xer(); |
| 5794 | boolean json_needed = sdef->hasJson && enable_json(); |
| 5795 | |
| 5796 | def = mputprintf(def, |
| 5797 | #ifndef NDEBUG |
| 5798 | "// written by %s in " __FILE__ " at line %d\n" |
| 5799 | #endif |
| 5800 | "class %s : public Base_Type {\n" |
| 5801 | "boolean bound_flag;\n" |
| 5802 | "public:\n" |
| 5803 | #ifndef NDEBUG |
| 5804 | , __FUNCTION__, __LINE__ |
| 5805 | #endif |
| 5806 | , name); |
| 5807 | |
| 5808 | /* default ctor */ |
| 5809 | def = mputprintf(def, "%s();\n", name); |
| 5810 | src = mprintf("%s::%s()\n" |
| 5811 | "{\n" |
| 5812 | "bound_flag = FALSE;\n" |
| 5813 | "}\n\n", name, name); |
| 5814 | |
| 5815 | /* ctor from NULL_VALUE (i.e. {}) */ |
| 5816 | def = mputprintf(def, "%s(null_type other_value);\n", name); |
| 5817 | src = mputprintf(src, "%s::%s(null_type)\n" |
| 5818 | "{\n" |
| 5819 | "bound_flag = TRUE;\n" |
| 5820 | "}\n\n", name, name); |
| 5821 | |
| 5822 | /* copy ctor */ |
| 5823 | def = mputprintf(def, "%s(const %s& other_value);\n", name, name); |
| 5824 | src = mputprintf(src, "%s::%s(const %s& other_value)\n" |
| 5825 | "{\n" |
| 5826 | "other_value.must_bound(\"Copying an unbound value of " |
| 5827 | "type %s.\");\n" |
| 5828 | "bound_flag = TRUE;\n" |
| 5829 | "}\n\n", name, name, name, dispname); |
| 5830 | |
| 5831 | /* assignment op: from NULL_VALUE */ |
| 5832 | def = mputprintf(def, "%s& operator=(null_type other_value);\n", name); |
| 5833 | src = mputprintf(src, "%s& %s::operator=(null_type)\n" |
| 5834 | "{\n" |
| 5835 | "bound_flag = TRUE;\n" |
| 5836 | "return *this;\n" |
| 5837 | "}\n\n", name, name); |
| 5838 | |
| 5839 | /* assignment op: from itself */ |
| 5840 | def = mputprintf(def, "%s& operator=(const %s& other_value);\n", name, |
| 5841 | name); |
| 5842 | src = mputprintf(src, "%s& %s::operator=(const %s& other_value)\n" |
| 5843 | "{\n" |
| 5844 | "other_value.must_bound(\"Assignment of an unbound value of type " |
| 5845 | "%s.\");\n" |
| 5846 | "bound_flag = TRUE;\n" |
| 5847 | "return *this;\n" |
| 5848 | "}\n\n", name, name, name, dispname); |
| 5849 | |
| 5850 | /* comparison op: with NULL_VALUE */ |
| 5851 | def = mputstr(def, "boolean operator==(null_type other_value) const;\n"); |
| 5852 | src = mputprintf(src, |
| 5853 | "boolean %s::operator==(null_type) const\n" |
| 5854 | "{\n" |
| 5855 | "must_bound(\"Comparison of an unbound value of type %s.\");\n" |
| 5856 | "return TRUE;\n" |
| 5857 | "}\n\n", name, dispname); |
| 5858 | |
| 5859 | /* comparison op: with itself */ |
| 5860 | def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n", |
| 5861 | name); |
| 5862 | src = mputprintf(src, |
| 5863 | "boolean %s::operator==(const %s& other_value) const\n" |
| 5864 | "{\n" |
| 5865 | "must_bound(\"Comparison of an unbound value of type %s.\");\n" |
| 5866 | "other_value.must_bound(\"Comparison of an unbound value of type " |
| 5867 | "%s.\");\n" |
| 5868 | "return TRUE;\n" |
| 5869 | "}\n\n", name, name, dispname, dispname); |
| 5870 | |
| 5871 | /* non-equal operators */ |
| 5872 | def = mputprintf(def, |
| 5873 | "inline boolean operator!=(null_type other_value) const " |
| 5874 | "{ return !(*this == other_value); }\n" |
| 5875 | "inline boolean operator!=(const %s& other_value) const " |
| 5876 | "{ return !(*this == other_value); }\n", name); |
| 5877 | |
| 5878 | |
| 5879 | /* is_bound function */ |
| 5880 | def = mputstr(def, "inline boolean is_bound() const " |
| 5881 | "{ return bound_flag; }\n"); |
| 5882 | |
| 5883 | /* is_present function */ |
| 5884 | def = mputstr(def, |
| 5885 | "inline boolean is_present() const { return is_bound(); }\n"); |
| 5886 | |
| 5887 | /* is_value function */ |
| 5888 | def = mputstr(def, "inline boolean is_value() const " |
| 5889 | "{ return bound_flag; }\n"); |
| 5890 | |
| 5891 | /* clean_up function */ |
| 5892 | def = mputstr(def, "inline void clean_up() " |
| 5893 | "{ bound_flag = FALSE; }\n"); |
| 5894 | |
| 5895 | /* must_bound function */ |
| 5896 | def = mputstr(def, "inline void must_bound(const char *err_msg) const " |
| 5897 | "{ if (!bound_flag) TTCN_error(\"%s\", err_msg); }\n"); |
| 5898 | |
| 5899 | /* log function */ |
| 5900 | def = mputstr(def, "void log() const;\n"); |
| 5901 | src = mputprintf(src, "void %s::log() const\n" |
| 5902 | "{\n" |
| 5903 | "if (bound_flag) TTCN_Logger::log_event_str(\"{ }\");\n" |
| 5904 | "else TTCN_Logger::log_event_unbound();\n" |
| 5905 | "}\n\n", name); |
| 5906 | |
| 5907 | /* set_param function */ |
| 5908 | def = mputstr(def, "void set_param(Module_Param& param);\n"); |
| 5909 | src = mputprintf(src, "void %s::set_param(Module_Param& param)\n" |
| 5910 | "{\n" |
| 5911 | " param.basic_check(Module_Param::BC_VALUE, \"empty record/set value (i.e. { })\");\n" |
| 5912 | " Module_Param_Ptr mp = ¶m;\n" |
| 5913 | " if (param.get_type() == Module_Param::MP_Reference) {\n" |
| 5914 | " mp = param.get_referenced_param();\n" |
| 5915 | " }\n" |
| 5916 | " if (mp->get_type()!=Module_Param::MP_Value_List || mp->get_size()>0) {\n" |
| 5917 | " param.type_error(\"empty record/set value (i.e. { })\", \"%s\");\n" |
| 5918 | " }\n" |
| 5919 | " bound_flag = TRUE;\n" |
| 5920 | "}\n\n", name, dispname); |
| 5921 | |
| 5922 | /* get param function */ |
| 5923 | def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); |
| 5924 | src = mputprintf(src, |
| 5925 | "Module_Param* %s::get_param(Module_Param_Name& /* param_name */) const\n" |
| 5926 | "{\n" |
| 5927 | " if (!is_bound()) {\n" |
| 5928 | " return new Module_Param_Unbound();\n" |
| 5929 | " }\n" |
| 5930 | " return new Module_Param_Value_List();\n" |
| 5931 | "}\n\n", name); |
| 5932 | |
| 5933 | /* encode_text function */ |
| 5934 | def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); |
| 5935 | src = mputprintf(src, "void %s::encode_text(Text_Buf& /*text_buf*/) const\n" |
| 5936 | "{\n" |
| 5937 | "must_bound(\"Text encoder: Encoding an unbound value of type %s.\");\n" |
| 5938 | "}\n\n", name, dispname); |
| 5939 | |
| 5940 | /* decode_text function */ |
| 5941 | def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); |
| 5942 | src = mputprintf(src, "void %s::decode_text(Text_Buf& /*text_buf*/)\n" |
| 5943 | "{\n" |
| 5944 | "bound_flag = TRUE;\n" |
| 5945 | "}\n\n", name); |
| 5946 | |
| 5947 | if(ber_needed || raw_needed || text_needed || xer_needed || json_needed) |
| 5948 | def_encdec(name, &def, &src, ber_needed, raw_needed, |
| 5949 | text_needed, xer_needed, json_needed, FALSE); |
| 5950 | |
| 5951 | /* BER functions */ |
| 5952 | if(ber_needed) { |
| 5953 | /* BER_encode_TLV() */ |
| 5954 | src=mputprintf |
| 5955 | (src, |
| 5956 | "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td," |
| 5957 | " unsigned p_coding) const\n" |
| 5958 | "{\n" |
| 5959 | " BER_chk_descr(p_td);\n" |
| 5960 | " ASN_BER_TLV_t *new_tlv=ASN_BER_TLV_t::construct(NULL);\n" |
| 5961 | " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n" |
| 5962 | " return new_tlv;\n" |
| 5963 | "}\n" |
| 5964 | "\n" |
| 5965 | , name |
| 5966 | ); |
| 5967 | |
| 5968 | /* BER_decode_TLV() */ |
| 5969 | src=mputprintf |
| 5970 | (src, |
| 5971 | "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td," |
| 5972 | " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n" |
| 5973 | "{\n" |
| 5974 | " BER_chk_descr(p_td);\n" |
| 5975 | " ASN_BER_TLV_t stripped_tlv;\n" |
| 5976 | " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n" |
| 5977 | " TTCN_EncDec_ErrorContext ec_0(\"While decoding '%s' type: \");\n" |
| 5978 | " stripped_tlv.chk_constructed_flag(TRUE);\n" |
| 5979 | " bound_flag=TRUE;\n" |
| 5980 | " return TRUE;\n" |
| 5981 | "}\n" |
| 5982 | "\n" |
| 5983 | , name, sdef->dispname |
| 5984 | ); |
| 5985 | } /* if ber_needed */ |
| 5986 | if(text_needed){ |
| 5987 | src = mputprintf(src, |
| 5988 | "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td," |
| 5989 | "TTCN_Buffer& p_buf) const{\n" |
| 5990 | " int encoded_length=0;\n" |
| 5991 | " if(p_td.text->begin_encode){\n" |
| 5992 | " p_buf.put_cs(*p_td.text->begin_encode);\n" |
| 5993 | " encoded_length+=p_td.text->begin_encode->lengthof();\n" |
| 5994 | " }\n" |
| 5995 | " if(!bound_flag) {\n" |
| 5996 | " TTCN_EncDec_ErrorContext::error\n" |
| 5997 | " (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value.\");\n" |
| 5998 | " }\n" |
| 5999 | " if(p_td.text->end_encode){\n" |
| 6000 | " p_buf.put_cs(*p_td.text->end_encode);\n" |
| 6001 | " encoded_length+=p_td.text->end_encode->lengthof();\n" |
| 6002 | " }\n" |
| 6003 | " return encoded_length;\n" |
| 6004 | "}\n" |
| 6005 | ,name |
| 6006 | ); |
| 6007 | src = mputprintf(src, |
| 6008 | "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td," |
| 6009 | " TTCN_Buffer& p_buf, Limit_Token_List& limit, boolean no_err, boolean){\n" |
| 6010 | " bound_flag = TRUE;\n" |
| 6011 | " int decoded_length=0;\n" |
| 6012 | " if(p_td.text->begin_decode){\n" |
| 6013 | " int tl;\n" |
| 6014 | " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n" |
| 6015 | " if(no_err)return -1;\n" |
| 6016 | " TTCN_EncDec_ErrorContext::error\n" |
| 6017 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" |
| 6018 | " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)" |
| 6019 | ", p_td.name);\n" |
| 6020 | " return 0;\n" |
| 6021 | " }\n" |
| 6022 | " decoded_length+=tl;\n" |
| 6023 | " p_buf.increase_pos(tl);\n" |
| 6024 | " }\n" |
| 6025 | " if(p_td.text->end_decode){\n" |
| 6026 | " int tl;\n" |
| 6027 | " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n" |
| 6028 | " if(no_err)return -1;\n" |
| 6029 | " TTCN_EncDec_ErrorContext::error\n" |
| 6030 | " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'" |
| 6031 | " not found for '%%s': \",(const char*)*(p_td.text->end_decode)" |
| 6032 | ", p_td.name);\n" |
| 6033 | " return 0;\n" |
| 6034 | " }\n" |
| 6035 | " decoded_length+=tl;\n" |
| 6036 | " p_buf.increase_pos(tl);\n" |
| 6037 | " }\n" |
| 6038 | " return decoded_length;\n" |
| 6039 | "}\n" |
| 6040 | ,name |
| 6041 | ); |
| 6042 | |
| 6043 | } |
| 6044 | /* RAW functions */ |
| 6045 | if (raw_needed) { |
| 6046 | src = mputprintf(src, |
| 6047 | "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td, " |
| 6048 | "RAW_enc_tree& /*myleaf*/) const\n" |
| 6049 | "{\n" |
| 6050 | "if (!bound_flag) TTCN_EncDec_ErrorContext::error" |
| 6051 | "(TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value of " |
| 6052 | "type %%s.\", p_td.name);\n" |
| 6053 | "return 0;\n" |
| 6054 | "}\n\n", name); |
| 6055 | |
| 6056 | src = mputprintf(src, |
| 6057 | "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td, " |
| 6058 | "TTCN_Buffer& p_buf, int, raw_order_t, boolean, int, boolean)\n" |
| 6059 | "{\n" |
| 6060 | "bound_flag = TRUE;\n" |
| 6061 | "return p_buf.increase_pos_padd(p_td.raw->prepadding) + " |
| 6062 | "p_buf.increase_pos_padd(p_td.raw->padding);\n" |
| 6063 | "}\n\n", name); |
| 6064 | } |
| 6065 | |
| 6066 | if (xer_needed) { /* XERSTUFF codegen for empty record/SEQUENCE */ |
| 6067 | src=mputprintf(src, |
| 6068 | "boolean %s::can_start(const char *p_name, const char *p_uri, " |
| 6069 | "const XERdescriptor_t& p_td, unsigned int p_flavor) {\n" |
| 6070 | " boolean e_xer = is_exer(p_flavor);\n" |
| 6071 | " if (e_xer && (p_td.xer_bits & UNTAGGED)) return false;\n" |
| 6072 | " else return check_name(p_name, p_td, e_xer) && (!e_xer || check_namespace(p_uri, p_td));\n" |
| 6073 | "}\n\n" |
| 6074 | , name |
| 6075 | |
| 6076 | ); |
| 6077 | src = mputprintf(src, |
| 6078 | "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, " |
| 6079 | "unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const{\n" |
| 6080 | " int encoded_length=(int)p_buf.get_len();\n" |
| 6081 | " int is_indented = !is_canonical(p_flavor);\n" |
| 6082 | " int e_xer = is_exer(p_flavor);\n" |
| 6083 | " if (is_indented) do_indent(p_buf, p_indent);\n" |
| 6084 | " p_buf.put_c('<');\n" |
| 6085 | " if (e_xer) write_ns_prefix(p_td, p_buf);\n" |
| 6086 | " p_buf.put_s((size_t)p_td.namelens[e_xer]-2, (cbyte*)p_td.names[e_xer]);\n" |
| 6087 | " p_buf.put_s(2 + is_indented, (cbyte*)\"/>\\n\");\n" |
| 6088 | " return (int)p_buf.get_len() - encoded_length;\n" |
| 6089 | "}\n\n" |
| 6090 | , name); |
| 6091 | src = mputprintf(src, |
| 6092 | #ifndef NDEBUG |
| 6093 | "// written by %s in " __FILE__ " at %d\n" |
| 6094 | #endif |
| 6095 | "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader, " |
| 6096 | "unsigned int p_flavor, embed_values_dec_struct_t*)\n" |
| 6097 | "{\n" |
| 6098 | " int e_xer = is_exer(p_flavor);\n" |
| 6099 | " bound_flag = true;\n" |
| 6100 | " int rd_ok, depth=-1;\n" |
| 6101 | " for (rd_ok=p_reader.Ok(); rd_ok==1; rd_ok=p_reader.Read()) {\n" |
| 6102 | " int type = p_reader.NodeType();\n" |
| 6103 | " if (type==XML_READER_TYPE_ELEMENT) {\n" |
| 6104 | " verify_name(p_reader, p_td, e_xer);\n" |
| 6105 | " depth=p_reader.Depth();\n" |
| 6106 | " if (p_reader.IsEmptyElement()) {\n" |
| 6107 | " rd_ok = p_reader.Read(); break;\n" |
| 6108 | " }\n" |
| 6109 | " else if ((p_flavor & XER_MASK) == XER_CANONICAL) {\n" |
| 6110 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG, " |
| 6111 | "\"Expected an empty element tag\");\n" |
| 6112 | " }\n" |
| 6113 | " }\n" |
| 6114 | " else if (type == XML_READER_TYPE_END_ELEMENT && depth != -1) {\n" |
| 6115 | " verify_end(p_reader, p_td, depth, e_xer);\n" |
| 6116 | " rd_ok = p_reader.Read(); break;\n" |
| 6117 | " }\n" |
| 6118 | " }\n" |
| 6119 | " return 1;\n" |
| 6120 | "}\n\n" |
| 6121 | #ifndef NDEBUG |
| 6122 | , __FUNCTION__, __LINE__ |
| 6123 | #endif |
| 6124 | , name); |
| 6125 | } |
| 6126 | if (json_needed) { |
| 6127 | // JSON encode, RT1 |
| 6128 | src = mputprintf(src, |
| 6129 | "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n" |
| 6130 | "{\n" |
| 6131 | " if (!is_bound()) {\n" |
| 6132 | " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n" |
| 6133 | " \"Encoding an unbound value of type %s.\");\n" |
| 6134 | " return -1;\n" |
| 6135 | " }\n\n" |
| 6136 | " return p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL) + \n" |
| 6137 | " p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);\n" |
| 6138 | "}\n\n" |
| 6139 | , name, dispname); |
| 6140 | |
| 6141 | // JSON decode, RT1 |
| 6142 | src = mputprintf(src, |
| 6143 | "int %s::JSON_decode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok, boolean p_silent)\n" |
| 6144 | "{\n" |
| 6145 | " json_token_t token = JSON_TOKEN_NONE;\n" |
| 6146 | " int dec_len = p_tok.get_next_token(&token, NULL, NULL);\n" |
| 6147 | " if (JSON_TOKEN_ERROR == token) {\n" |
| 6148 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n" |
| 6149 | " return JSON_ERROR_FATAL;\n" |
| 6150 | " }\n" |
| 6151 | " else if (JSON_TOKEN_OBJECT_START != token) {\n" |
| 6152 | " return JSON_ERROR_INVALID_TOKEN;\n" |
| 6153 | " }\n\n" |
| 6154 | " dec_len += p_tok.get_next_token(&token, NULL, NULL);\n" |
| 6155 | " if (JSON_TOKEN_OBJECT_END != token) {\n" |
| 6156 | " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_STATIC_OBJECT_END_TOKEN_ERROR, \"\");\n" |
| 6157 | " return JSON_ERROR_FATAL;\n" |
| 6158 | " }\n\n" |
| 6159 | " bound_flag = true;\n\n" |
| 6160 | " return dec_len;\n" |
| 6161 | "}\n\n" |
| 6162 | , name); |
| 6163 | } |
| 6164 | |
| 6165 | /* closing class definition */ |
| 6166 | def = mputstr(def, "};\n\n"); |
| 6167 | |
| 6168 | output->header.class_defs = mputstr(output->header.class_defs, def); |
| 6169 | Free(def); |
| 6170 | |
| 6171 | output->source.methods = mputstr(output->source.methods, src); |
| 6172 | Free(src); |
| 6173 | |
| 6174 | output->header.function_prototypes = |
| 6175 | mputprintf(output->header.function_prototypes, |
| 6176 | "extern boolean operator==(null_type null_value, const %s& " |
| 6177 | "other_value);\n", name); |
| 6178 | output->source.function_bodies = |
| 6179 | mputprintf(output->source.function_bodies, |
| 6180 | "boolean operator==(null_type, const %s& other_value)\n" |
| 6181 | "{\n" |
| 6182 | "other_value.must_bound(\"Comparison of an unbound value of type " |
| 6183 | "%s.\");\n" |
| 6184 | "return TRUE;\n" |
| 6185 | "}\n\n", name, dispname); |
| 6186 | |
| 6187 | output->header.function_prototypes = |
| 6188 | mputprintf(output->header.function_prototypes, |
| 6189 | "inline boolean operator!=(null_type null_value, const %s& " |
| 6190 | "other_value) " |
| 6191 | "{ return !(null_value == other_value); }\n", name); |
| 6192 | } |
| 6193 | |
| 6194 | static void defEmptyRecordTemplate(const char *name, const char *dispname, |
| 6195 | output_struct *output) |
| 6196 | { |
| 6197 | char *def = NULL, *src = NULL; |
| 6198 | |
| 6199 | /* class definition */ |
| 6200 | def = mprintf("class %s_template : public Base_Template {\n" |
| 6201 | "struct {\n" |
| 6202 | "unsigned int n_values;\n" |
| 6203 | "%s_template *list_value;\n" |
| 6204 | "} value_list;\n", name, name); |
| 6205 | |
| 6206 | /* copy_template function */ |
| 6207 | def = mputprintf(def, "void copy_template(const %s_template& " |
| 6208 | "other_value);\n\n", name); |
| 6209 | src = mputprintf(src, |
| 6210 | "void %s_template::copy_template(const %s_template& other_value)\n" |
| 6211 | "{\n" |
| 6212 | "set_selection(other_value);\n" |
| 6213 | "switch (template_selection) {\n" |
| 6214 | "case OMIT_VALUE:\n" |
| 6215 | "case ANY_VALUE:\n" |
| 6216 | "case ANY_OR_OMIT:\n" |
| 6217 | "case SPECIFIC_VALUE:\n" |
| 6218 | "break;\n" |
| 6219 | "case VALUE_LIST:\n" |
| 6220 | "case COMPLEMENTED_LIST:\n" |
| 6221 | "value_list.n_values = other_value.value_list.n_values;\n" |
| 6222 | "value_list.list_value = new %s_template[value_list.n_values];\n" |
| 6223 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 6224 | "list_count++)\n" |
| 6225 | "value_list.list_value[list_count].copy_template(" |
| 6226 | "other_value.value_list.list_value[list_count]);\n" |
| 6227 | "break;\n" |
| 6228 | "default:\n" |
| 6229 | "TTCN_error(\"Copying an uninitialized/unsupported template of type " |
| 6230 | "%s.\");\n" |
| 6231 | "break;\n" |
| 6232 | "}\n" |
| 6233 | "}\n\n", name, name, name, dispname); |
| 6234 | |
| 6235 | /* default ctor */ |
| 6236 | def = mputprintf(def, "public:\n" |
| 6237 | "%s_template();\n", name); |
| 6238 | src = mputprintf(src, "%s_template::%s_template()\n" |
| 6239 | "{\n" |
| 6240 | "}\n\n", name, name); |
| 6241 | |
| 6242 | /* ctor for generic wildcards */ |
| 6243 | def = mputprintf(def, "%s_template(template_sel other_value);\n", name); |
| 6244 | src = mputprintf(src, "%s_template::%s_template(template_sel other_value)\n" |
| 6245 | " : Base_Template(other_value)\n" |
| 6246 | "{\n" |
| 6247 | "check_single_selection(other_value);\n" |
| 6248 | "}\n\n", name, name); |
| 6249 | |
| 6250 | /* ctor for value {} */ |
| 6251 | def = mputprintf(def, "%s_template(null_type other_value);\n", name); |
| 6252 | src = mputprintf(src, "%s_template::%s_template(null_type)\n" |
| 6253 | " : Base_Template(SPECIFIC_VALUE)\n" |
| 6254 | "{\n" |
| 6255 | "}\n\n", name, name); |
| 6256 | |
| 6257 | /* ctor for specific value */ |
| 6258 | def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name); |
| 6259 | src = mputprintf(src, "%s_template::%s_template(const %s& other_value)\n" |
| 6260 | " : Base_Template(SPECIFIC_VALUE)\n" |
| 6261 | "{\n" |
| 6262 | "other_value.must_bound(\"Creating a template from an unbound value of " |
| 6263 | "type %s.\");\n" |
| 6264 | "}\n\n", name, name, name, dispname); |
| 6265 | |
| 6266 | /* ctor for optional value */ |
| 6267 | def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n", |
| 6268 | name, name); |
| 6269 | src = mputprintf(src, "%s_template::%s_template(const OPTIONAL<%s>& " |
| 6270 | "other_value)\n" |
| 6271 | "{\n" |
| 6272 | "switch (other_value.get_selection()) {\n" |
| 6273 | "case OPTIONAL_PRESENT:\n" |
| 6274 | "set_selection(SPECIFIC_VALUE);\n" |
| 6275 | "break;\n" |
| 6276 | "case OPTIONAL_OMIT:\n" |
| 6277 | "set_selection(OMIT_VALUE);\n" |
| 6278 | "break;\n" |
| 6279 | "default:\n" |
| 6280 | "TTCN_error(\"Creating a template of type %s from an unbound optional " |
| 6281 | "field.\");\n" |
| 6282 | "}\n" |
| 6283 | "}\n\n", name, name, name, dispname); |
| 6284 | |
| 6285 | /* copy ctor */ |
| 6286 | def = mputprintf(def, "%s_template(const %s_template& other_value);\n", |
| 6287 | name, name); |
| 6288 | src = mputprintf(src, "%s_template::%s_template(const %s_template& " |
| 6289 | "other_value)\n" |
| 6290 | ": Base_Template()" /* yes, the base class _default_ constructor */ |
| 6291 | "{\n" |
| 6292 | "copy_template(other_value);\n" |
| 6293 | "}\n\n", name, name, name); |
| 6294 | |
| 6295 | /* dtor */ |
| 6296 | def = mputprintf(def, "~%s_template();\n", name); |
| 6297 | src = mputprintf(src, "%s_template::~%s_template()\n" |
| 6298 | "{\n" |
| 6299 | "clean_up();\n" |
| 6300 | "}\n\n", name, name); |
| 6301 | |
| 6302 | /* clean_up function */ |
| 6303 | def = mputstr(def, "void clean_up();\n"); |
| 6304 | src = mputprintf(src, "void %s_template::clean_up()\n" |
| 6305 | "{\n" |
| 6306 | "if (template_selection == VALUE_LIST || " |
| 6307 | "template_selection == COMPLEMENTED_LIST)\n" |
| 6308 | "delete [] value_list.list_value;\n" |
| 6309 | "template_selection = UNINITIALIZED_TEMPLATE;\n" |
| 6310 | "}\n\n", name); |
| 6311 | |
| 6312 | /* assignment op for generic wildcards */ |
| 6313 | def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n", |
| 6314 | name); |
| 6315 | src = mputprintf(src, "%s_template& %s_template::operator=(template_sel " |
| 6316 | "other_value)\n" |
| 6317 | "{\n" |
| 6318 | "check_single_selection(other_value);\n" |
| 6319 | "clean_up();\n" |
| 6320 | "set_selection(other_value);\n" |
| 6321 | "return *this;\n" |
| 6322 | "}\n\n", name, name); |
| 6323 | |
| 6324 | /* assignment op for value {} */ |
| 6325 | def = mputprintf(def, "%s_template& operator=(null_type other_value);\n", |
| 6326 | name); |
| 6327 | src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n" |
| 6328 | "{\n" |
| 6329 | "clean_up();\n" |
| 6330 | "set_selection(SPECIFIC_VALUE);\n" |
| 6331 | "return *this;\n" |
| 6332 | "}\n\n", name, name); |
| 6333 | |
| 6334 | /* assignment op for specific value */ |
| 6335 | def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n", |
| 6336 | name, name); |
| 6337 | src = mputprintf(src, "%s_template& %s_template::operator=(const %s& " |
| 6338 | "other_value)\n" |
| 6339 | "{\n" |
| 6340 | "other_value.must_bound(\"Assignment of an unbound value of type %s " |
| 6341 | "to a template.\");\n" |
| 6342 | "clean_up();\n" |
| 6343 | "set_selection(SPECIFIC_VALUE);\n" |
| 6344 | "return *this;\n" |
| 6345 | "}\n\n", name, name, name, dispname); |
| 6346 | |
| 6347 | /* assignment op for optional value */ |
| 6348 | def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& " |
| 6349 | "other_value);\n", name, name); |
| 6350 | src = mputprintf(src, "%s_template& %s_template::operator=" |
| 6351 | "(const OPTIONAL<%s>& other_value)\n" |
| 6352 | "{\n" |
| 6353 | "clean_up();\n" |
| 6354 | "switch (other_value.get_selection()) {\n" |
| 6355 | "case OPTIONAL_PRESENT:\n" |
| 6356 | "set_selection(SPECIFIC_VALUE);\n" |
| 6357 | "break;\n" |
| 6358 | "case OPTIONAL_OMIT:\n" |
| 6359 | "set_selection(OMIT_VALUE);\n" |
| 6360 | "break;\n" |
| 6361 | "default:\n" |
| 6362 | "TTCN_error(\"Assignment of an unbound optional field to a template " |
| 6363 | "of type %s.\");\n" |
| 6364 | "}\n" |
| 6365 | "return *this;\n" |
| 6366 | "}\n\n", name, name, name, dispname); |
| 6367 | |
| 6368 | /* assignment op for itself */ |
| 6369 | def = mputprintf(def, "%s_template& operator=(const %s_template& " |
| 6370 | "other_value);\n", name, name); |
| 6371 | src = mputprintf(src, "%s_template& %s_template::operator=" |
| 6372 | "(const %s_template& other_value)\n" |
| 6373 | "{\n" |
| 6374 | "if (&other_value != this) {\n" |
| 6375 | "clean_up();\n" |
| 6376 | "set_selection(other_value);\n" |
| 6377 | "}\n" |
| 6378 | "return *this;\n" |
| 6379 | "}\n\n", name, name, name); |
| 6380 | |
| 6381 | /* match operation with {} */ |
| 6382 | def = mputstr(def, "boolean match(null_type other_value, boolean legacy " |
| 6383 | "= FALSE) const;\n"); |
| 6384 | src = mputprintf(src, "boolean %s_template::match(null_type other_value," |
| 6385 | "boolean) const\n" |
| 6386 | "{\n" |
| 6387 | "switch (template_selection) {\n" |
| 6388 | "case ANY_VALUE:\n" |
| 6389 | "case ANY_OR_OMIT:\n" |
| 6390 | "case SPECIFIC_VALUE:\n" |
| 6391 | "return TRUE;\n" |
| 6392 | "case OMIT_VALUE:\n" |
| 6393 | "return FALSE;\n" |
| 6394 | "case VALUE_LIST:\n" |
| 6395 | "case COMPLEMENTED_LIST:\n" |
| 6396 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 6397 | "list_count++)\n" |
| 6398 | "if (value_list.list_value[list_count].match(other_value)) " |
| 6399 | "return template_selection == VALUE_LIST;\n" |
| 6400 | "return template_selection == COMPLEMENTED_LIST;\n" |
| 6401 | "default:\n" |
| 6402 | "TTCN_error(\"Matching an uninitialized/unsupported template of " |
| 6403 | "type %s.\");\n" |
| 6404 | "}\n" |
| 6405 | "return FALSE;\n" |
| 6406 | "}\n\n", name, dispname); |
| 6407 | |
| 6408 | /* match operation with specific value */ |
| 6409 | def = mputprintf(def, "boolean match(const %s& other_value, boolean legacy " |
| 6410 | "= FALSE) const;\n", name); |
| 6411 | src = mputprintf(src, "boolean %s_template::match(const %s& other_value, " |
| 6412 | "boolean) const\n" |
| 6413 | "{\n" |
| 6414 | "if (!other_value.is_bound()) return FALSE;" |
| 6415 | "return match(NULL_VALUE);\n" |
| 6416 | "}\n\n", name, name); |
| 6417 | |
| 6418 | /* valueof operation */ |
| 6419 | def = mputprintf(def, "%s valueof() const;\n", name); |
| 6420 | src = mputprintf(src, "%s %s_template::valueof() const\n" |
| 6421 | "{\n" |
| 6422 | "if (template_selection != SPECIFIC_VALUE || is_ifpresent) " |
| 6423 | "TTCN_error(\"Performing a valueof or send operation on a " |
| 6424 | "non-specific template of type %s.\");\n" |
| 6425 | "return NULL_VALUE;\n" |
| 6426 | "}\n\n", name, name, dispname); |
| 6427 | |
| 6428 | /* void set_type(template_sel, int) function */ |
| 6429 | def = mputstr(def, |
| 6430 | "void set_type(template_sel template_type, " |
| 6431 | "unsigned int list_length);\n"); |
| 6432 | |
| 6433 | src = mputprintf(src, |
| 6434 | "void %s_template::set_type(template_sel template_type, " |
| 6435 | "unsigned int list_length)\n" |
| 6436 | "{\n" |
| 6437 | "if (template_type != VALUE_LIST " |
| 6438 | "&& template_type != COMPLEMENTED_LIST)\n" |
| 6439 | "TTCN_error(\"Setting an invalid list for a template of type %s.\");\n" |
| 6440 | "clean_up();\n" |
| 6441 | "set_selection(template_type);\n" |
| 6442 | "value_list.n_values = list_length;\n" |
| 6443 | "value_list.list_value = new %s_template[list_length];\n" |
| 6444 | "}\n\n", name, dispname, name); |
| 6445 | |
| 6446 | /* list_item(int) function */ |
| 6447 | |
| 6448 | def = mputprintf(def, |
| 6449 | "%s_template& list_item(unsigned int list_index) const;\n", name); |
| 6450 | |
| 6451 | src = mputprintf(src, |
| 6452 | "%s_template& %s_template::list_item(unsigned int list_index) const\n" |
| 6453 | "{\n" |
| 6454 | "if (template_selection != VALUE_LIST " |
| 6455 | "&& template_selection != COMPLEMENTED_LIST)\n" |
| 6456 | "TTCN_error(\"Accessing a list element of a non-list template of " |
| 6457 | "type %s.\");\n" |
| 6458 | "if (list_index >= value_list.n_values)\n" |
| 6459 | "TTCN_error(\"Index overflow in a value list template of type " |
| 6460 | "%s.\");\n" |
| 6461 | "return value_list.list_value[list_index];\n" |
| 6462 | "}\n\n", name, name, dispname, dispname); |
| 6463 | |
| 6464 | /* log function */ |
| 6465 | def = mputstr(def, "void log() const;\n"); |
| 6466 | src = mputprintf(src, "void %s_template::log() const\n" |
| 6467 | "{\n" |
| 6468 | "switch (template_selection) {\n" |
| 6469 | "case SPECIFIC_VALUE:\n" |
| 6470 | "TTCN_Logger::log_event_str(\"{ }\");\n" |
| 6471 | "break;\n" |
| 6472 | "case COMPLEMENTED_LIST:\n" |
| 6473 | "TTCN_Logger::log_event_str(\"complement \");\n" |
| 6474 | "case VALUE_LIST:\n" |
| 6475 | "TTCN_Logger::log_char('(');\n" |
| 6476 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 6477 | "list_count++) {\n" |
| 6478 | "if (list_count > 0) TTCN_Logger::log_event_str(\", \");\n" |
| 6479 | "value_list.list_value[list_count].log();\n" |
| 6480 | "}\n" |
| 6481 | "TTCN_Logger::log_char(')');\n" |
| 6482 | "break;\n" |
| 6483 | "default:\n" |
| 6484 | "log_generic();\n" |
| 6485 | "}\n" |
| 6486 | "log_ifpresent();\n" |
| 6487 | "}\n\n", name); |
| 6488 | |
| 6489 | /* log_match function */ |
| 6490 | def = mputprintf(def, "void log_match(const %s& match_value, " |
| 6491 | "boolean legacy = FALSE) const;\n", name); |
| 6492 | src = mputprintf(src, "void %s_template::log_match(const %s& match_value, " |
| 6493 | "boolean) const\n" |
| 6494 | "{\n" |
| 6495 | "match_value.log();\n" |
| 6496 | "TTCN_Logger::log_event_str(\" with \");\n" |
| 6497 | "log();\n" |
| 6498 | "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n" |
| 6499 | "else TTCN_Logger::log_event_str(\" unmatched\");\n" |
| 6500 | "}\n\n", name, name); |
| 6501 | |
| 6502 | /* encode_text function */ |
| 6503 | def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n"); |
| 6504 | src = mputprintf(src, "void %s_template::encode_text(Text_Buf& text_buf) " |
| 6505 | "const\n" |
| 6506 | "{\n" |
| 6507 | "encode_text_base(text_buf);\n" |
| 6508 | "switch (template_selection) {\n" |
| 6509 | "case OMIT_VALUE:\n" |
| 6510 | "case ANY_VALUE:\n" |
| 6511 | "case ANY_OR_OMIT:\n" |
| 6512 | "case SPECIFIC_VALUE:\n" |
| 6513 | "break;\n" |
| 6514 | "case VALUE_LIST:\n" |
| 6515 | "case COMPLEMENTED_LIST:\n" |
| 6516 | "text_buf.push_int(value_list.n_values);\n" |
| 6517 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 6518 | "list_count++)\n" |
| 6519 | "value_list.list_value[list_count].encode_text(text_buf);\n" |
| 6520 | "break;\n" |
| 6521 | "default:\n" |
| 6522 | "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported " |
| 6523 | "template of type %s.\");\n" |
| 6524 | "}\n" |
| 6525 | "}\n\n", name, dispname); |
| 6526 | |
| 6527 | /* decode_text function */ |
| 6528 | def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n"); |
| 6529 | src = mputprintf(src, "void %s_template::decode_text(Text_Buf& text_buf)\n" |
| 6530 | "{\n" |
| 6531 | "clean_up();\n" |
| 6532 | "decode_text_base(text_buf);\n" |
| 6533 | "switch (template_selection) {\n" |
| 6534 | "case OMIT_VALUE:\n" |
| 6535 | "case ANY_VALUE:\n" |
| 6536 | "case ANY_OR_OMIT:\n" |
| 6537 | "case SPECIFIC_VALUE:\n" |
| 6538 | "break;\n" |
| 6539 | "case VALUE_LIST:\n" |
| 6540 | "case COMPLEMENTED_LIST:\n" |
| 6541 | "value_list.n_values = text_buf.pull_int().get_val();\n" |
| 6542 | "value_list.list_value = new %s_template[value_list.n_values];\n" |
| 6543 | "for (unsigned int list_count = 0; list_count < value_list.n_values; " |
| 6544 | "list_count++)\n" |
| 6545 | "value_list.list_value[list_count].decode_text(text_buf);\n" |
| 6546 | "break;\n" |
| 6547 | "default:\n" |
| 6548 | "TTCN_error(\"Text decoder: An unknown/unsupported selection was " |
| 6549 | "received in a template of type %s.\");\n" |
| 6550 | "}\n" |
| 6551 | "}\n\n", name, name, dispname); |
| 6552 | |
| 6553 | /* set_param() */ |
| 6554 | def = mputstr(def, "void set_param(Module_Param& param);\n"); |
| 6555 | src = mputprintf(src, |
| 6556 | "void %s_template::set_param(Module_Param& param)\n" |
| 6557 | "{\n" |
| 6558 | " param.basic_check(Module_Param::BC_TEMPLATE, \"empty record/set template\");\n" |
| 6559 | " Module_Param_Ptr mp = ¶m;\n" |
| 6560 | " if (param.get_type() == Module_Param::MP_Reference) {\n" |
| 6561 | " mp = param.get_referenced_param();\n" |
| 6562 | " }\n" |
| 6563 | " switch (mp->get_type()) {\n" |
| 6564 | " case Module_Param::MP_Omit:\n" |
| 6565 | " *this = OMIT_VALUE;\n" |
| 6566 | " break;\n" |
| 6567 | " case Module_Param::MP_Any:\n" |
| 6568 | " *this = ANY_VALUE;\n" |
| 6569 | " break;\n" |
| 6570 | " case Module_Param::MP_AnyOrNone:\n" |
| 6571 | " *this = ANY_OR_OMIT;\n" |
| 6572 | " break;\n" |
| 6573 | " case Module_Param::MP_List_Template:\n" |
| 6574 | " case Module_Param::MP_ComplementList_Template: {\n" |
| 6575 | " %s_template temp;\n" |
| 6576 | " temp.set_type(mp->get_type()==Module_Param::MP_List_Template ? " |
| 6577 | "VALUE_LIST : COMPLEMENTED_LIST, mp->get_size());\n" |
| 6578 | " for (size_t p_i=0; p_i<mp->get_size(); p_i++) {\n" |
| 6579 | " temp.list_item(p_i).set_param(*mp->get_elem(p_i));\n" |
| 6580 | " }\n" |
| 6581 | " *this = temp;\n" |
| 6582 | " break; }\n" |
| 6583 | " case Module_Param::MP_Value_List:\n" |
| 6584 | " if (mp->get_size()>0) param.type_error(\"empty record/set template\", \"%s\");\n" |
| 6585 | " *this = NULL_VALUE;\n" |
| 6586 | " break;\n" |
| 6587 | " default:\n" |
| 6588 | " param.type_error(\"empty record/set template\", \"%s\");\n" |
| 6589 | " }\n" |
| 6590 | " is_ifpresent = param.get_ifpresent() || mp->get_ifpresent();\n" |
| 6591 | "}\n\n", name, name, dispname, dispname); |
| 6592 | |
| 6593 | /* get_param() */ |
| 6594 | def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n"); |
| 6595 | src = mputprintf(src, |
| 6596 | "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n" |
| 6597 | "{\n" |
| 6598 | " Module_Param* mp = NULL;\n" |
| 6599 | " switch (template_selection) {\n" |
| 6600 | " case UNINITIALIZED_TEMPLATE:\n" |
| 6601 | " mp = new Module_Param_Unbound();\n" |
| 6602 | " break;\n" |
| 6603 | " case OMIT_VALUE:\n" |
| 6604 | " mp = new Module_Param_Omit();\n" |
| 6605 | " break;\n" |
| 6606 | " case ANY_VALUE:\n" |
| 6607 | " mp = new Module_Param_Any();\n" |
| 6608 | " break;\n" |
| 6609 | " case ANY_OR_OMIT:\n" |
| 6610 | " mp = new Module_Param_AnyOrNone();\n" |
| 6611 | " break;\n" |
| 6612 | " case SPECIFIC_VALUE:\n" |
| 6613 | " mp = new Module_Param_Value_List();\n" |
| 6614 | " break;\n" |
| 6615 | " case VALUE_LIST:\n" |
| 6616 | " case COMPLEMENTED_LIST: {\n" |
| 6617 | " if (template_selection == VALUE_LIST) {\n" |
| 6618 | " mp = new Module_Param_List_Template();\n" |
| 6619 | " }\n" |
| 6620 | " else {\n" |
| 6621 | " mp = new Module_Param_ComplementList_Template();\n" |
| 6622 | " }\n" |
| 6623 | " for (size_t i = 0; i < value_list.n_values; ++i) {\n" |
| 6624 | " mp->add_elem(value_list.list_value[i].get_param(param_name));\n" |
| 6625 | " }\n" |
| 6626 | " break; }\n" |
| 6627 | " default:\n" |
| 6628 | " break;\n" |
| 6629 | " }\n" |
| 6630 | " if (is_ifpresent) {\n" |
| 6631 | " mp->set_ifpresent();\n" |
| 6632 | " }\n" |
| 6633 | " return mp;\n" |
| 6634 | "}\n\n", name); |
| 6635 | |
| 6636 | /* check template restriction */ |
| 6637 | def = mputstr(def, "void check_restriction(template_res t_res, " |
| 6638 | "const char* t_name=NULL, boolean legacy = FALSE) const;\n"); |
| 6639 | src = mputprintf(src, |
| 6640 | "void %s_template::check_restriction(" |
| 6641 | "template_res t_res, const char* t_name, boolean legacy) const\n" |
| 6642 | "{\n" |
| 6643 | "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n" |
| 6644 | "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n" |
| 6645 | "case TR_OMIT:\n" |
| 6646 | "if (template_selection==OMIT_VALUE) return;\n" |
| 6647 | "case TR_VALUE:\n" |
| 6648 | "if (template_selection!=SPECIFIC_VALUE || is_ifpresent) break;\n" |
| 6649 | "return;\n" |
| 6650 | "case TR_PRESENT:\n" |
| 6651 | "if (!match_omit(legacy)) return;\n" |
| 6652 | "break;\n" |
| 6653 | "default:\n" |
| 6654 | "return;\n" |
| 6655 | "}\n" |
| 6656 | "TTCN_error(\"Restriction `%%s' on template of type %%s " |
| 6657 | "violated.\", get_res_name(t_res), t_name ? t_name : \"%s\");\n" |
| 6658 | "}\n\n", name, dispname); |
| 6659 | |
| 6660 | defCommonRecordTemplate(name, &def, &src); |
| 6661 | |
| 6662 | def = mputstr(def, "};\n\n"); |
| 6663 | |
| 6664 | output->header.class_defs = mputstr(output->header.class_defs, def); |
| 6665 | Free(def); |
| 6666 | |
| 6667 | output->source.methods = mputstr(output->source.methods, src); |
| 6668 | Free(src); |
| 6669 | } |
| 6670 | |
| 6671 | static void defCommonRecordTemplate(const char *name, |
| 6672 | char **def, char **src) |
| 6673 | { |
| 6674 | /* TTCN-3 ispresent() function */ |
| 6675 | *def = mputstr(*def, "boolean is_present(boolean legacy = FALSE) const;\n"); |
| 6676 | *src = mputprintf(*src, |
| 6677 | "boolean %s_template::is_present(boolean legacy) const\n" |
| 6678 | "{\n" |
| 6679 | "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n" |
| 6680 | "return !match_omit(legacy);\n" |
| 6681 | "}\n\n", name); |
| 6682 | |
| 6683 | /* match_omit() */ |
| 6684 | *def = mputstr(*def, "boolean match_omit(boolean legacy = FALSE) const;\n"); |
| 6685 | *src = mputprintf(*src, |
| 6686 | "boolean %s_template::match_omit(boolean legacy) const\n" |
| 6687 | "{\n" |
| 6688 | "if (is_ifpresent) return TRUE;\n" |
| 6689 | "switch (template_selection) {\n" |
| 6690 | "case OMIT_VALUE:\n" |
| 6691 | "case ANY_OR_OMIT:\n" |
| 6692 | "return TRUE;\n" |
| 6693 | "case VALUE_LIST:\n" |
| 6694 | "case COMPLEMENTED_LIST:\n" |
| 6695 | "if (legacy) {\n" |
| 6696 | "for (unsigned int l_idx=0; l_idx<value_list.n_values; l_idx++)\n" |
| 6697 | "if (value_list.list_value[l_idx].match_omit())\n" |
| 6698 | "return template_selection==VALUE_LIST;\n" |
| 6699 | "return template_selection==COMPLEMENTED_LIST;\n" |
| 6700 | "} // else fall through\n" |
| 6701 | "default:\n" |
| 6702 | "return FALSE;\n" |
| 6703 | "}\n" |
| 6704 | "return FALSE;\n" |
| 6705 | "}\n\n", name); |
| 6706 | } |
| 6707 | |
| 6708 | /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ |
| 6709 | |
| 6710 | void defRecordClass2(const struct_def *sdef, output_struct *output) |
| 6711 | { |
| 6712 | size_t i; |
| 6713 | size_t optional_num = 0; |
| 6714 | const char *name = sdef->name; |
| 6715 | char *def = NULL, *src = NULL; |
| 6716 | |
| 6717 | boolean xer_needed = sdef->hasXer && enable_xer(); |
| 6718 | boolean raw_needed = sdef->hasRaw && enable_raw(); |
| 6719 | boolean has_optional = FALSE; |
| 6720 | boolean has_default = FALSE; |
| 6721 | |
| 6722 | const char* base_class = (sdef->nElements==0) ? "Empty_Record_Type" : "Record_Type"; |
| 6723 | |
| 6724 | /* class declaration code */ |
| 6725 | output->header.class_decls = mputprintf(output->header.class_decls, |
| 6726 | "class %s;\n", name); |
| 6727 | |
| 6728 | /* class definition and source code */ |
| 6729 | def=mputprintf(def, "class %s : public %s {\n", name, base_class); |
| 6730 | |
| 6731 | /* data members */ |
| 6732 | for (i = 0; i < sdef->nElements; i++) { |
| 6733 | if(sdef->elements[i].isOptional) { |
| 6734 | optional_num++; |
| 6735 | def = mputprintf(def, " OPTIONAL<%s> field_%s;\n", |
| 6736 | sdef->elements[i].type, |
| 6737 | sdef->elements[i].name); |
| 6738 | } else { |
| 6739 | def = mputprintf(def, " %s field_%s;\n", |
| 6740 | sdef->elements[i].type, sdef->elements[i].name); |
| 6741 | } |
| 6742 | } |
| 6743 | if (sdef->nElements) { |
| 6744 | def = mputprintf(def, " Base_Type* fld_vec[%lu];\n", (unsigned long)sdef->nElements); |
| 6745 | } |
| 6746 | |
| 6747 | /* default constructor */ |
| 6748 | if (sdef->nElements==0) { |
| 6749 | def = mputprintf(def, "public:\n" |
| 6750 | " %s();\n", name); |
| 6751 | src = mputprintf(src, |
| 6752 | "%s::%s() : Empty_Record_Type() {}\n\n", |
| 6753 | name, name); |
| 6754 | } else { |
| 6755 | def = mputstr(def, " void init_vec();\n"); |
| 6756 | src = mputprintf(src, "void %s::init_vec() { ", name); |
| 6757 | for (i = 0; i < sdef->nElements; i++) { |
| 6758 | src = mputprintf(src, "fld_vec[%lu]=&field_%s; ", |
| 6759 | (unsigned long)i, sdef->elements[i].name); |
| 6760 | } |
| 6761 | src = mputstr(src, " }\n\n"); |
| 6762 | |
| 6763 | def = mputprintf(def, "public:\n" |
| 6764 | " %s();\n", name); |
| 6765 | src = mputprintf(src, |
| 6766 | "%s::%s() : Record_Type() { init_vec(); }\n\n", name, name); |
| 6767 | } |
| 6768 | |
| 6769 | /* copy constructor */ |
| 6770 | if (sdef->nElements) { |
| 6771 | def = mputprintf(def, " %s(const %s& other_value);\n", name, name); |
| 6772 | src = mputprintf(src, "%s::%s(const %s& other_value) : Record_Type(other_value)\n", name, name, name); |
| 6773 | src = mputstr(src, "{\n" |
| 6774 | " if(!other_value.is_bound()) " |
| 6775 | "TTCN_error(\"Copying an unbound record/set value.\");\n" |
| 6776 | "bound_flag = TRUE;\n"); |
| 6777 | for (i = 0; i < sdef->nElements; i++) { |
| 6778 | src = mputprintf(src, |
| 6779 | "if (other_value.field_%s.is_bound() )\n" |
| 6780 | " field_%s = other_value.field_%s;\n", |
| 6781 | sdef->elements[i].name, sdef->elements[i].name, |
| 6782 | sdef->elements[i].name); |
| 6783 | } |
| 6784 | |
| 6785 | src = mputstr(src, "init_vec();\n" |
| 6786 | "}\n\n"); |
| 6787 | } else { |
| 6788 | def = mputprintf(def, " %s(const %s& other_value): %s(other_value) {}\n", name, name, base_class); |
| 6789 | } |
| 6790 | |
| 6791 | if (sdef->nElements>0) { /* constructor by fields */ |
| 6792 | def = mputprintf(def, " %s(", name); |
| 6793 | src = mputprintf(src, "%s::%s(", name, name); |
| 6794 | for (i = 0; i < sdef->nElements; i++) { |
| 6795 | char *tmp = NULL; |
| 6796 | if (i > 0) tmp = mputstr(tmp, ",\n "); |
| 6797 | if (sdef->elements[i].isOptional) |
| 6798 | tmp = mputprintf |
| 6799 | (tmp, |
| 6800 | "const OPTIONAL<%s>& par_%s", |
| 6801 | sdef->elements[i].type, sdef->elements[i].name); |
| 6802 | else |
| 6803 | tmp = mputprintf |
| 6804 | (tmp, |
| 6805 | "const %s& par_%s", |
| 6806 | sdef->elements[i].type, sdef->elements[i].name); |
| 6807 | def = mputstr(def, tmp); |
| 6808 | src = mputstr(src, tmp); |
| 6809 | Free(tmp); |
| 6810 | } |
| 6811 | def = mputstr(def, ");\n"); |
| 6812 | src = mputprintf(src, ") : "); |
| 6813 | for (i = 0; i < sdef->nElements; i++) { |
| 6814 | if (i > 0) src = mputstr(src, ",\n "); |
| 6815 | src = mputprintf(src, "field_%s(par_%s)", sdef->elements[i].name, |
| 6816 | sdef->elements[i].name); |
| 6817 | } |
| 6818 | src = mputstr(src, "\n" |
| 6819 | "{\n" |
| 6820 | "init_vec();\n" |
| 6821 | "bound_flag = TRUE;\n" |
| 6822 | "}\n\n"); |
| 6823 | } else { /* constructor from null */ |
| 6824 | def = mputprintf(def, " %s(null_type) {bound_flag = TRUE;}\n", name); |
| 6825 | } |
| 6826 | |
| 6827 | /* assignment operators */ |
| 6828 | def = mputprintf(def, "inline %s& operator=(const %s& other_value) " |
| 6829 | "{ set_value(&other_value); return *this; }\n\n", name, name); |
| 6830 | if (sdef->nElements == 0) { |
| 6831 | def = mputprintf(def, "inline %s& operator=(null_type) " |
| 6832 | "{ bound_flag = TRUE; return *this; }\n", name); |
| 6833 | } |
| 6834 | |
| 6835 | /* == operator */ |
| 6836 | def = mputprintf(def, "inline boolean operator==(const %s& other_value) " |
| 6837 | "const { return is_equal(&other_value); }\n", name); |
| 6838 | /* != operator */ |
| 6839 | def = mputprintf(def, |
| 6840 | " inline boolean operator!=(const %s& other_value) const\n" |
| 6841 | " { return !is_equal(&other_value); }\n\n", name); |
| 6842 | |
| 6843 | for (i = 0; i < sdef->nElements; i++) { |
| 6844 | if(sdef->elements[i].isOptional) |
| 6845 | def = mputprintf |
| 6846 | (def, |
| 6847 | " inline OPTIONAL<%s>& %s()\n" |
| 6848 | " {return field_%s;}\n" |
| 6849 | " inline const OPTIONAL<%s>& %s() const\n" |
| 6850 | " {return field_%s;}\n", |
| 6851 | sdef->elements[i].type, sdef->elements[i].name, |
| 6852 | sdef->elements[i].name, |
| 6853 | sdef->elements[i].type, sdef->elements[i].name, |
| 6854 | sdef->elements[i].name); |
| 6855 | else def = mputprintf |
| 6856 | (def, |
| 6857 | " inline %s& %s()\n" |
| 6858 | " {return field_%s;}\n" |
| 6859 | " inline const %s& %s() const\n" |
| 6860 | " {return field_%s;}\n", |
| 6861 | sdef->elements[i].type, sdef->elements[i].name, |
| 6862 | sdef->elements[i].name, sdef->elements[i].type, |
| 6863 | sdef->elements[i].name, sdef->elements[i].name); |
| 6864 | |
| 6865 | } |
| 6866 | |
| 6867 | /* override virtual functions where needed */ |
| 6868 | def = mputprintf(def, |
| 6869 | "Base_Type* clone() const { return new %s(*this); }\n" |
| 6870 | "const TTCN_Typedescriptor_t* get_descriptor() const;\n" |
| 6871 | "boolean is_set() const { return %s; }\n", |
| 6872 | name, |
| 6873 | (sdef->kind==SET) ? "TRUE" : "FALSE"); |
| 6874 | src = mputprintf(src, |
| 6875 | "const TTCN_Typedescriptor_t* %s::get_descriptor() const { return &%s_descr_; }\n", |
| 6876 | name, name); |
| 6877 | |
| 6878 | if (sdef->nElements > 0) { |
| 6879 | |
| 6880 | /* field access functions */ |
| 6881 | def = mputprintf(def, |
| 6882 | "Base_Type* get_at(int index_value) { return fld_vec[index_value]; }\n" |
| 6883 | "const Base_Type* get_at(int index_value) const { return fld_vec[index_value]; }\n\n" |
| 6884 | "int get_count() const { return %lu; }\n", (unsigned long)sdef->nElements); |
| 6885 | |
| 6886 | /* override if there are optional fields */ |
| 6887 | if (optional_num) { |
| 6888 | def = mputprintf(def, |
| 6889 | "int optional_count() const { return %lu; }\n", (unsigned long)optional_num); |
| 6890 | } |
| 6891 | |
| 6892 | if (sdef->opentype_outermost) |
| 6893 | def = mputstr(def, "boolean is_opentype_outermost() const { return TRUE; }\n"); |
| 6894 | |
| 6895 | /* FIXME: use static member in Record_Type and initialize somewhere */ |
| 6896 | if (default_as_optional) |
| 6897 | def = mputstr(def, "boolean default_as_optional() const { return TRUE; }\n"); |
| 6898 | |
| 6899 | for (i = 0; i < sdef->nElements; i++) { |
| 6900 | if (sdef->elements[i].isOptional) { |
| 6901 | has_optional = TRUE; |
| 6902 | break; |
| 6903 | } |
| 6904 | } |
| 6905 | |
| 6906 | for (i = 0; i < sdef->nElements; i++) { |
| 6907 | if (sdef->elements[i].isDefault) { |
| 6908 | has_default = TRUE; |
| 6909 | break; |
| 6910 | } |
| 6911 | } |
| 6912 | def = mputstr(def, |
| 6913 | "static const TTCN_Typedescriptor_t* fld_descriptors[];\n" |
| 6914 | "const TTCN_Typedescriptor_t* fld_descr(int p_index) const;\n\n" |
| 6915 | "static const char* fld_names[];\n" |
| 6916 | "const char* fld_name(int p_index) const;\n\n"); |
| 6917 | |
| 6918 | src = mputprintf(src, "const TTCN_Typedescriptor_t* %s::fld_descriptors[] = ", name); |
| 6919 | for (i = 0; i < sdef->nElements; i++) { |
| 6920 | src = mputprintf(src, "%c &%s_descr_", |
| 6921 | (i ? ',' : '{'), sdef->elements[i].typedescrname); |
| 6922 | } |
| 6923 | src = mputstr(src, " };\n"); |
| 6924 | src = mputprintf(src, |
| 6925 | "const TTCN_Typedescriptor_t* %s::fld_descr(int p_index) const " |
| 6926 | "{ return fld_descriptors[p_index]; }\n\n", name); |
| 6927 | |
| 6928 | src = mputprintf(src, "const char* %s::fld_names[] = ", name); |
| 6929 | for (i = 0; i < sdef->nElements; i++) { |
| 6930 | src = mputprintf(src, "%c \"%s\"", |
| 6931 | (i ? ',' : '{'), sdef->elements[i].dispname); |
| 6932 | } |
| 6933 | src = mputstr(src, " };\n"); |
| 6934 | |
| 6935 | src = mputprintf(src, |
| 6936 | "const char* %s::fld_name(int p_index) const " |
| 6937 | "{ return fld_names[p_index]; }\n\n", name); |
| 6938 | |
| 6939 | if (has_optional) { |
| 6940 | def = mputstr(def, |
| 6941 | "static const int optional_indexes[];\n" |
| 6942 | "const int* get_optional_indexes() const;\n\n"); |
| 6943 | src = mputprintf(src, "const int %s::optional_indexes[] = { ", name); |
| 6944 | for (i = 0; i < sdef->nElements; i++) { |
| 6945 | if (sdef->elements[i].isOptional) { |
| 6946 | src = mputprintf(src, "%lu, ", (unsigned long)i); |
| 6947 | } |
| 6948 | } |
| 6949 | src = mputstr(src, "-1 };\n"); |
| 6950 | src = mputprintf(src, |
| 6951 | "const int* %s::get_optional_indexes() const " |
| 6952 | "{ return optional_indexes; }\n\n", name); |
| 6953 | } |
| 6954 | |
| 6955 | if (has_default) { |
| 6956 | def = mputstr(def, |
| 6957 | "static const default_struct default_indexes[];\n" |
| 6958 | "const default_struct* get_default_indexes() const;\n"); |
| 6959 | src = mputprintf(src, "const Record_Type::default_struct %s::default_indexes[] = { ", name); |
| 6960 | for (i = 0; i < sdef->nElements; i++) { |
| 6961 | if (sdef->elements[i].isDefault) { |
| 6962 | src = mputprintf(src, "{%lu,&%s}, ", |
| 6963 | (unsigned long)i, sdef->elements[i].defvalname); |
| 6964 | } |
| 6965 | } |
| 6966 | src = mputstr(src, "{-1,NULL} };\n"); |
| 6967 | src = mputprintf(src, |
| 6968 | "const Record_Type::default_struct* %s::get_default_indexes() const " |
| 6969 | "{ return default_indexes; }\n", name); |
| 6970 | } |
| 6971 | |
| 6972 | if (raw_needed) { |
| 6973 | struct raw_option_struct *raw_options; |
| 6974 | boolean haslengthto, haspointer, hascrosstag, has_ext_bit; |
| 6975 | boolean generate_raw_function = FALSE; |
| 6976 | |
| 6977 | raw_options = (struct raw_option_struct*) |
| 6978 | Malloc(sdef->nElements * sizeof(*raw_options)); |
| 6979 | |
| 6980 | set_raw_options(sdef, raw_options, &haslengthto, |
| 6981 | &haspointer, &hascrosstag, &has_ext_bit); |
| 6982 | |
| 6983 | /* set the value of generate_raw_function: if the coding/decoding is too |
| 6984 | complex for this type then generate the functions, otherwise generate |
| 6985 | helper functions only which are called by the default RAW enc/dec |
| 6986 | functions */ |
| 6987 | if (haslengthto || haspointer || hascrosstag) { |
| 6988 | generate_raw_function = TRUE; |
| 6989 | goto check_generate_end; |
| 6990 | } |
| 6991 | for (i = 0; i < sdef->nElements; i++) { |
| 6992 | if (raw_options[i].lengthto || raw_options[i].lengthof || |
| 6993 | raw_options[i].lengthoffield || raw_options[i].pointerto || |
| 6994 | raw_options[i].pointerof || raw_options[i].ptrbase || |
| 6995 | raw_options[i].extbitgroup || raw_options[i].tag_type || |
| 6996 | raw_options[i].delayed_decode || raw_options[i].nof_dependent_fields |
| 6997 | || raw_options[i].dependent_fields) { |
| 6998 | generate_raw_function = TRUE; |
| 6999 | goto check_generate_end; |
| 7000 | } |
| 7001 | } |
| 7002 | for (i = 0; i < sdef->nElements; i++) { |
| 7003 | if (raw_options[i].lengthof || raw_options[i].lengthoffield || |
| 7004 | raw_options[i].nof_dependent_fields || |
| 7005 | raw_options[i].dependent_fields) { |
| 7006 | generate_raw_function = TRUE; |
| 7007 | goto check_generate_end; |
| 7008 | } |
| 7009 | } |
| 7010 | if (sdef->raw.ext_bit_goup_num || sdef->raw.ext_bit_groups || |
| 7011 | sdef->raw.lengthto || sdef->raw.lengthindex || |
| 7012 | sdef->raw.taglist.nElements || sdef->raw.crosstaglist.nElements || |
| 7013 | sdef->raw.presence.fieldnum || sdef->raw.presence.fields || |
| 7014 | sdef->raw.member_name) { |
| 7015 | generate_raw_function = TRUE; |
| 7016 | goto check_generate_end; |
| 7017 | } |
| 7018 | for (i = 0; i < sdef->nElements; i++) { |
| 7019 | if (sdef->elements[i].hasRaw) { |
| 7020 | generate_raw_function = TRUE; |
| 7021 | goto check_generate_end; |
| 7022 | } |
| 7023 | } |
| 7024 | check_generate_end: |
| 7025 | |
| 7026 | if (generate_raw_function) { |
| 7027 | def = mputprintf(def, |
| 7028 | "int RAW_encode(const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n" |
| 7029 | "virtual int RAW_encode_negtest(const Erroneous_descriptor_t *, const TTCN_Typedescriptor_t&, RAW_enc_tree&) const;\n" |
| 7030 | "int RAW_decode(const TTCN_Typedescriptor_t&, TTCN_Buffer&, " |
| 7031 | "int, raw_order_t, boolean no_err = FALSE, " |
| 7032 | "int sel_field = -1, boolean first_call = TRUE);\n"); |
| 7033 | src = generate_raw_coding(src, sdef, raw_options, haspointer, |
| 7034 | hascrosstag, has_ext_bit); |
| 7035 | } else { /* generate helper functions for the default RAW enc/dec */ |
| 7036 | if (has_ext_bit) |
| 7037 | def = mputstr(def,"boolean raw_has_ext_bit() const { return TRUE; }\n"); |
| 7038 | } |
| 7039 | for (i = 0; i < sdef->nElements; i++) { |
| 7040 | Free(raw_options[i].lengthoffield); |
| 7041 | Free(raw_options[i].dependent_fields); |
| 7042 | } |
| 7043 | Free(raw_options); |
| 7044 | } /* if (raw_needed) */ |
| 7045 | |
| 7046 | if (xer_needed) { /* XERSTUFF codegen for record/SEQUENCE in RT2 */ |
| 7047 | size_t num_attributes = 0; |
| 7048 | |
| 7049 | /* XER descriptors needed because of the xer antipattern */ |
| 7050 | def = mputstr(def, |
| 7051 | "static const XERdescriptor_t* xer_descriptors[];\n" |
| 7052 | "const XERdescriptor_t* xer_descr(int p_index) const;\n" |
| 7053 | "virtual boolean can_start_v(const char *name, const char *prefix, " |
| 7054 | "XERdescriptor_t const& xd, unsigned int flavor);\n" |
| 7055 | "static boolean can_start (const char *name, const char *prefix, " |
| 7056 | "XERdescriptor_t const& xd, unsigned int flavor);\n"); |
| 7057 | src = mputprintf(src, "const XERdescriptor_t* %s::xer_descriptors[] = ", name); |
| 7058 | for (i = 0; i < sdef->nElements; i++) { |
| 7059 | src = mputprintf(src, "%c &%s_xer_", |
| 7060 | (i ? ',' : '{'), sdef->elements[i].typegen); |
| 7061 | } |
| 7062 | src = mputstr(src, " };\n"); |
| 7063 | src = mputprintf(src, |
| 7064 | "const XERdescriptor_t* %s::xer_descr(int p_index) const " |
| 7065 | "{ return xer_descriptors[p_index]; }\n" |
| 7066 | /* The virtual can_start_v hands off to the static can_start. |
| 7067 | * We must make a virtual call in Record_Type::XER_decode because |
| 7068 | * we don't know the actual type (derived from Record_Type) */ |
| 7069 | "boolean %s::can_start_v(const char *p_name, const char *p_uri, " |
| 7070 | "XERdescriptor_t const& p_td, unsigned int p_flavor)\n" |
| 7071 | "{ return can_start(p_name, p_uri, p_td, p_flavor); }\n" |
| 7072 | "boolean %s::can_start(const char *p_name, const char *p_uri, " |
| 7073 | "XERdescriptor_t const& p_td, unsigned int p_flavor) {\n" |
| 7074 | " boolean e_xer = is_exer(p_flavor);\n" |
| 7075 | " if (!e_xer || (!(p_td.xer_bits & UNTAGGED) && !(p_flavor & USE_NIL))) return check_name(p_name, p_td, e_xer) && (!e_xer || check_namespace(p_uri, p_td));\n" |
| 7076 | , name , name, name); |
| 7077 | for (i = 0; i < sdef->nElements; i++) { |
| 7078 | src = mputprintf(src, |
| 7079 | " else if (%s::can_start(p_name, p_uri, %s_xer_, p_flavor)) return true;\n" |
| 7080 | , sdef->elements[i].type, sdef->elements[i].typegen); |
| 7081 | } |
| 7082 | src = mputstr(src, |
| 7083 | " return false;\n" |
| 7084 | "}\n\n"); |
| 7085 | /* end of antipattern */ |
| 7086 | |
| 7087 | /* calculate num_attributes in compile time */ |
| 7088 | for ( i=0; i < sdef->nElements; ++i ) { |
| 7089 | if (sdef->elements[i].xerAttribute |
| 7090 | ||(sdef->elements[i].xerAnyKind & ANY_ATTRIB_BIT)) ++num_attributes; |
| 7091 | else if (num_attributes) break; |
| 7092 | } |
| 7093 | |
| 7094 | /* generate helper virtual functions for XER encdec */ |
| 7095 | if (num_attributes) { |
| 7096 | def = mputprintf(def, |
| 7097 | "int get_xer_num_attr() const { return %lu; }\n", |
| 7098 | (unsigned long)num_attributes); |
| 7099 | } |
| 7100 | } |
| 7101 | else { /* XER not needed */ |
| 7102 | def = mputstr(def, |
| 7103 | "boolean can_start_v(const char *, const char *, XERdescriptor_t const&, unsigned int)\n" |
| 7104 | "{ return FALSE; }\n" |
| 7105 | ); |
| 7106 | } /* if (xer_needed) */ |
| 7107 | } /* if (sdef->nElements > 0) */ |
| 7108 | |
| 7109 | /* end of class definition */ |
| 7110 | def = mputstr(def, "};\n\n"); |
| 7111 | |
| 7112 | output->header.class_defs = mputstr(output->header.class_defs, def); |
| 7113 | Free(def); |
| 7114 | |
| 7115 | output->source.methods = mputstr(output->source.methods, src); |
| 7116 | Free(src); |
| 7117 | } |
| 7118 | |
| 7119 | void defRecordTemplate2(const struct_def *sdef, output_struct *output) |
| 7120 | { |
| 7121 | int i; |
| 7122 | const char *name = sdef->name; |
| 7123 | char *def = NULL, *src = NULL; |
| 7124 | |
| 7125 | const char* base_class = (sdef->nElements==0) ? "Empty_Record_Template" : "Record_Template"; |
| 7126 | |
| 7127 | /* class declaration */ |
| 7128 | output->header.class_decls = mputprintf(output->header.class_decls, |
| 7129 | "class %s_template;\n", name); |
| 7130 | |
| 7131 | /* template class definition */ |
| 7132 | def = mputprintf(def, "class %s_template : public %s {\n", name, base_class); |
| 7133 | |
| 7134 | if (sdef->nElements>0) { |
| 7135 | /* set_specific function (used in field access members) */ |
| 7136 | def = mputstr(def, "void set_specific();\n"); |
| 7137 | src = mputprintf(src, "void %s_template::set_specific()\n" |
| 7138 | "{\n" |
| 7139 | "if (template_selection != SPECIFIC_VALUE) {\n" |
| 7140 | "%s" |
| 7141 | "clean_up();\n" |
| 7142 | "single_value.n_elements = %lu;\n" |
| 7143 | "single_value.value_elements = (Base_Template**)allocate_pointers(single_value.n_elements);\n" |
| 7144 | "set_selection(SPECIFIC_VALUE);\n", |
| 7145 | name, sdef->nElements ? "boolean was_any = (template_selection == ANY_VALUE || template_selection == ANY_OR_OMIT);\n" : "", |
| 7146 | (unsigned long)sdef->nElements); |
| 7147 | for (i = 0; i < sdef->nElements; i++) { |
| 7148 | src = mputprintf(src, |
| 7149 | "single_value.value_elements[%d] = was_any ? new %s_template(%s) : new %s_template;\n", |
| 7150 | i, sdef->elements[i].type, |
| 7151 | sdef->elements[i].isOptional ? "ANY_OR_OMIT" : "ANY_VALUE", |
| 7152 | sdef->elements[i].type); |
| 7153 | } |
| 7154 | src = mputstr(src, |
| 7155 | "}\n" |
| 7156 | "}\n\n"); |
| 7157 | } |
| 7158 | |
| 7159 | /* default constructor */ |
| 7160 | def = mputprintf(def, "public:\n" |
| 7161 | "%s_template(): %s() {}\n", name, base_class); |
| 7162 | |
| 7163 | if (sdef->nElements==0) { |
| 7164 | /* ctor for value {} */ |
| 7165 | def = mputprintf(def, "%s_template(null_type) : " |
| 7166 | "Empty_Record_Template() { set_selection(SPECIFIC_VALUE); }\n", |
| 7167 | name); |
| 7168 | } |
| 7169 | |
| 7170 | /* constructor t1_template(template_sel other_value) */ |
| 7171 | def = mputprintf(def, "%s_template(template_sel other_value): " |
| 7172 | "%s(other_value) {}\n", name, base_class); |
| 7173 | |
| 7174 | /* constructor t1_template(const t1& other_value) */ |
| 7175 | def = mputprintf(def, "%s_template(const %s& other_value): " |
| 7176 | "%s() { copy_value(&other_value); }\n", |
| 7177 | name, name, base_class); |
| 7178 | |
| 7179 | /* constructor t1_template(const OPTIONAL<t1>& other_value) */ |
| 7180 | def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value): " |
| 7181 | "%s() { copy_optional(&other_value); }\n", |
| 7182 | name, name, base_class); |
| 7183 | |
| 7184 | /* copy constructor */ |
| 7185 | def = mputprintf(def, "%s_template(const %s_template& other_value): %s() " |
| 7186 | "{ copy_template(other_value); }\n", name, name, base_class); |
| 7187 | |
| 7188 | /* assignment operator <- template_sel */ |
| 7189 | def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n", |
| 7190 | name); |
| 7191 | src = mputprintf(src, |
| 7192 | "%s_template& %s_template::operator=(template_sel other_value)\n" |
| 7193 | "{\n" |
| 7194 | "check_single_selection(other_value);\n" |
| 7195 | "clean_up();\n" |
| 7196 | "set_selection(other_value);\n" |
| 7197 | "return *this;\n" |
| 7198 | "}\n\n", name, name); |
| 7199 | |
| 7200 | /* assignment operator <- value */ |
| 7201 | def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n", |
| 7202 | name, name); |
| 7203 | src = mputprintf(src, |
| 7204 | "%s_template& %s_template::operator=(const %s& other_value)\n" |
| 7205 | "{\n" |
| 7206 | "clean_up();\n" |
| 7207 | "copy_value(&other_value);\n" |
| 7208 | "return *this;\n" |
| 7209 | "}\n\n", name, name, name); |
| 7210 | |
| 7211 | /* assignment operator <- optional value */ |
| 7212 | def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& " |
| 7213 | "other_value);\n", name, name); |
| 7214 | src = mputprintf(src, |
| 7215 | "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n" |
| 7216 | "{\n" |
| 7217 | "clean_up();\n" |
| 7218 | "copy_optional(&other_value);\n" |
| 7219 | "return *this;\n" |
| 7220 | "}\n\n", name, name, name); |
| 7221 | |
| 7222 | /* assignment operator <- template*/ |
| 7223 | def = mputprintf(def, |
| 7224 | "%s_template& operator=(const %s_template& other_value);\n", |
| 7225 | name, name); |
| 7226 | src = mputprintf(src, |
| 7227 | "%s_template& %s_template::operator=(const %s_template& other_value)\n" |
| 7228 | "{\n" |
| 7229 | "if (&other_value != this) {\n" |
| 7230 | "clean_up();\n" |
| 7231 | "copy_template(other_value);\n" |
| 7232 | "}\n" |
| 7233 | "return *this;\n" |
| 7234 | "}\n\n", name, name, name); |
| 7235 | |
| 7236 | if (sdef->nElements==0) { |
| 7237 | /* assignment op for value {} */ |
| 7238 | def = mputprintf(def, "%s_template& operator=(null_type other_value);\n", |
| 7239 | name); |
| 7240 | src = mputprintf(src, "%s_template& %s_template::operator=(null_type)\n" |
| 7241 | "{\n" |
| 7242 | "clean_up();\n" |
| 7243 | "set_selection(SPECIFIC_VALUE);\n" |
| 7244 | "return *this;\n" |
| 7245 | "}\n\n", name, name); |
| 7246 | } |
| 7247 | |
| 7248 | /* match operation (template matching) */ |
| 7249 | def = mputprintf(def, "inline boolean match(const %s& other_value, " |
| 7250 | "boolean legacy = FALSE) const " |
| 7251 | "{ return matchv(&other_value, legacy); }\n", name); |
| 7252 | |
| 7253 | /* log_match */ |
| 7254 | def = mputprintf(def, "inline void log_match(const %s& match_value, " |
| 7255 | "boolean legacy = FALSE) const " |
| 7256 | "{ log_matchv(&match_value, legacy); }\n", name); |
| 7257 | |
| 7258 | /* valueof operation */ |
| 7259 | def = mputprintf(def, "%s valueof() const;\n", name); |
| 7260 | |
| 7261 | src = mputprintf(src, "%s %s_template::valueof() const\n" |
| 7262 | "{\n" |
| 7263 | "%s ret_val;\n" |
| 7264 | "valueofv(&ret_val);\n" |
| 7265 | "return ret_val;\n" |
| 7266 | "}\n\n", name, name, name); |
| 7267 | |
| 7268 | /* list_item(int) function */ |
| 7269 | |
| 7270 | def = mputprintf(def, |
| 7271 | "inline %s_template& list_item(unsigned int list_index) const " |
| 7272 | "{ return *(static_cast<%s_template*>(get_list_item(list_index))); }\n", name, name); |
| 7273 | |
| 7274 | if (sdef->nElements>0) { |
| 7275 | /* template field access functions (non-const & const) */ |
| 7276 | for (i = 0; i < sdef->nElements; i++) { |
| 7277 | def = mputprintf(def, |
| 7278 | "%s_template& %s();\n" |
| 7279 | "const %s_template& %s() const;\n", |
| 7280 | sdef->elements[i].type, sdef->elements[i].name, |
| 7281 | sdef->elements[i].type, sdef->elements[i].name); |
| 7282 | src = mputprintf(src, |
| 7283 | "%s_template& %s_template::%s() { return *(static_cast<%s_template*>(get_at(%d))); }\n" |
| 7284 | "const %s_template& %s_template::%s() const { return *(static_cast<const %s_template*>(get_at(%d))); }\n", |
| 7285 | sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i, |
| 7286 | sdef->elements[i].type, name, sdef->elements[i].name, sdef->elements[i].type, i); |
| 7287 | } |
| 7288 | } |
| 7289 | |
| 7290 | /* virtual functions */ |
| 7291 | def = mputprintf(def, |
| 7292 | "%s* create() const { return new %s_template; }\n" |
| 7293 | "const TTCN_Typedescriptor_t* get_descriptor() const;\n", |
| 7294 | base_class, name); |
| 7295 | src = mputprintf(src, |
| 7296 | "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const { return &%s_descr_; }\n", |
| 7297 | name, name); |
| 7298 | |
| 7299 | if (sdef->nElements>0) { |
| 7300 | def = mputprintf(def, "const char* fld_name(int p_index) const;\n"); |
| 7301 | src = mputprintf(src, |
| 7302 | "const char* %s_template::fld_name(int p_index) const { return %s::fld_names[p_index]; }\n", |
| 7303 | name, name); |
| 7304 | } |
| 7305 | |
| 7306 | def = mputstr(def, "};\n\n"); |
| 7307 | |
| 7308 | output->header.class_defs = mputstr(output->header.class_defs, def); |
| 7309 | Free(def); |
| 7310 | |
| 7311 | output->source.methods = mputstr(output->source.methods, src); |
| 7312 | Free(src); |
| 7313 | } |
| 7314 | |