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