fixed compilation errors when DEBUG is switched on
[deliverable/titan.core.git] / compiler2 / enum.c
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Baranyi, Botond
12 * Beres, Szabolcs
13 * Cserveni, Akos
14 * Delic, Adam
15 * Feher, Csaba
16 * Forstner, Matyas
17 * Kovacs, Ferenc
18 * Kremer, Peter
19 * Raduly, Csaba
20 * Szabados, Kristof
21 * Szabo, Bence Janos
22 * Szabo, Janos Zoltan – initial implementation
23 * Szalai, Gabor
24 *
25 ******************************************************************************/
26 #include "../common/memory.h"
27 #include "datatypes.h"
28 #include "enum.h"
29 #include "encdec.h"
30
31 #include <stdlib.h>
32
33 #include "main.hh"
34 #include "ttcn3/compiler.h"
35
36 void defEnumClass(const enum_def *edef, output_struct *output)
37 {
38 size_t i;
39 char *def = NULL, *src = NULL;
40 const char *name = edef->name, *dispname = edef->dispname;
41 boolean ber_needed = edef->isASN1 && enable_ber();
42 boolean raw_needed = edef->hasRaw && enable_raw();
43 boolean text_needed= edef->hasText && enable_text();
44 boolean xer_needed = edef->hasXer && enable_xer();
45 boolean json_needed = edef->hasJson && enable_json();
46
47 char *enum_type, *qualified_enum_type, *unknown_value, *unbound_value;
48 enum_type = mcopystr("enum_type");
49 qualified_enum_type = mprintf("%s::enum_type", name);
50 unknown_value = mcopystr("UNKNOWN_VALUE");
51 unbound_value = mcopystr("UNBOUND_VALUE");
52
53 /* Class declaration */
54 output->header.class_decls = mputprintf(output->header.class_decls,
55 "class %s;\n", name);
56
57 /* Class definition */
58 def = mputprintf(def,
59 #ifndef NDEBUG
60 "// written by %s in " __FILE__ " at %d\n"
61 #endif
62 "class %s : public %s { // enum\n"
63 "friend class %s_template;\n"
64 #ifndef NDEBUG
65 , __FUNCTION__, __LINE__
66 #endif
67 , name, (use_runtime_2) ? "Enum_Type" : "Base_Type", name);
68 def = mputstr(def, "public:\n"
69 "enum enum_type { ");
70 for (i = 0; i < edef->nElements; i++) {
71 def = mputprintf(def, "%s = %d, ", edef->elements[i].name,
72 edef->elements[i].value);
73 }
74 def = mputprintf(def, "UNKNOWN_VALUE = %d, UNBOUND_VALUE = %d };\n"
75 "private:\n", edef->firstUnused, edef->secondUnused);
76 def = mputprintf(def, "%s enum_value;\n\n"
77 "public:\n", enum_type);
78
79 /* constructors */
80 def = mputprintf(def, "%s();\n", name);
81 src = mputprintf(src, "%s::%s()\n"
82 "{\n"
83 "enum_value = %s;\n"
84 "}\n\n", name, name, unbound_value);
85
86 def = mputprintf(def, "%s(int other_value);\n", name);
87 src = mputprintf(src,
88 "%s::%s(int other_value)\n"
89 "{\n"
90 "if (!is_valid_enum(other_value)) "
91 "TTCN_error(\"Initializing a variable of enumerated type %s with "
92 "invalid numeric value %%d.\", other_value);\n"
93 "enum_value = (%s)other_value;\n"
94 "}\n\n",
95 name, name, dispname, enum_type);
96
97 def = mputprintf(def, "%s(%s other_value);\n", name, enum_type);
98 src = mputprintf(src,
99 "%s::%s(%s other_value)\n"
100 "{\n"
101 "enum_value = other_value;\n"
102 "}\n\n", name, name, enum_type);
103
104 def = mputprintf(def, "%s(const %s& other_value);\n\n", name, name);
105 src = mputprintf
106 (src,
107 "%s::%s(const %s& other_value)\n"
108 ": %s()\n" /* Base class DEFAULT constructor*/
109 "{\n"
110 "if (other_value.enum_value == %s) "
111 "TTCN_error(\"Copying an unbound value of enumerated type %s.\");\n"
112 "enum_value = other_value.enum_value;\n"
113 "}\n\n", name, name, name, (use_runtime_2) ? "Enum_Type" : "Base_Type",
114 unbound_value, dispname);
115
116 /* assignment operators */
117 def = mputprintf(def, "%s& operator=(int other_value);\n", name);
118 src = mputprintf(src,
119 "%s& %s::operator=(int other_value)\n"
120 "{\n"
121 "if (!is_valid_enum(other_value)) "
122 "TTCN_error(\"Assigning unknown numeric value %%d to a variable "
123 "of enumerated type %s.\", other_value);\n"
124 "enum_value = (%s)other_value;\n"
125 "return *this;\n"
126 "}\n\n", name, name, dispname, enum_type);
127
128 def = mputprintf(def, "%s& operator=(%s other_value);\n", name, enum_type);
129 src = mputprintf(src,
130 "%s& %s::operator=(%s other_value)\n"
131 "{\n"
132 "enum_value = other_value;\n"
133 "return *this;\n"
134 "}\n\n", name, name, enum_type);
135
136 def = mputprintf(def, "%s& operator=(const %s& other_value);\n\n", name,
137 name);
138 src = mputprintf(src,
139 "%s& %s::operator=(const %s& other_value)\n"
140 "{\n"
141 "if (other_value.enum_value == %s) "
142 "TTCN_error(\"Assignment of an unbound value of enumerated type %s.\");\n"
143 "enum_value = other_value.enum_value;\n"
144 "return *this;\n"
145 "}\n\n", name, name, name, unbound_value, dispname);
146
147 /* Comparison operators */
148 def = mputprintf(def, "boolean operator==(%s other_value) const;\n",
149 enum_type);
150 src = mputprintf(src,
151 "boolean %s::operator==(%s other_value) const\n"
152 "{\n"
153 "if (enum_value == %s) "
154 "TTCN_error(\"The left operand of comparison is an unbound value of "
155 "enumerated type %s.\");\n"
156 "return enum_value == other_value;\n"
157 "}\n\n", name, enum_type, unbound_value, dispname);
158
159 def = mputprintf(def, "boolean operator==(const %s& other_value) const;\n",
160 name);
161 src = mputprintf(src,
162 "boolean %s::operator==(const %s& other_value) const\n"
163 "{\n"
164 "if (enum_value == %s) "
165 "TTCN_error(\"The left operand of comparison is an unbound value of "
166 "enumerated type %s.\");\n"
167 "if (other_value.enum_value == %s) "
168 "TTCN_error(\"The right operand of comparison is an unbound value of "
169 "enumerated type %s.\");\n"
170 "return enum_value == other_value.enum_value;\n"
171 "}\n\n", name, name, unbound_value, dispname, unbound_value, dispname);
172
173 def = mputprintf(def, "inline boolean operator!=(%s other_value) "
174 "const { return !(*this == other_value); }\n", enum_type);
175
176 def = mputprintf(def, "inline boolean operator!=(const %s& other_value) "
177 "const { return !(*this == other_value); }\n", name);
178
179 def = mputprintf(def, "boolean operator<(%s other_value) const;\n",
180 enum_type);
181 src = mputprintf(src,
182 "boolean %s::operator<(%s other_value) const\n"
183 "{\n"
184 "if (enum_value == %s) "
185 "TTCN_error(\"The left operand of comparison is an unbound value of "
186 "enumerated type %s.\");\n"
187 "return enum_value < other_value;\n"
188 "}\n\n", name, enum_type, unbound_value, dispname);
189
190 def = mputprintf(def, "boolean operator<(const %s& other_value) const;\n",
191 name);
192 src = mputprintf(src,
193 "boolean %s::operator<(const %s& other_value) const\n"
194 "{\n"
195 "if (enum_value == %s) "
196 "TTCN_error(\"The left operand of comparison is an unbound value of "
197 "enumerated type %s.\");\n"
198 "if (other_value.enum_value == %s) "
199 "TTCN_error(\"The right operand of comparison is an unbound value of "
200 "enumerated type %s.\");\n"
201 "return enum_value < other_value.enum_value;\n"
202 "}\n\n", name, name, unbound_value, dispname, unbound_value, dispname);
203
204 def = mputprintf(def, "boolean operator>(%s other_value) const;\n",
205 enum_type);
206 src = mputprintf(src,
207 "boolean %s::operator>(%s other_value) const\n"
208 "{\n"
209 "if (enum_value == %s) "
210 "TTCN_error(\"The left operand of comparison is an unbound value of "
211 "enumerated type %s.\");\n"
212 "return enum_value > other_value;\n"
213 "}\n\n", name, enum_type, unbound_value, dispname);
214
215 def = mputprintf(def, "boolean operator>(const %s& other_value) const;\n",
216 name);
217 src = mputprintf(src,
218 "boolean %s::operator>(const %s& other_value) const\n"
219 "{\n"
220 "if (enum_value == %s) "
221 "TTCN_error(\"The left operand of comparison is an unbound value of "
222 "enumerated type %s.\");\n"
223 "if (other_value.enum_value == %s) "
224 "TTCN_error(\"The right operand of comparison is an unbound value of "
225 "enumerated type %s.\");\n"
226 "return enum_value > other_value.enum_value;\n"
227 "}\n\n", name, name, unbound_value, dispname, unbound_value, dispname);
228
229 def = mputprintf(def, "inline boolean operator<=(%s other_value) "
230 "const { return !(*this > other_value); }\n", enum_type);
231
232 def = mputprintf(def, "inline boolean operator<=(const %s& other_value) "
233 "const { return !(*this > other_value); }\n", name);
234
235 def = mputprintf(def, "inline boolean operator>=(%s other_value) "
236 "const { return !(*this < other_value); }\n", enum_type);
237
238 def = mputprintf(def, "inline boolean operator>=(const %s& other_value) "
239 "const { return !(*this < other_value); }\n\n", name);
240
241 /* Conversion function: enum_to_str */
242 def = mputprintf(def, "static const char *enum_to_str(%s enum_par%s);\n",
243 enum_type,
244 edef->xerText ? ", boolean txt = false" : "");
245 src = mputprintf(src, "const char *%s::enum_to_str(%s enum_par%s)\n"
246 "{\n"
247 "switch (enum_par) {\n", name, enum_type,
248 edef->xerText ? ", boolean txt" : "");
249 for (i = 0; i < edef->nElements; i++) {
250 if (edef->elements[i].text) {
251 src = mputprintf(src,
252 "case %s: if (txt) return \"%s\"; else return \"%s\";\n",
253 edef->elements[i].name, edef->elements[i].text, edef->elements[i].dispname);
254 }
255 else {
256 src = mputprintf(src, "case %s: return \"%s\";\n",
257 edef->elements[i].name, edef->elements[i].dispname);
258 }
259 }
260 src = mputstr(src, "default: return \"<unknown>\";\n"
261 "}\n"
262 "}\n\n");
263
264 /* Conversion function: str_to_enum */
265 def = mputprintf(def, "static %s str_to_enum(const char *str_par);\n",
266 enum_type);
267 src = mputprintf(src, "%s %s::str_to_enum(const char *str_par)\n"
268 "{\n", qualified_enum_type, name);
269 for (i = 0; i < edef->nElements; i++) {
270 if (edef->elements[i].text) {
271 src = mputprintf(src, "if (!strcmp(str_par, \"%s\") || !strcmp(str_par, \"%s\")) return %s;\n"
272 "else ", edef->elements[i].text, edef->elements[i].dispname, edef->elements[i].name);
273 }
274 else {
275 src = mputprintf(src, "if (!strcmp(str_par, \"%s\")) return %s;\n"
276 "else ", edef->elements[i].dispname, edef->elements[i].name);
277 }
278 }
279 src = mputprintf(src, "return %s;\n"
280 "}\n\n", unknown_value);
281
282 /* Checking function: is_valid_enum */
283 def = mputstr(def, "static boolean is_valid_enum(int int_par);\n\n");
284 src = mputprintf(src, "boolean %s::is_valid_enum(int int_par)\n"
285 "{\n"
286 "switch (int_par) {\n", name);
287 for (i = 0; i < edef->nElements; i++) {
288 src = mputprintf(src, "case %d:\n", edef->elements[i].value);
289 }
290 src = mputstr(src, "return TRUE;\n"
291 "default:\n"
292 "return FALSE;\n"
293 "}\n"
294 "}\n\n");
295
296 /* TTCN-3 predefined function enum2int() */
297 def = mputprintf(def, "static int enum2int(%s enum_par);\n", enum_type);
298 src = mputprintf(src, "int %s::enum2int(%s enum_par)\n"
299 "{\n"
300 "if (enum_par==%s || enum_par==%s) TTCN_error(\"The argument of function "
301 "enum2int() is an %%s value of enumerated type %s.\", "
302 "enum_par==%s?\"unbound\":\"invalid\");\n"
303 "return enum_par;\n"
304 "}\n\n",
305 name, enum_type, unbound_value, unknown_value, dispname, unbound_value);
306 def = mputprintf(def, "static int enum2int(const %s& enum_par);\n", name);
307 src = mputprintf(src, "int %s::enum2int(const %s& enum_par)\n"
308 "{\n"
309 "if (enum_par.enum_value==%s || enum_par.enum_value==%s) "
310 "TTCN_error(\"The argument of function "
311 "enum2int() is an %%s value of enumerated type %s.\", "
312 "enum_par==%s?\"unbound\":\"invalid\");\n"
313 "return enum_par.enum_value;\n"
314 "}\n\n",
315 name, name, unbound_value, unknown_value, dispname, unbound_value);
316 def = mputstr(def,
317 "int as_int() const { return enum2int(enum_value); }\n"
318 "void from_int(int p_val) { *this = p_val; }\n");
319
320 /* TTCN-3 predefined function int2enum() */
321 def = mputstr(def, "void int2enum(int int_val);\n");
322 src = mputprintf(src, "void %s::int2enum(int int_val)\n"
323 "{\n"
324 "if (!is_valid_enum(int_val)) "
325 "TTCN_error(\"Assigning invalid numeric value %%d to a variable of "
326 "enumerated type %s.\", int_val);\n"
327 "enum_value = (%s)int_val;\n"
328 "}\n\n", name, dispname, enum_type);
329
330 /* miscellaneous members */
331 def = mputprintf(def, "operator %s() const;\n", enum_type);
332 src = mputprintf(src,
333 "%s::operator %s() const\n"
334 "{\n"
335 "if (enum_value == %s) "
336 "TTCN_error(\"Using the value of an unbound variable of enumerated "
337 "type %s.\");\n"
338 "return enum_value;\n"
339 "}\n\n", name, qualified_enum_type, unbound_value, dispname);
340
341 def = mputprintf(def, "inline boolean is_bound() const "
342 "{ return enum_value != %s; }\n", unbound_value);
343 def = mputprintf(def, "inline boolean is_value() const "
344 "{ return enum_value != %s; }\n", unbound_value);
345 def = mputprintf(def, "inline void clean_up()"
346 "{ enum_value = %s; }\n", unbound_value);
347
348 if (use_runtime_2) {
349 def = mputstr(def,
350 "boolean is_equal(const Base_Type* other_value) const;\n"
351 "void set_value(const Base_Type* other_value);\n"
352 "Base_Type* clone() const;\n"
353 "const TTCN_Typedescriptor_t* get_descriptor() const;\n");
354 src = mputprintf(src,
355 "boolean %s::is_equal(const Base_Type* other_value) const "
356 "{ return *this == *(static_cast<const %s*>(other_value)); }\n"
357 "void %s::set_value(const Base_Type* other_value) "
358 "{ *this = *(static_cast<const %s*>(other_value)); }\n"
359 "Base_Type* %s::clone() const { return new %s(*this); }\n"
360 "const TTCN_Typedescriptor_t* %s::get_descriptor() const "
361 "{ return &%s_descr_; }\n",
362 name, name,
363 name, name,
364 name, name,
365 name, name);
366 } else {
367 def = mputstr(def,
368 "inline boolean is_present() const { return is_bound(); }\n");
369 }
370
371 def = mputstr(def, "void log() const;\n");
372 src = mputprintf(src,
373 "void %s::log() const\n"
374 "{\n"
375 "if (enum_value != %s) TTCN_Logger::log_event_enum(enum_to_str(enum_value), enum_value);\n"
376 "else TTCN_Logger::log_event_unbound();\n"
377 "}\n\n", name, unbound_value);
378
379 def = mputstr(def, "void set_param(Module_Param& param);\n");
380 src = mputprintf
381 (src,
382 "void %s::set_param(Module_Param& param)\n"
383 "{\n"
384 " param.basic_check(Module_Param::BC_VALUE, \"enumerated value\");\n"
385 " Module_Param_Ptr m_p = &param;\n"
386 " if (param.get_type() == Module_Param::MP_Reference) {\n"
387 /* enumerated values are also treated as references (containing only 1 name) by the parser;
388 first check if the reference name is a valid enumerated value */
389 " char* enum_name = param.get_enumerated();\n"
390 /* get_enumerated() returns NULL if the reference contained more than one name */
391 " enum_value = (enum_name != NULL) ? str_to_enum(enum_name) : %s;\n"
392 " if (is_valid_enum(enum_value)) {\n"
393 " return;\n"
394 " }\n"
395 /* it's not a valid enum value => dereference it! */
396 " m_p = param.get_referenced_param();\n"
397 " }\n"
398 " if (m_p->get_type()!=Module_Param::MP_Enumerated) param.type_error(\"enumerated value\", \"%s\");\n"
399 " enum_value = str_to_enum(m_p->get_enumerated());\n"
400 " if (!is_valid_enum(enum_value)) {\n"
401 " param.error(\"Invalid enumerated value for type %s.\");\n"
402 " }\n"
403 "}\n\n", name, unknown_value, dispname, dispname);
404
405 def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
406 src = mputprintf
407 (src,
408 "Module_Param* %s::get_param(Module_Param_Name& /* param_name */) const\n"
409 "{\n"
410 " if (!is_bound()) {\n"
411 " return new Module_Param_Unbound();\n"
412 " }\n"
413 " return new Module_Param_Enumerated(mcopystr(enum_to_str(enum_value)));\n"
414 "}\n\n", name);
415
416 /* encoders/decoders */
417 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
418 src = mputprintf(src,
419 "void %s::encode_text(Text_Buf& text_buf) const\n"
420 "{\n"
421 "if (enum_value == %s) "
422 "TTCN_error(\"Text encoder: Encoding an unbound value of enumerated "
423 "type %s.\");\n"
424 "text_buf.push_int(enum_value);\n"
425 "}\n\n", name, unbound_value, dispname);
426
427 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
428 src = mputprintf(src,
429 "void %s::decode_text(Text_Buf& text_buf)\n"
430 "{\n"
431 "enum_value = (%s)text_buf.pull_int().get_val();\n"
432 "if (!is_valid_enum(enum_value)) "
433 "TTCN_error(\"Text decoder: Unknown numeric value %%d was "
434 "received for enumerated type %s.\", enum_value);\n"
435 "}\n\n", name, enum_type, dispname);
436
437 /* BER functions */
438 if(ber_needed || raw_needed || text_needed || xer_needed || json_needed)
439 def_encdec(name, &def, &src, ber_needed,
440 raw_needed,text_needed, xer_needed, json_needed, TRUE);
441 if(ber_needed) {
442 src=mputprintf(src,
443 "ASN_BER_TLV_t* %s::BER_encode_TLV(const TTCN_Typedescriptor_t&"
444 " p_td, unsigned p_coding) const\n"
445 "{\n"
446 " BER_chk_descr(p_td);\n"
447 " ASN_BER_TLV_t *new_tlv=BER_encode_chk_bound(is_bound());\n"
448 " if(!new_tlv) {\n"
449 " BER_encode_chk_enum_valid(p_td, is_valid_enum(enum_value),"
450 " enum_value);\n"
451 " new_tlv=BER_encode_TLV_INTEGER(p_coding, enum_value);\n"
452 " }\n"
453 " new_tlv=ASN_BER_V2TLV(new_tlv, p_td, p_coding);\n"
454 " return new_tlv;\n"
455 "}\n"
456 "\n"
457 "boolean %s::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,"
458 " const ASN_BER_TLV_t& p_tlv, unsigned L_form)\n"
459 "{\n"
460 " enum_value = %s;\n"
461 " BER_chk_descr(p_td);\n"
462 " ASN_BER_TLV_t stripped_tlv;\n"
463 " BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);\n"
464 " TTCN_EncDec_ErrorContext ec(\"While decoding ENUMERATED type %s: "
465 "\");\n"
466 " int tmp_mfr;\n"
467 " if (BER_decode_TLV_INTEGER(stripped_tlv, L_form, tmp_mfr)) {\n"
468 " BER_decode_chk_enum_valid(p_td, is_valid_enum(tmp_mfr), tmp_mfr);\n"
469 " enum_value = (%s)tmp_mfr;\n"
470 " return TRUE;\n"
471 " } else return FALSE;\n"
472 "}\n\n"
473 , name, name, unbound_value, dispname, enum_type);
474 } /* if ber_needed */
475 /* new TEXT functions */
476 if(text_needed){
477 src = mputprintf(src,
478 "int %s::TEXT_encode(const TTCN_Typedescriptor_t& p_td,"
479 "TTCN_Buffer& p_buf) const{\n"
480 "int encoded_length=0;\n"
481 "if(p_td.text->begin_encode){\n"
482 " p_buf.put_cs(*p_td.text->begin_encode);\n"
483 " encoded_length+=p_td.text->begin_encode->lengthof();\n"
484 "}\n"
485 " if (enum_value == %s) {\n"
486 " TTCN_EncDec_ErrorContext::error\n"
487 " (TTCN_EncDec::ET_UNBOUND, \"Encoding an unbound value of "
488 "enumerated type %s.\");\n"
489 " if(p_td.text->end_encode){\n"
490 " p_buf.put_cs(*p_td.text->end_encode);\n"
491 " encoded_length+=p_td.text->end_encode->lengthof();\n"
492 " }\n"
493 " return encoded_length;\n"
494 " }\n"
495 "if(p_td.text->val.enum_values==NULL){\n"
496 " int len=strlen(enum_to_str(enum_value));\n"
497 " p_buf.put_s(len,(const unsigned char*)enum_to_str(enum_value));\n"
498 " encoded_length+=len;\n"
499 "} else {\n"
500 "switch(enum_value){\n"
501 , name, unbound_value, dispname
502 );
503 for(i=0;i<edef->nElements;i++){
504 src = mputprintf(src,
505 "case %s: \n"
506 "if(p_td.text->val.enum_values[%lu].encode_token){\n"
507 " p_buf.put_cs(*p_td.text->val.enum_values[%lu].encode_token);\n"
508 " encoded_length+=p_td.text->val.enum_values[%lu]"
509 ".encode_token->lengthof();\n"
510 "} else { "
511 " int len=strlen(enum_to_str(enum_value));\n"
512 " p_buf.put_s(len,(const unsigned char*)enum_to_str(enum_value));\n"
513 " encoded_length+=len;\n"
514 "}\n"
515 "break;\n"
516 ,edef->elements[i].name,
517 (unsigned long) i,(unsigned long) i,(unsigned long) i
518 );
519 }
520
521 src = mputstr(src,
522 " default:\n"
523 "break;\n"
524 "}\n"
525 "}\n"
526 " if(p_td.text->end_encode){\n"
527 " p_buf.put_cs(*p_td.text->end_encode);\n"
528 " encoded_length+=p_td.text->end_encode->lengthof();\n"
529 " }\n"
530 " return encoded_length;\n"
531 "}\n"
532 );
533 src = mputprintf(src,
534 "int %s::TEXT_decode(const TTCN_Typedescriptor_t& p_td,"
535 " TTCN_Buffer& p_buf, Limit_Token_List&, boolean no_err, boolean){\n"
536 " int decoded_length=0;\n"
537 " int str_len=0;\n"
538 " if(p_td.text->begin_decode){\n"
539 " int tl;\n"
540 " if((tl=p_td.text->begin_decode->match_begin(p_buf))<0){\n"
541 " if(no_err)return -1;\n"
542 " TTCN_EncDec_ErrorContext::error\n"
543 " (TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%%s'"
544 " not found for '%%s': \",(const char*)*(p_td.text->begin_decode)"
545 ", p_td.name);\n"
546 " return 0;\n"
547 " }\n"
548 " decoded_length+=tl;\n"
549 " p_buf.increase_pos(tl);\n"
550 " }\n"
551 " if(p_buf.get_read_len()<1 && no_err) return -1;\n"
552 ,name
553 );
554
555
556 for(i=0;i<edef->nElements;i++){
557 src = mputprintf(src,
558 "if((str_len=p_td.text->val.enum_values[%lu].decode_token->"
559 "match_begin(p_buf))!=-1){\n"
560 " enum_value=%s;\n"
561 "} else "
562 ,(unsigned long) i,edef->elements[i].name
563 );
564 }
565
566 src = mputstr(src,
567 " {\n"
568 " if(no_err)return -1;\n"
569 " TTCN_EncDec_ErrorContext::error"
570 "(TTCN_EncDec::ET_TOKEN_ERR, \"No enum token found for '%s': \""
571 ",p_td.name);\n"
572 " return decoded_length;\n"
573 "}\n"
574 " decoded_length+=str_len;\n"
575 " p_buf.increase_pos(str_len);\n"
576 " if(p_td.text->end_decode){\n"
577 " int tl;\n"
578 " if((tl=p_td.text->end_decode->match_begin(p_buf))<0){\n"
579 " if(no_err)return -1;\n"
580 " TTCN_EncDec_ErrorContext::error"
581 "(TTCN_EncDec::ET_TOKEN_ERR, \"The specified token '%s'"
582 " not found for '%s': \",(const char*)*(p_td.text->end_decode)"
583 ",p_td.name);\n"
584 " return decoded_length;\n"
585 " }\n"
586 " decoded_length+=tl;\n"
587 " p_buf.increase_pos(tl);\n"
588 " }\n"
589 " return decoded_length;\n"
590 "}\n"
591 );
592 }
593 /* new RAW functions */
594 if (raw_needed) {
595 int min_bits = 0;
596 int max_val = edef->firstUnused;
597 size_t a;
598 for (a = 0; a < edef->nElements; a++) {
599 int val = edef->elements[a].value;
600 if (abs(max_val) < abs(val)) max_val = val;
601 }
602 if (max_val < 0) {
603 min_bits = 1;
604 max_val = -max_val;
605 }
606 while (max_val) {
607 min_bits++;
608 max_val /= 2;
609 }
610 src = mputprintf(src,
611 "int %s::RAW_decode(const TTCN_Typedescriptor_t& p_td,TTCN_Buffer& p_buf,"
612 "int limit, raw_order_t top_bit_ord, boolean no_err, int, boolean)\n"
613 "{\n"
614 " int decoded_value = 0;\n"
615 " int decoded_length = RAW_decode_enum_type(p_td, p_buf, limit, "
616 "top_bit_ord, decoded_value, %d, no_err);\n"
617 " if (decoded_length < 0) return decoded_length;\n"
618 " if (is_valid_enum(decoded_value)) "
619 "enum_value = (%s)decoded_value;\n"
620 " else {\n"
621 " if(no_err){\n"
622 " return -1;\n"
623 " } else {\n"
624 " TTCN_EncDec_ErrorContext::error\n"
625 " (TTCN_EncDec::ET_ENC_ENUM, \"Invalid enum value '%%d'"
626 " for '%%s': \",decoded_value, p_td.name);\n"
627 " enum_value = %s;\n"
628 " }\n"
629 " }\n"
630 " return decoded_length;\n"
631 "}\n\n", name, min_bits, enum_type, unknown_value);
632 src = mputprintf(src,
633 "int %s::RAW_encode(const TTCN_Typedescriptor_t& p_td, "
634 "RAW_enc_tree& myleaf) const\n"
635 "{\n"
636 " return RAW_encode_enum_type(p_td, myleaf, (int)enum_value, %d);\n"
637 "}\n\n", name, min_bits);
638 } /* if raw_needed */
639
640 if (xer_needed) { /* XERSTUFF encoder codegen for enum */
641 /* FIXME This is redundant,
642 * because the code is identical to BaseType::can_start()
643 * and enum types are derived from BaseType or EnumType (which, in turn,
644 * is derived from BaseType). However, the declaration of can_start()
645 * is written by def_encdec() in encdec.c, which doesn't know
646 * that this is an enum type. Maybe we need to pass an is_enum to
647 * def_encdec, and then we can omit generating can_start() for enums.
648 */
649 src = mputprintf(src,
650 "boolean %s::can_start(const char *name, const char *uri, "
651 "const XERdescriptor_t& xd, unsigned int flavor) {\n"
652 " boolean exer = is_exer(flavor);\n"
653 " return check_name(name, xd, exer) && (!exer || check_namespace(uri, xd));\n"
654 "}\n\n"
655 , name
656 );
657
658 src = mputprintf(src,
659 "int %s::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,"
660 " unsigned int p_flavor, int p_indent, embed_values_enc_struct_t*) const\n"
661 "{\n"
662 " int encoded_length=(int)p_buf.get_len();\n"
663 " const boolean e_xer = is_exer(p_flavor);\n"
664 " p_flavor |= (SIMPLE_TYPE | BXER_EMPTY_ELEM);\n"
665 " if (begin_xml(p_td, p_buf, p_flavor, p_indent, false) == -1) "
666 "--encoded_length;\n"
667 " if (!e_xer) p_buf.put_c('<');\n"
668 , name
669 );
670 if (edef->xerUseNumber) {
671 src = mputstr(src,
672 " if (e_xer) {\n" /* compile-time instead of p_td.useNumber */
673 " char sval[24];\n" /* unsigned 64 bits fit in 20 characters */
674 " int slen = snprintf(sval, 24, \"%d\", enum_value);\n"
675 " if (slen > 0) p_buf.put_s((size_t)slen, (const unsigned char*)sval);\n"
676 " }\n"
677 " else" /* no newline, will take over following curly */
678 );
679 }
680 src = mputprintf(src,
681 " {\n"
682 " const char * enumval = enum_to_str(enum_value%s);\n"
683 " p_buf.put_s(strlen(enumval), (const unsigned char*)enumval);\n"
684 " }\n"
685 " if (!e_xer) p_buf.put_s(2, (const unsigned char*)\"/>\");\n"
686 " end_xml(p_td, p_buf, p_flavor, p_indent, false);\n"
687 , edef->xerText ? ", e_xer" : ""
688 );
689 src = mputstr(src,
690 " return (int)p_buf.get_len() - encoded_length;\n"
691 "}\n\n");
692
693 src = mputprintf(src, /* XERSTUFF decoder codegen for enum */
694 #ifndef NDEBUG
695 "// written by %s in " __FILE__ " at %d\n"
696 #endif
697 "int %s::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& p_reader,"
698 " unsigned int p_flavor, unsigned int /*p_flavor2*/, embed_values_dec_struct_t*)\n"
699 "{\n"
700 " int rd_ok = 1, type;\n"
701
702 " const int e_xer = is_exer(p_flavor);\n"
703 " const boolean name_tag = !((!e_xer && is_record_of(p_flavor)) || (e_xer && ((p_td.xer_bits & UNTAGGED) ||(is_record_of(p_flavor) && is_exerlist(p_flavor)))));\n"
704 " if (e_xer && ((p_td.xer_bits & XER_ATTRIBUTE) || is_exerlist(p_flavor))) {\n"
705 " if ((p_td.xer_bits & XER_ATTRIBUTE)) verify_name(p_reader, p_td, e_xer);\n"
706 " const char * value = (const char *)p_reader.Value();\n"
707 " if (value) {\n"
708 #ifndef NDEBUG
709 , __FUNCTION__, __LINE__
710 #endif
711 , name);
712 if (edef->xerUseNumber) {
713 src = mputprintf(src,
714 " int tempvalue;\n"
715 " sscanf(value, \"%%d\", &tempvalue);\n"
716 " if (is_valid_enum(tempvalue)) enum_value = (%s)tempvalue;\n" /* static_cast would be nice */
717 " else enum_value = %s;\n", enum_type, unknown_value
718 );
719 }
720 else {
721 src = mputstr(src, " enum_value = str_to_enum(value);\n");
722 }
723 src = mputstr(src,
724 " }\n"
725 /* The caller should do AdvanceAttribute() */
726 " }\n"
727 " else {\n"
728 " if (name_tag)"
729 /* Go past the opening tag with the type name */
730 " for (; rd_ok == 1; rd_ok = p_reader.Read()) {\n"
731 " type = p_reader.NodeType();\n"
732 " if (XML_READER_TYPE_ELEMENT == type) {\n"
733 " rd_ok = p_reader.Read();\n"
734 " break;\n"
735 " }\n"
736 " }\n"
737 /* Go to the element with the actual data (EmptyElementEnumerated) */
738 " for (; rd_ok == 1; rd_ok = p_reader.Read()) {\n"
739 " type = p_reader.NodeType();\n"
740 " if (!e_xer && XML_READER_TYPE_ELEMENT == type) break;\n"
741 " if (XML_READER_TYPE_TEXT == type) break;\n"
742 " }\n"
743 " const char *local_name = e_xer ? (const char *)p_reader.Value() : (const char *)p_reader.Name();\n"
744 /* TextEnumerated EmptyElementEnumerated */
745 " if (!local_name) ; else");
746 if (edef->xerUseNumber) {
747 src = mputprintf(src,
748 " if (e_xer) {\n"
749 " int tempvalue;\n"
750 " sscanf(local_name, \"%%d\", &tempvalue);\n"
751 " if (is_valid_enum(tempvalue)) enum_value = (%s)tempvalue;\n" /* static_cast would be nice */
752 " else enum_value = %s;\n"
753 " }\n"
754 " else" /* no newline */ , enum_type, unknown_value
755 );
756 }
757 {
758 src = mputstr(src,
759 " {\n"
760 " for (; '\\t'==*local_name || '\\n'==*local_name; ++local_name) ;\n" /* crutch while default-for-empty always puts in a newline */
761 " enum_value = str_to_enum(local_name);\n"
762 " }\n");
763 }
764 src = mputprintf(src,
765 " if (name_tag)\n"
766 " for (rd_ok = p_reader.Read(); rd_ok == 1; rd_ok = p_reader.Read()) {\n"
767 " type = p_reader.NodeType();\n"
768 " if (XML_READER_TYPE_END_ELEMENT == type) {\n"
769 " rd_ok = p_reader.Read();\n"
770 " break;\n"
771 " }\n"
772 " }\n"
773 " else rd_ok = p_reader.Read();\n"
774 " }\n"
775 " if (e_xer && (p_flavor & EXIT_ON_ERROR) && %s == enum_value) clean_up();\n" // set to unbound if decoding failed
776 " int decoded_length = 0;\n"
777 " return decoded_length;\n"
778 "}\n\n"
779 , unknown_value);
780 }
781 if (json_needed) {
782 // JSON encode
783 src = mputprintf(src,
784 "int %s::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const\n"
785 "{\n"
786 " if (enum_value == %s) {\n"
787 " TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,\n"
788 " \"Encoding an unbound value of enumerated type %s.\");\n"
789 " return -1;\n"
790 " }\n\n"
791 " char* tmp_str = mprintf(\"\\\"%%s\\\"\", enum_to_str(enum_value));\n"
792 " int enc_len = p_tok.put_next_token(JSON_TOKEN_STRING, tmp_str);\n"
793 " Free(tmp_str);\n"
794 " return enc_len;\n"
795 "}\n\n"
796 , name, unbound_value, dispname);
797
798 // JSON decode
799 src = mputprintf(src,
800 "int %s::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok, boolean p_silent)\n"
801 "{\n"
802 " json_token_t token = JSON_TOKEN_NONE;\n"
803 " char* value = 0;\n"
804 " size_t value_len = 0;\n"
805 " boolean error = false;\n"
806 " int dec_len = 0;\n"
807 " boolean use_default = p_td.json->default_value && 0 == p_tok.get_buffer_length();\n"
808 " if (use_default) {\n"
809 // No JSON data in the buffer -> use default value
810 " value = (char*)p_td.json->default_value;\n"
811 " value_len = strlen(value);\n"
812 " } else {\n"
813 " dec_len = p_tok.get_next_token(&token, &value, &value_len);\n"
814 " }\n"
815 " if (JSON_TOKEN_ERROR == token) {\n"
816 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_BAD_TOKEN_ERROR, \"\");\n"
817 " return JSON_ERROR_FATAL;\n"
818 " }\n"
819 " else if (JSON_TOKEN_STRING == token || use_default) {\n"
820 " if (use_default || (value_len > 2 && value[0] == '\\\"' && value[value_len - 1] == '\\\"')) {\n"
821 " if (!use_default) value[value_len - 1] = 0;\n"
822 " enum_value = str_to_enum(value + (use_default ? 0 : 1));\n"
823 " if (!use_default) value[value_len - 1] = '\\\"';\n"
824 " if (%s == enum_value) {\n"
825 " error = true;\n"
826 " }\n"
827 " } else {\n"
828 " error = true;\n"
829 " }\n"
830 " } else {\n"
831 " enum_value = %s;\n"
832 " return JSON_ERROR_INVALID_TOKEN;\n"
833 " }\n\n"
834 " if (error) {\n"
835 " JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FORMAT_ERROR, \"string\", \"enumerated\");\n"
836 " enum_value = %s;\n"
837 " return JSON_ERROR_FATAL;\n"
838 " }\n"
839 " return dec_len;\n"
840 "}\n\n"
841 , name, unknown_value, unbound_value, unbound_value);
842 }
843 /* end of class */
844 def = mputstr(def, "};\n\n");
845
846 output->header.class_defs = mputstr(output->header.class_defs, def);
847 Free(def);
848 output->source.methods = mputstr(output->source.methods, src);
849 Free(src);
850
851
852 Free(enum_type);
853 Free(qualified_enum_type);
854 Free(unknown_value);
855 Free(unbound_value);
856 }
857
858 void defEnumTemplate(const enum_def *edef, output_struct *output)
859 {
860 char *def = NULL, *src = NULL;
861 const char *name = edef->name, *dispname = edef->dispname;
862
863 char *enum_type, *unbound_value, *unknown_value;
864 enum_type = mprintf("%s::enum_type", name);
865 unbound_value = mprintf("%s::UNBOUND_VALUE", name);
866 unknown_value = mprintf("%s::UNKNOWN_VALUE", name);
867
868 /* Class declaration */
869 output->header.class_decls = mputprintf(output->header.class_decls,
870 "class %s_template;\n", name);
871
872 /* Class definition */
873 def = mputprintf(def, "class %s_template : public Base_Template {\n"
874 "union {\n"
875 "%s single_value;\n"
876 "struct {\n"
877 "unsigned int n_values;\n"
878 "%s_template *list_value;\n"
879 "} value_list;\n"
880 "};\n\n", name, enum_type, name);
881
882 /* private members */
883 def = mputprintf(def, "void copy_template(const %s_template& "
884 "other_value);\n", name);
885 src = mputprintf(src,
886 "void %s_template::copy_template(const %s_template& "
887 "other_value)\n"
888 "{\n"
889 "set_selection(other_value);\n"
890 "switch (template_selection) {\n"
891 "case SPECIFIC_VALUE:\n"
892 "single_value = other_value.single_value;\n"
893 "break;\n"
894 "case OMIT_VALUE:\n"
895 "case ANY_VALUE:\n"
896 "case ANY_OR_OMIT:\n"
897 "break;\n"
898 "case VALUE_LIST:\n"
899 "case COMPLEMENTED_LIST:\n"
900 "value_list.n_values = other_value.value_list.n_values;\n"
901 "value_list.list_value = new %s_template[value_list.n_values];\n"
902 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
903 "list_count++)\n"
904 "value_list.list_value[list_count].copy_template("
905 "other_value.value_list.list_value[list_count]);\n"
906 "break;\n"
907 "default:\n"
908 "TTCN_error(\"Copying an uninitialized/unsupported template of "
909 "enumerated type %s.\");\n"
910 "}\n"
911 "}\n\n", name, name, name, dispname);
912
913 def = mputstr(def, "\npublic:\n");
914
915 /* constructors */
916 def = mputprintf(def, "%s_template();\n", name);
917 src = mputprintf(src,
918 "%s_template::%s_template()\n"
919 "{\n"
920 "}\n\n", name, name);
921
922 def = mputprintf(def, "%s_template(template_sel other_value);\n", name);
923 src = mputprintf(src,
924 "%s_template::%s_template(template_sel other_value)\n"
925 " : Base_Template(other_value)\n"
926 "{\n"
927 "check_single_selection(other_value);\n"
928 "}\n\n", name, name);
929
930 def = mputprintf(def, "%s_template(int other_value);\n", name);
931 src = mputprintf(src,
932 "%s_template::%s_template(int other_value)\n"
933 " : Base_Template(SPECIFIC_VALUE)\n"
934 "{\n"
935 "if (!%s::is_valid_enum(other_value)) "
936 "TTCN_error(\"Initializing a template of enumerated type %s with "
937 "unknown numeric value %%d.\", other_value);\n"
938 "single_value = (%s)other_value;\n"
939 "}\n\n", name, name, name, dispname, enum_type);
940
941 def = mputprintf(def, "%s_template(%s other_value);\n", name, enum_type);
942 src = mputprintf(src,
943 "%s_template::%s_template(%s other_value)\n"
944 " : Base_Template(SPECIFIC_VALUE)\n"
945 "{\n"
946 "single_value = other_value;\n"
947 "}\n\n", name, name, enum_type);
948
949 def = mputprintf(def, "%s_template(const %s& other_value);\n", name, name);
950 src = mputprintf(src,
951 "%s_template::%s_template(const %s& other_value)\n"
952 " : Base_Template(SPECIFIC_VALUE)\n"
953 "{\n"
954 "if (other_value.enum_value == %s) "
955 "TTCN_error(\"Creating a template from an unbound value of enumerated "
956 "type %s.\");\n"
957 "single_value = other_value.enum_value;\n"
958 "}\n\n", name, name, name, unbound_value, dispname);
959
960 def = mputprintf(def, "%s_template(const OPTIONAL<%s>& other_value);\n",
961 name, name);
962 src = mputprintf(src,
963 "%s_template::%s_template(const OPTIONAL<%s>& other_value)\n"
964 "{\n"
965 "switch (other_value.get_selection()) {\n"
966 "case OPTIONAL_PRESENT:\n"
967 "set_selection(SPECIFIC_VALUE);\n"
968 "single_value = (%s)(const %s&)other_value;\n"
969 "break;\n"
970 "case OPTIONAL_OMIT:\n"
971 "set_selection(OMIT_VALUE);\n"
972 "break;\n"
973 "default:\n"
974 "TTCN_error(\"Creating a template of enumerated type %s from an unbound "
975 "optional field.\");\n"
976 "}\n"
977 "}\n\n", name, name, name, enum_type, name, dispname);
978
979 def = mputprintf(def, "%s_template(const %s_template& other_value);\n",
980 name, name);
981 src = mputprintf(src,
982 "%s_template::%s_template(const %s_template& other_value)\n"
983 " : Base_Template()\n"
984 "{\n"
985 "copy_template(other_value);\n"
986 "}\n\n", name, name, name);
987
988 /* destructor */
989 def = mputprintf(def, "~%s_template();\n\n", name);
990 src = mputprintf(src,
991 "%s_template::~%s_template()\n"
992 "{\n"
993 "clean_up();\n"
994 "}\n\n", name, name);
995
996 /* is_bound */
997 def = mputstr(def, "boolean is_bound() const;\n");
998 src = mputprintf(src, "boolean %s_template::is_bound() const\n"
999 "{\n"
1000 "if (template_selection == UNINITIALIZED_TEMPLATE && !is_ifpresent) "
1001 "return FALSE;\n", name);
1002 src = mputstr(src, "return TRUE;\n"
1003 "}\n\n");
1004
1005 /* is_value */
1006 def = mputstr(def, "boolean is_value() const;\n");
1007 src = mputprintf(src, "boolean %s_template::is_value() const\n"
1008 "{\n"
1009 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) "
1010 "return FALSE;\n"
1011 "return single_value != %s;\n"
1012 "}\n\n", name, unbound_value);
1013
1014 /* clean_up */
1015 def = mputstr(def, "void clean_up();\n");
1016 src = mputprintf(src,
1017 "void %s_template::clean_up()\n"
1018 "{\n"
1019 "if (template_selection == VALUE_LIST || "
1020 "template_selection == COMPLEMENTED_LIST) "
1021 "delete [] value_list.list_value;\n"
1022 "template_selection = UNINITIALIZED_TEMPLATE;\n"
1023 "}\n\n", name);
1024
1025 /* assignment operators */
1026 def = mputprintf(def, "%s_template& operator=(template_sel other_value);\n",
1027 name);
1028 src = mputprintf(src,
1029 "%s_template& %s_template::operator=(template_sel other_value)\n"
1030 "{\n"
1031 "check_single_selection(other_value);\n"
1032 "clean_up();\n"
1033 "set_selection(other_value);\n"
1034 "return *this;\n"
1035 "}\n\n", name, name);
1036
1037 def = mputprintf(def, "%s_template& operator=(int other_value);\n",
1038 name);
1039 src = mputprintf(src,
1040 "%s_template& %s_template::operator=(int other_value)\n"
1041 "{\n"
1042 "if (!%s::is_valid_enum(other_value)) "
1043 "TTCN_warning(\"Assigning unknown numeric value %%d to a template "
1044 "of enumerated type %s.\", other_value);\n"
1045 "clean_up();\n"
1046 "set_selection(SPECIFIC_VALUE);\n"
1047 "single_value = (%s)other_value;\n"
1048 "return *this;\n"
1049 "}\n\n", name, name, name, dispname, enum_type);
1050
1051 def = mputprintf(def, "%s_template& operator=(%s other_value);\n",
1052 name, enum_type);
1053 src = mputprintf(src,
1054 "%s_template& %s_template::operator=(%s other_value)\n"
1055 "{\n"
1056 "clean_up();\n"
1057 "set_selection(SPECIFIC_VALUE);\n"
1058 "single_value = other_value;\n"
1059 "return *this;\n"
1060 "}\n\n", name, name, enum_type);
1061
1062 def = mputprintf(def, "%s_template& operator=(const %s& other_value);\n",
1063 name, name);
1064 src = mputprintf(src,
1065 "%s_template& %s_template::operator=(const %s& other_value)\n"
1066 "{\n"
1067 "if (other_value.enum_value == %s) "
1068 "TTCN_error(\"Assignment of an unbound value of enumerated type %s to a "
1069 "template.\");\n"
1070 "clean_up();\n"
1071 "set_selection(SPECIFIC_VALUE);\n"
1072 "single_value = other_value.enum_value;\n"
1073 "return *this;\n"
1074 "}\n\n", name, name, name, unbound_value, dispname);
1075
1076 def = mputprintf(def, "%s_template& operator=(const OPTIONAL<%s>& "
1077 "other_value);\n", name, name);
1078 src = mputprintf(src,
1079 "%s_template& %s_template::operator=(const OPTIONAL<%s>& other_value)\n"
1080 "{\n"
1081 "clean_up();\n"
1082 "switch (other_value.get_selection()) {\n"
1083 "case OPTIONAL_PRESENT:\n"
1084 "set_selection(SPECIFIC_VALUE);\n"
1085 "single_value = (%s)(const %s&)other_value;\n"
1086 "break;\n"
1087 "case OPTIONAL_OMIT:\n"
1088 "set_selection(OMIT_VALUE);\n"
1089 "break;\n"
1090 "default:\n"
1091 "TTCN_error(\"Assignment of an unbound optional field to a template of "
1092 "enumerated type %s.\");\n"
1093 "}\n"
1094 "return *this;\n"
1095 "}\n\n", name, name, name, enum_type, name, dispname);
1096
1097 def = mputprintf(def, "%s_template& operator=(const %s_template& "
1098 "other_value);\n\n", name, name);
1099 src = mputprintf(src,
1100 "%s_template& %s_template::operator=(const %s_template& other_value)\n"
1101 "{\n"
1102 "if (&other_value != this) {\n"
1103 "clean_up();\n"
1104 "copy_template(other_value);\n"
1105 "}\n"
1106 "return *this;\n"
1107 "}\n\n", name, name, name);
1108
1109 /* match operators */
1110 def = mputprintf(def, "boolean match(%s other_value, boolean legacy = FALSE) "
1111 "const;\n", enum_type);
1112 src = mputprintf(src,
1113 "boolean %s_template::match(%s other_value, boolean) const\n"
1114 "{\n"
1115 "switch (template_selection) {\n"
1116 "case SPECIFIC_VALUE:\n"
1117 "return single_value == other_value;\n"
1118 "case OMIT_VALUE:\n"
1119 "return FALSE;\n"
1120 "case ANY_VALUE:\n"
1121 "case ANY_OR_OMIT:\n"
1122 "return TRUE;\n"
1123 "case VALUE_LIST:\n"
1124 "case COMPLEMENTED_LIST:\n"
1125 "for (unsigned int list_count = 0; list_count < value_list.n_values; "
1126 "list_count++)\n"
1127 "if (value_list.list_value[list_count].match(other_value)) "
1128 "return template_selection == VALUE_LIST;\n"
1129 "return template_selection == COMPLEMENTED_LIST;\n"
1130 "default:\n"
1131 "TTCN_error(\"Matching an uninitialized/unsupported template of "
1132 "enumerated type %s.\");\n"
1133 "}\n"
1134 "return FALSE;\n"
1135 "}\n\n", name, enum_type, dispname);
1136
1137 def = mputprintf(def, "boolean match(const %s& other_value, boolean legacy "
1138 "= FALSE) const;\n", name);
1139 src = mputprintf(src,
1140 "boolean %s_template::match(const %s& other_value, boolean) const\n"
1141 "{\n"
1142 "if (other_value.enum_value == %s) "
1143 "TTCN_error(\"Matching a template of enumerated type %s with an unbound "
1144 "value.\");\n"
1145 "return match(other_value.enum_value);\n"
1146 "}\n\n", name, name, unbound_value, dispname);
1147
1148 /* valueof operator */
1149 def = mputprintf(def, "%s valueof() const;\n", enum_type);
1150 src = mputprintf(src,
1151 "%s %s_template::valueof() const\n"
1152 "{\n"
1153 "if (template_selection != SPECIFIC_VALUE || is_ifpresent) "
1154 "TTCN_error(\"Performing a valueof or send operation on a "
1155 "non-specific template of enumerated type %s.\");\n"
1156 "return single_value;\n"
1157 "}\n\n", enum_type, name, dispname);
1158
1159 /* value list handling operators */
1160 def = mputstr
1161 (def,
1162 "void set_type(template_sel template_type, unsigned int list_length);\n");
1163 src = mputprintf(src,
1164 "void %s_template::set_type(template_sel template_type, "
1165 "unsigned int list_length)\n"
1166 "{\n"
1167 "if (template_type != VALUE_LIST && template_type != COMPLEMENTED_LIST) "
1168 "TTCN_error(\"Setting an invalid list type for a template of enumerated "
1169 "type %s.\");\n"
1170 "clean_up();\n"
1171 "set_selection(template_type);\n"
1172 "value_list.n_values = list_length;\n"
1173 "value_list.list_value = new %s_template[list_length];\n"
1174 "}\n\n", name, dispname, name);
1175
1176 def = mputprintf(def, "%s_template& list_item(unsigned int list_index);\n",
1177 name);
1178 src = mputprintf(src,
1179 "%s_template& %s_template::list_item(unsigned int list_index)\n"
1180 "{\n"
1181 "if (template_selection != VALUE_LIST && "
1182 "template_selection != COMPLEMENTED_LIST) "
1183 "TTCN_error(\"Accessing a list element in a non-list template of "
1184 "enumerated type %s.\");\n"
1185 "if (list_index >= value_list.n_values) "
1186 "TTCN_error(\"Index overflow in a value list template of enumerated type "
1187 "%s.\");\n"
1188 "return value_list.list_value[list_index];\n"
1189 "}\n\n", name, name, dispname, dispname);
1190
1191 if (use_runtime_2) {
1192 /** virtual stuff */
1193 def = mputstr(def,
1194 "void valueofv(Base_Type* value) const;\n"
1195 "void set_value(template_sel other_value);\n"
1196 "void copy_value(const Base_Type* other_value);\n"
1197 "Base_Template* clone() const;\n"
1198 "const TTCN_Typedescriptor_t* get_descriptor() const;\n"
1199 "boolean matchv(const Base_Type* other_value, boolean legacy) const;\n"
1200 "void log_matchv(const Base_Type* match_value, boolean legacy) const;\n");
1201 src = mputprintf(src,
1202 "void %s_template::valueofv(Base_Type* value) const "
1203 "{ *(static_cast<%s*>(value)) = valueof(); }\n"
1204 "void %s_template::set_value(template_sel other_value) "
1205 "{ *this = other_value; }\n"
1206 "void %s_template::copy_value(const Base_Type* other_value) "
1207 "{ *this = *(static_cast<const %s*>(other_value)); }\n"
1208 "Base_Template* %s_template::clone() const "
1209 "{ return new %s_template(*this); }\n"
1210 "const TTCN_Typedescriptor_t* %s_template::get_descriptor() const "
1211 "{ return &%s_descr_; }\n"
1212 "boolean %s_template::matchv(const Base_Type* other_value, "
1213 "boolean legacy) const "
1214 "{ return match(*(static_cast<const %s*>(other_value)), legacy); }\n"
1215 "void %s_template::log_matchv(const Base_Type* match_value, "
1216 "boolean legacy) const "
1217 " { log_match(*(static_cast<const %s*>(match_value)), legacy); }\n",
1218 name, name,
1219 name,
1220 name, name,
1221 name, name,
1222 name, name,
1223 name, name,
1224 name, name);
1225 }
1226
1227 /* logging functions */
1228 def = mputstr(def, "void log() const;\n");
1229 src = mputprintf
1230 (src,
1231 "void %s_template::log() const\n"
1232 "{\n"
1233 "switch (template_selection) {\n"
1234 "case SPECIFIC_VALUE:\n"
1235 "TTCN_Logger::log_event_enum(%s::enum_to_str(single_value), single_value);\n"
1236 "break;\n"
1237 "case COMPLEMENTED_LIST:\n"
1238 "TTCN_Logger::log_event_str(\"complement \");\n"
1239 "case VALUE_LIST:\n"
1240 "TTCN_Logger::log_char('(');\n"
1241 "for (unsigned int elem_count = 0; elem_count < value_list.n_values; "
1242 "elem_count++) {\n"
1243 "if (elem_count > 0) TTCN_Logger::log_event_str(\", \");\n"
1244 "value_list.list_value[elem_count].log();\n"
1245 "}\n"
1246 "TTCN_Logger::log_char(')');\n"
1247 "break;\n"
1248 "default:\n"
1249 "log_generic();\n"
1250 "}\n"
1251 "log_ifpresent();\n"
1252 "}\n\n", name, name);
1253
1254 def = mputprintf(def, "void log_match(const %s& match_value, "
1255 "boolean legacy = FALSE) const;\n", name);
1256 src = mputprintf(src,
1257 "void %s_template::log_match(const %s& match_value, boolean) const\n"
1258 "{\n"
1259 "match_value.log();\n"
1260 "TTCN_Logger::log_event_str(\" with \");\n"
1261 "log();\n"
1262 "if (match(match_value)) TTCN_Logger::log_event_str(\" matched\");\n"
1263 "else TTCN_Logger::log_event_str(\" unmatched\");\n"
1264 "}\n\n", name, name);
1265
1266 /* encoding/decoding functions */
1267 def = mputstr(def, "void encode_text(Text_Buf& text_buf) const;\n");
1268 src = mputprintf(src,
1269 "void %s_template::encode_text(Text_Buf& text_buf) "
1270 "const\n"
1271 "{\n"
1272 "encode_text_base(text_buf);\n"
1273 "switch (template_selection) {\n"
1274 "case SPECIFIC_VALUE:\n"
1275 "text_buf.push_int(single_value);\n"
1276 "case OMIT_VALUE:\n"
1277 "case ANY_VALUE:\n"
1278 "case ANY_OR_OMIT:\n"
1279 "break;\n"
1280 "case VALUE_LIST:\n"
1281 "case COMPLEMENTED_LIST:\n"
1282 "text_buf.push_int(value_list.n_values);\n"
1283 "for (unsigned int elem_count = 0; elem_count < value_list.n_values; "
1284 "elem_count++)\n"
1285 "value_list.list_value[elem_count].encode_text(text_buf);\n"
1286 "break;\n"
1287 "default:\n"
1288 "TTCN_error(\"Text encoder: Encoding an uninitialized/unsupported "
1289 "template of enumerated type %s.\");\n"
1290 "}\n"
1291 "}\n\n", name, dispname);
1292
1293 def = mputstr(def, "void decode_text(Text_Buf& text_buf);\n");
1294 src = mputprintf(src,
1295 "void %s_template::decode_text(Text_Buf& text_buf)\n"
1296 "{\n"
1297 "clean_up();\n"
1298 "decode_text_base(text_buf);\n"
1299 "switch (template_selection) {\n"
1300 "case SPECIFIC_VALUE:\n"
1301 "single_value = (%s)text_buf.pull_int().get_val();\n"
1302 "if (!%s::is_valid_enum(single_value)) "
1303 "TTCN_error(\"Text decoder: Unknown numeric value %%d was "
1304 "received for a template of enumerated type %s.\", single_value);\n"
1305 "case OMIT_VALUE:\n"
1306 "case ANY_VALUE:\n"
1307 "case ANY_OR_OMIT:\n"
1308 "break;\n"
1309 "case VALUE_LIST:\n"
1310 "case COMPLEMENTED_LIST:\n"
1311 "value_list.n_values = text_buf.pull_int().get_val();\n"
1312 "value_list.list_value = new %s_template[value_list.n_values];\n"
1313 "for (unsigned int elem_count = 0; elem_count < value_list.n_values; "
1314 "elem_count++)\n"
1315 "value_list.list_value[elem_count].decode_text(text_buf);\n"
1316 "break;\n"
1317 "default:\n"
1318 "TTCN_error(\"Text decoder: An unknown/unsupported selection was "
1319 "received for a template of enumerated type %s.\");\n"
1320 "}\n"
1321 "}\n\n", name, enum_type, name, dispname, name, dispname);
1322
1323 /* TTCN-3 ispresent() function */
1324 def = mputstr(def, "boolean is_present(boolean legacy = FALSE) const;\n");
1325 src = mputprintf(src,
1326 "boolean %s_template::is_present(boolean legacy) const\n"
1327 "{\n"
1328 "if (template_selection==UNINITIALIZED_TEMPLATE) return FALSE;\n"
1329 "return !match_omit(legacy);\n"
1330 "}\n\n", name);
1331
1332 /* match_omit() */
1333 def = mputstr(def, "boolean match_omit(boolean legacy = FALSE) const;\n");
1334 src = mputprintf(src,
1335 "boolean %s_template::match_omit(boolean legacy) const\n"
1336 "{\n"
1337 "if (is_ifpresent) return TRUE;\n"
1338 "switch (template_selection) {\n"
1339 "case OMIT_VALUE:\n"
1340 "case ANY_OR_OMIT:\n"
1341 "return TRUE;\n"
1342 "case VALUE_LIST:\n"
1343 "case COMPLEMENTED_LIST:\n"
1344 "if (legacy) {\n"
1345 "for (unsigned int i=0; i<value_list.n_values; i++)\n"
1346 "if (value_list.list_value[i].match_omit())\n"
1347 "return template_selection==VALUE_LIST;\n"
1348 "return template_selection==COMPLEMENTED_LIST;\n"
1349 "} // else fall through\n"
1350 "default:\n"
1351 "return FALSE;\n"
1352 "}\n"
1353 "return FALSE;\n"
1354 "}\n\n", name);
1355
1356 /* set_param() */
1357 def = mputstr(def, "void set_param(Module_Param& param);\n");
1358 src = mputprintf(src,
1359 "void %s_template::set_param(Module_Param& param)\n"
1360 "{\n"
1361 " param.basic_check(Module_Param::BC_TEMPLATE, \"enumerated template\");\n"
1362 " Module_Param_Ptr m_p = &param;\n"
1363 " if (param.get_type() == Module_Param::MP_Reference) {\n"
1364 /* enumerated values are also treated as references (containing only 1 name) by the parser;
1365 first check if the reference name is a valid enumerated value */
1366 " char* enum_name = param.get_enumerated();\n"
1367 /* get_enumerated() returns NULL if the reference contained more than one name */
1368 " %s enum_val = (enum_name != NULL) ? %s::str_to_enum(enum_name) : %s;\n"
1369 " if (%s::is_valid_enum(enum_val)) {\n"
1370 " *this = enum_val;\n"
1371 " is_ifpresent = param.get_ifpresent() || m_p->get_ifpresent();\n"
1372 " return;\n"
1373 " }\n"
1374 /* it's not a valid enum value => dereference it! */
1375 " m_p = param.get_referenced_param();\n"
1376 " }\n"
1377 " switch (m_p->get_type()) {\n"
1378 " case Module_Param::MP_Omit:\n"
1379 " *this = OMIT_VALUE;\n"
1380 " break;\n"
1381 " case Module_Param::MP_Any:\n"
1382 " *this = ANY_VALUE;\n"
1383 " break;\n"
1384 " case Module_Param::MP_AnyOrNone:\n"
1385 " *this = ANY_OR_OMIT;\n"
1386 " break;\n"
1387 " case Module_Param::MP_List_Template:\n"
1388 " case Module_Param::MP_ComplementList_Template: {\n"
1389 " %s_template new_temp;\n"
1390 " new_temp.set_type(m_p->get_type()==Module_Param::MP_List_Template ? "
1391 "VALUE_LIST : COMPLEMENTED_LIST, m_p->get_size());\n"
1392 " for (size_t p_i=0; p_i<m_p->get_size(); p_i++) {\n"
1393 " new_temp.list_item(p_i).set_param(*m_p->get_elem(p_i));\n"
1394 " }\n"
1395 " *this = new_temp;\n"
1396 " break; }\n"
1397 " case Module_Param::MP_Enumerated: {\n"
1398 " %s enum_val = %s::str_to_enum(m_p->get_enumerated());\n"
1399 " if (!%s::is_valid_enum(enum_val)) {\n"
1400 " param.error(\"Invalid enumerated value for type %s.\");\n"
1401 " }\n"
1402 " *this = enum_val;\n"
1403 " } break;\n"
1404 " default:\n"
1405 " param.type_error(\"enumerated template\", \"%s\");\n"
1406 " }\n"
1407 " is_ifpresent = param.get_ifpresent() || m_p->get_ifpresent();\n"
1408 "}\n\n", name, enum_type, name, unknown_value, name
1409 , name, enum_type, name, name, dispname, dispname);
1410
1411 /* get_param() */
1412 def = mputstr(def, "Module_Param* get_param(Module_Param_Name& param_name) const;\n");
1413 src = mputprintf
1414 (src,
1415 "Module_Param* %s_template::get_param(Module_Param_Name& param_name) const\n"
1416 "{\n"
1417 " Module_Param* m_p = NULL;\n"
1418 " switch (template_selection) {\n"
1419 " case UNINITIALIZED_TEMPLATE:\n"
1420 " m_p = new Module_Param_Unbound();\n"
1421 " break;\n"
1422 " case OMIT_VALUE:\n"
1423 " m_p = new Module_Param_Omit();\n"
1424 " break;\n"
1425 " case ANY_VALUE:\n"
1426 " m_p = new Module_Param_Any();\n"
1427 " break;\n"
1428 " case ANY_OR_OMIT:\n"
1429 " m_p = new Module_Param_AnyOrNone();\n"
1430 " break;\n"
1431 " case SPECIFIC_VALUE:\n"
1432 " m_p = new Module_Param_Enumerated(mcopystr(%s::enum_to_str(single_value)));\n"
1433 " break;\n"
1434 " case VALUE_LIST:\n"
1435 " case COMPLEMENTED_LIST: {\n"
1436 " if (template_selection == VALUE_LIST) {\n"
1437 " m_p = new Module_Param_List_Template();\n"
1438 " }\n"
1439 " else {\n"
1440 " m_p = new Module_Param_ComplementList_Template();\n"
1441 " }\n"
1442 " for (size_t i_i = 0; i_i < value_list.n_values; ++i_i) {\n"
1443 " m_p->add_elem(value_list.list_value[i_i].get_param(param_name));\n"
1444 " }\n"
1445 " break; }\n"
1446 " default:\n"
1447 " break;\n"
1448 " }\n"
1449 " if (is_ifpresent) {\n"
1450 " m_p->set_ifpresent();\n"
1451 " }\n"
1452 " return m_p;\n"
1453 "}\n\n", name, name);
1454
1455 if (!use_runtime_2) {
1456 /* check template restriction */
1457 def = mputstr(def, "void check_restriction(template_res t_res, "
1458 "const char* t_name=NULL, boolean legacy = FALSE) const;\n");
1459 src = mputprintf(src,
1460 "void %s_template::check_restriction(template_res t_res, const char* t_name,\n"
1461 "boolean legacy) const\n"
1462 "{\n"
1463 "if (template_selection==UNINITIALIZED_TEMPLATE) return;\n"
1464 "switch ((t_name&&(t_res==TR_VALUE))?TR_OMIT:t_res) {\n"
1465 "case TR_VALUE:\n"
1466 "if (!is_ifpresent && template_selection==SPECIFIC_VALUE) return;\n"
1467 "break;\n"
1468 "case TR_OMIT:\n"
1469 "if (!is_ifpresent && (template_selection==OMIT_VALUE || "
1470 "template_selection==SPECIFIC_VALUE)) return;\n"
1471 "break;\n"
1472 "case TR_PRESENT:\n"
1473 "if (!match_omit(legacy)) return;\n"
1474 "break;\n"
1475 "default:\n"
1476 "return;\n"
1477 "}\n"
1478 "TTCN_error(\"Restriction `%%s' on template of type %%s violated.\", "
1479 "get_res_name(t_res), t_name ? t_name : \"%s\");\n"
1480 "}\n\n", name, dispname);
1481 }
1482
1483 /* end of class */
1484 def = mputstr(def, "};\n\n");
1485
1486 output->header.class_defs = mputstr(output->header.class_defs, def);
1487 Free(def);
1488 output->source.methods = mputstr(output->source.methods, src);
1489 Free(src);
1490
1491 Free(enum_type);
1492 Free(unbound_value);
1493 Free(unknown_value);
1494 }
This page took 0.065336 seconds and 5 git commands to generate.