blob: 7398a46002bad2c17c6229f95e13229d53119c72 [file] [log] [blame]
vlm1d036692004-08-19 13:29:46 +00001#include "asn1c_internal.h"
2#include "asn1c_constraint.h"
vlmb2839012004-08-20 13:37:01 +00003#include "asn1c_misc.h"
4#include "asn1c_out.h"
vlm1d036692004-08-19 13:29:46 +00005
6#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
7#include <asn1fix_export.h> /* other exportable stuff from libasn1fix */
8
vlmb2839012004-08-20 13:37:01 +00009static int asn1c_emit_constraint_tables(arg_t *arg, int got_size);
vlm1d036692004-08-19 13:29:46 +000010static int emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range);
vlma447dea2004-09-07 06:31:15 +000011static int emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_range_t *r_value);
vlm1d036692004-08-19 13:29:46 +000012static int emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype);
13static asn1p_expr_type_e _find_terminal_type(arg_t *arg);
14static int emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1_integer_t natural_start, asn1_integer_t natural_stop);
15
16#define MKID(id) asn1c_make_identifier(0, (id), 0)
17
18static int global_compile_mark;
19
20int
21asn1c_emit_constraint_checking_code(arg_t *arg) {
22 asn1cnst_range_t *r_size;
23 asn1cnst_range_t *r_value;
24 asn1p_expr_t *expr = arg->expr;
25 asn1p_expr_type_e etype;
26 asn1p_constraint_t *ct;
27 int got_something = 0;
vlmb2839012004-08-20 13:37:01 +000028 int produce_st = 0;
vlm1d036692004-08-19 13:29:46 +000029
30 ct = expr->combined_constraints;
31 if(ct == NULL)
32 return 1; /* No additional constraints defined */
33
34 etype = _find_terminal_type(arg);
35
vlm5d6d4b82004-08-25 02:03:59 +000036 r_value=asn1constraint_compute_PER_range(etype, ct, ACT_EL_RANGE,0,0,0);
37 r_size = asn1constraint_compute_PER_range(etype, ct, ACT_CT_SIZE,0,0,0);
vlm1d036692004-08-19 13:29:46 +000038 if(r_value) {
vlm5d6d4b82004-08-25 02:03:59 +000039 if(r_value->incompatible
vlm1d036692004-08-19 13:29:46 +000040 || r_value->empty_constraint
41 || (r_value->left.type == ARE_MIN
42 && r_value->right.type == ARE_MAX)
43 || (etype == ASN_BASIC_BOOLEAN
44 && r_value->left.value == 0
45 && r_value->right.value == 1)
46 ) {
47 asn1constraint_range_free(r_value);
48 r_value = 0;
49 }
50 }
51 if(r_size) {
vlm5d6d4b82004-08-25 02:03:59 +000052 if(r_size->incompatible
vlm1d036692004-08-19 13:29:46 +000053 || r_size->empty_constraint
54 || (r_size->left.value == 0 /* or .type == MIN */
55 && r_size->right.type == ARE_MAX)
56 ) {
57 asn1constraint_range_free(r_size);
58 r_size = 0;
59 }
60 }
61
vlmb2839012004-08-20 13:37:01 +000062 /*
63 * Do we really need an "*st = sptr" pointer?
64 */
65 switch(etype) {
66 case ASN_BASIC_INTEGER:
67 case ASN_BASIC_ENUMERATED:
68 if(!(arg->flags & A1C_USE_NATIVE_INTEGERS))
69 produce_st = 1;
70 break;
vlmffa21d22004-08-21 07:34:58 +000071 case ASN_BASIC_BIT_STRING:
vlmb2839012004-08-20 13:37:01 +000072 case ASN_BASIC_OCTET_STRING:
73 produce_st = 1;
74 break;
75 default:
76 if(etype & ASN_STRING_MASK)
77 produce_st = 1;
78 break;
79 }
80 if(produce_st)
vlmffa21d22004-08-21 07:34:58 +000081 OUT("const %s_t *st = sptr;\n",
82 asn1c_type_name(arg, arg->expr, TNF_SAFE));
vlm1d036692004-08-19 13:29:46 +000083
84 if(r_size || r_value) {
85 if(r_size) {
86 OUT("size_t size;\n");
87 }
88 if(r_value)
89 switch(etype) {
90 case ASN_BASIC_INTEGER:
91 case ASN_BASIC_ENUMERATED:
92 OUT("long value;\n");
93 break;
94 case ASN_BASIC_BOOLEAN:
95 OUT("int value;\n");
96 break;
97 default:
98 break;
99 }
100 }
101
102 OUT("\n");
103
104 /*
105 * Protection against null input.
106 */
107 OUT("if(!sptr) {\n");
108 INDENT(+1);
109 OUT("_ASN_ERRLOG(app_errlog, app_key,\n");
vlm758530a2004-08-22 13:47:59 +0000110 OUT("\t\"%%s: value not given (%%s:%%d)\",\n");
111 OUT("\ttd->name, __FILE__, __LINE__);\n");
vlm1d036692004-08-19 13:29:46 +0000112 OUT("return -1;\n");
113 INDENT(-1);
114 OUT("}\n");
115 OUT("\n");
116
117 if(r_value)
vlma447dea2004-09-07 06:31:15 +0000118 emit_value_determination_code(arg, etype, r_value);
vlm1d036692004-08-19 13:29:46 +0000119 if(r_size)
120 emit_size_determination_code(arg, etype);
121
vlmb2839012004-08-20 13:37:01 +0000122 INDENT(-1);
123 REDIR(OT_CTABLES);
124 /* Emit FROM() tables */
125 asn1c_emit_constraint_tables(arg, r_size?1:0);
126 REDIR(OT_CODE);
127 INDENT(+1);
128
vlm1d036692004-08-19 13:29:46 +0000129 /*
130 * Here is an if() {} else {} constaint checking code.
131 */
132 OUT("\n");
133 OUT("if(");
134 INDENT(+1);
135 if(r_size) {
136 if(got_something++) { OUT("\n"); OUT(" && "); }
137 OUT("(");
138 emit_range_comparison_code(arg, r_size, "size", 0, -1);
139 OUT(")");
140 }
141 if(r_value) {
142 if(got_something++) { OUT("\n"); OUT(" && "); }
143 OUT("(");
144 if(etype == ASN_BASIC_BOOLEAN)
145 emit_range_comparison_code(arg, r_value,
146 "value", 0, 1);
147 else
148 emit_range_comparison_code(arg, r_value,
149 "value", -1, -1);
150 OUT(")");
151 }
152 if(ct->_compile_mark) {
153 if(got_something++) { OUT("\n"); OUT(" && "); }
vlm7e20dfc2004-08-22 13:11:40 +0000154 OUT("!check_permitted_alphabet_%d(sptr)",
vlm1d036692004-08-19 13:29:46 +0000155 ct->_compile_mark);
156 }
157 if(!got_something) {
158 OUT("1 /* No applicable constraints whatsoever */");
vlmb2839012004-08-20 13:37:01 +0000159 OUT(") {\n");
160 INDENT(-1);
161 INDENTED(OUT("/* Nothing is here. See below */\n"));
162 OUT("}\n");
163 OUT("\n");
164 return 1;
vlm1d036692004-08-19 13:29:46 +0000165 }
166 INDENT(-1);
167 OUT(") {\n");
168 INDENT(+1);
169 OUT("/* Constraint check succeeded */\n");
vlm22b03112004-08-22 12:37:35 +0000170 OUT("return 0;\n");
vlm1d036692004-08-19 13:29:46 +0000171 INDENT(-1);
172 OUT("} else {\n");
173 INDENT(+1);
174 OUT("_ASN_ERRLOG(app_errlog, app_key,\n");
vlm758530a2004-08-22 13:47:59 +0000175 OUT("\t\"%%s: constraint failed (%%s:%%d)\",\n");
176 OUT("\ttd->name, __FILE__, __LINE__);\n");
vlm1d036692004-08-19 13:29:46 +0000177 OUT("return -1;\n");
178 INDENT(-1);
179 OUT("}\n");
180
181 return 0;
182}
183
vlmb2839012004-08-20 13:37:01 +0000184static int
185asn1c_emit_constraint_tables(arg_t *arg, int got_size) {
vlm1d036692004-08-19 13:29:46 +0000186 asn1_integer_t range_start;
187 asn1_integer_t range_stop;
188 asn1p_expr_type_e etype;
189 asn1cnst_range_t *range;
vlmb2839012004-08-20 13:37:01 +0000190 asn1p_constraint_t *ct;
191 int utf8_full_alphabet_check = 0;
192 int max_table_size = 256;
vlm1d036692004-08-19 13:29:46 +0000193 int table[256];
194 int use_table;
195
vlmb2839012004-08-20 13:37:01 +0000196 ct = arg->expr->combined_constraints;
vlm1d036692004-08-19 13:29:46 +0000197 if(!ct) return 0;
198
199 etype = _find_terminal_type(arg);
200
vlm5d6d4b82004-08-25 02:03:59 +0000201 range = asn1constraint_compute_PER_range(etype, ct, ACT_CT_FROM, 0,0,0);
vlm1d036692004-08-19 13:29:46 +0000202 if(!range) return 0;
203
vlm5d6d4b82004-08-25 02:03:59 +0000204 if(range->incompatible
vlm1d036692004-08-19 13:29:46 +0000205 || range->empty_constraint) {
206 asn1constraint_range_free(range);
207 return 0;
208 }
209
vlm465f3c02004-09-06 08:07:19 +0000210
211 if(range->left.type == ARE_MIN
212 && range->right.type == ARE_MAX) {
213 /*
214 * The permitted alphabet constraint checker code guarantees
215 * that either both bounds (left/right) are present, or
216 * they're absent simultaneously. Thus, this assertion
217 * legitimately holds true.
218 */
219 assert(range->el_count == 0);
220 /* The full range is specified. Ignore it. */
221 return 0;
222 }
223
vlm1d036692004-08-19 13:29:46 +0000224 range_start = range->left.value;
225 range_stop = range->right.value;
226 assert(range->left.type == ARE_VALUE);
227 assert(range->right.type == ARE_VALUE);
228 assert(range_start <= range_stop);
229
230 range_start = 0; /* Force old behavior */
231
232 /*
233 * Check if we need a test table to check the alphabet.
234 */
235 use_table = 1;
vlmb2839012004-08-20 13:37:01 +0000236 if(range->el_count == 0) {
237 /*
238 * It's better to have a short if() check
239 * than waste 4k of table space
240 */
241 use_table = 0;
242 }
vlm1d036692004-08-19 13:29:46 +0000243 if((range_stop - range_start) > 255)
244 use_table = 0;
vlmb2839012004-08-20 13:37:01 +0000245 if(etype == ASN_STRING_UTF8String) {
246 if(range_stop >= 0x80)
247 use_table = 0;
248 else
249 max_table_size = 128;
250 }
vlm1d036692004-08-19 13:29:46 +0000251
252 if(!ct->_compile_mark)
253 ct->_compile_mark = ++global_compile_mark;
254
255 if(use_table) {
256 int i, n = 0;
257 int untl;
258 memset(table, 0, sizeof(table));
259 for(i = -1; i < range->el_count; i++) {
260 asn1cnst_range_t *r;
261 asn1_integer_t v;
262 if(i == -1) {
263 if(range->el_count) continue;
264 r = range;
265 } else {
266 r = range->elements[i];
267 }
268 for(v = r->left.value; v <= r->right.value; v++) {
269 assert((v - range_start) >= 0);
vlmb2839012004-08-20 13:37:01 +0000270 assert((v - range_start) < max_table_size);
vlm1d036692004-08-19 13:29:46 +0000271 table[v - range_start] = ++n;
272 }
273 }
274
vlm1d036692004-08-19 13:29:46 +0000275 untl = (range_stop - range_start) + 1;
276 untl += (untl % 16)?16 - (untl % 16):0;
vlmb2839012004-08-20 13:37:01 +0000277 OUT("static int permitted_alphabet_table_%d[%d] = {\n",
278 ct->_compile_mark, max_table_size);
vlm1d036692004-08-19 13:29:46 +0000279 for(n = 0; n < untl; n++) {
280 OUT("%d,", table[n]?1:0);
281 if(!((n+1) % 16)) {
282 int c;
283 if(!n) {
284 OUT("\n");
285 continue;
286 }
287 OUT("\t/* ");
288 for(c = n - 15; c <= n; c++) {
289 if(table[c]) {
290 int a = c + range_start;
291 if(a > 0x20 && a < 0x80)
292 OUT("%c", a);
293 else
294 OUT(".");
295 } else {
296 OUT(" ");
297 }
298 }
299 OUT(" */");
300 OUT("\n");
301 }
302 }
303 OUT("};\n");
304 OUT("\n");
vlmb2839012004-08-20 13:37:01 +0000305 } else if(etype == ASN_STRING_UTF8String) {
306 /*
307 * UTF8String type is a special case in many respects.
308 */
309 assert(range_stop > 255); /* This one's unobvious */
310 if(got_size) {
311 /*
312 * Size has been already determined.
313 * The UTF8String length checker also checks
314 * for the syntax validity, so we don't have
315 * to repeat this process twice.
316 */
317 ct->_compile_mark = 0; /* Don't generate code */
318 asn1constraint_range_free(range);
319 return 0;
320 } else {
321 utf8_full_alphabet_check = 1;
322 }
323 } else {
324 /*
325 * This permitted alphabet check will be
326 * expressed using conditional statements
327 * instead of table lookups. Table would be
328 * to large or otherwise inappropriate (too sparse?).
329 */
vlm1d036692004-08-19 13:29:46 +0000330 }
331
332 OUT("static int check_permitted_alphabet_%d(const void *sptr) {\n",
333 ct->_compile_mark);
vlmb2839012004-08-20 13:37:01 +0000334 INDENT(+1);
335 if(utf8_full_alphabet_check) {
336 OUT("if(UTF8String_length((UTF8String_t *)sptr, td->name, \n");
337 OUT("\tapp_errlog, app_key) == -1)\n");
vlmcdf661b2004-08-22 12:47:03 +0000338 OUT("\t\treturn -1; /* Alphabet (sic!) test failed. */\n");
vlmb2839012004-08-20 13:37:01 +0000339 OUT("\n");
340 } else {
vlm1d036692004-08-19 13:29:46 +0000341 if(use_table) {
342 OUT("int *table = permitted_alphabet_table_%d;\n",
343 ct->_compile_mark);
344 emit_alphabet_check_loop(arg, 0);
345 } else {
346 emit_alphabet_check_loop(arg, range);
347 }
vlmb2839012004-08-20 13:37:01 +0000348 }
vlmcdf661b2004-08-22 12:47:03 +0000349 OUT("return 0;\n");
vlmb2839012004-08-20 13:37:01 +0000350 INDENT(-1);
vlm1d036692004-08-19 13:29:46 +0000351 OUT("}\n");
352 OUT("\n");
353
354 asn1constraint_range_free(range);
355
356 return 0;
357}
358
359static int
360emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range) {
vlm1d036692004-08-19 13:29:46 +0000361 asn1_integer_t natural_stop;
vlmb08de152004-08-22 03:30:05 +0000362 asn1p_expr_t *terminal;
vlm1d036692004-08-19 13:29:46 +0000363
vlmb08de152004-08-22 03:30:05 +0000364 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, arg->expr);
365 if(terminal) {
366 OUT("/* The underlying type is %s */\n",
367 ASN_EXPR_TYPE2STR(terminal->expr_type));
368 } else {
369 terminal = arg->expr;
370 }
vlmffa21d22004-08-21 07:34:58 +0000371 OUT("const %s_t *st = sptr;\n",
vlmb08de152004-08-22 03:30:05 +0000372 asn1c_type_name(arg, terminal, TNF_SAFE));
vlm1d036692004-08-19 13:29:46 +0000373
vlmb08de152004-08-22 03:30:05 +0000374 switch(terminal->expr_type) {
vlm1d036692004-08-19 13:29:46 +0000375 case ASN_STRING_UTF8String:
vlmffa21d22004-08-21 07:34:58 +0000376 OUT("const uint8_t *ch = st->buf;\n");
377 OUT("const uint8_t *end = ch + st->size;\n");
vlm1d036692004-08-19 13:29:46 +0000378 OUT("\n");
379 OUT("for(; ch < end; ch++) {\n");
380 INDENT(+1);
381 OUT("uint8_t cv = *ch;\n");
vlmcdf661b2004-08-22 12:47:03 +0000382 if(!range) OUT("if(cv >= 0x80) return -1;\n");
vlm1d036692004-08-19 13:29:46 +0000383 natural_stop = 0xffffffffUL;
384 break;
385 case ASN_STRING_UniversalString:
vlm465f3c02004-09-06 08:07:19 +0000386 OUT("const uint8_t *ch = st->buf;\n");
387 OUT("const uint8_t *end = ch + st->size;\n");
vlm1d036692004-08-19 13:29:46 +0000388 OUT("\n");
vlm465f3c02004-09-06 08:07:19 +0000389 OUT("if(st->size %% 4) return -1; /* (size%%4)! */\n");
390 OUT("for(; ch < end; ch += 4) {\n");
vlm1d036692004-08-19 13:29:46 +0000391 INDENT(+1);
vlm465f3c02004-09-06 08:07:19 +0000392 OUT("uint32_t cv = (ch[0] << 24)\n");
393 OUT("\t\t| (ch[1] << 16)\n");
394 OUT("\t\t| (ch[2] << 8)\n");
395 OUT("\t\t| ch[3];\n");
vlmcdf661b2004-08-22 12:47:03 +0000396 if(!range) OUT("if(cv > 255) return -1;\n");
vlm1d036692004-08-19 13:29:46 +0000397 natural_stop = 0xffffffffUL;
398 break;
399 case ASN_STRING_BMPString:
vlm465f3c02004-09-06 08:07:19 +0000400 OUT("const uint8_t *ch = st->buf;\n");
401 OUT("const uint8_t *end = ch + st->size;\n");
vlm1d036692004-08-19 13:29:46 +0000402 OUT("\n");
vlm465f3c02004-09-06 08:07:19 +0000403 OUT("if(st->size %% 2) return -1; /* (size%%2)! */\n");
404 OUT("for(; ch < end; ch += 2) {\n");
vlm1d036692004-08-19 13:29:46 +0000405 INDENT(+1);
vlm465f3c02004-09-06 08:07:19 +0000406 OUT("uint16_t cv = (ch[0] << 8)\n");
407 OUT("\t\t| ch[1];\n");
vlmcdf661b2004-08-22 12:47:03 +0000408 if(!range) OUT("if(cv > 255) return -1;\n");
vlm1d036692004-08-19 13:29:46 +0000409 natural_stop = 0xffff;
410 break;
411 case ASN_BASIC_OCTET_STRING:
412 default:
vlmffa21d22004-08-21 07:34:58 +0000413 OUT("const uint8_t *ch = st->buf;\n");
414 OUT("const uint8_t *end = ch + st->size;\n");
vlm1d036692004-08-19 13:29:46 +0000415 OUT("\n");
416 OUT("for(; ch < end; ch++) {\n");
417 INDENT(+1);
418 OUT("uint8_t cv = *ch;\n");
419 natural_stop = 0xff;
420 break;
421 }
422
423 if(range) {
424 OUT("if(!(");
425 emit_range_comparison_code(arg, range, "cv", 0, natural_stop);
vlmcdf661b2004-08-22 12:47:03 +0000426 OUT(")) return -1;\n");
vlm1d036692004-08-19 13:29:46 +0000427 } else {
vlmcdf661b2004-08-22 12:47:03 +0000428 OUT("if(!table[cv]) return -1;\n");
vlm1d036692004-08-19 13:29:46 +0000429 }
430
431 INDENT(-1);
432 OUT("}\n");
433
434 return 0;
435}
436
437static int
438emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1_integer_t natural_start, asn1_integer_t natural_stop) {
439 int ignore_left;
440 int ignore_right;
vlmb2839012004-08-20 13:37:01 +0000441 int generated_something = 0;
vlm1d036692004-08-19 13:29:46 +0000442 int i;
443
444 for(i = -1; i < range->el_count; i++) {
445 asn1cnst_range_t *r;
446 if(i == -1) {
447 if(range->el_count) continue;
448 r = range;
449 } else {
450 if(i) OUT(" || ");
451 r = range->elements[i];
452 }
453
454 if(r != range) OUT("(");
455
456 ignore_left = (r->left.type == ARE_MIN)
457 || (natural_start != -1
458 && r->left.value <= natural_start);
459 ignore_right = (r->right.type == ARE_MAX)
460 || (natural_stop != -1
461 && r->right.value >= natural_stop);
462 if(ignore_left && ignore_right) {
463 OUT("1 /* Constraint matches natural range of %s */",
464 varname);
465 continue;
466 }
467
468 if(ignore_left) {
469 OUT("%s <= %lld", varname,
470 (long long)r->right.value);
471 } else if(ignore_right) {
472 OUT("%s >= %lld", varname,
473 (long long)r->left.value);
474 } else if(r->left.value == r->right.value) {
475 OUT("%s == %lld", varname,
476 (long long)r->right.value);
477 } else {
478 OUT("%s >= %lld && %s <= %lld",
479 varname,
480 (long long)r->left.value,
481 varname,
482 (long long)r->right.value);
483 }
484 if(r != range) OUT(")");
vlmb2839012004-08-20 13:37:01 +0000485 generated_something = 1;
vlm1d036692004-08-19 13:29:46 +0000486 }
487
vlmb2839012004-08-20 13:37:01 +0000488 return generated_something;
vlm1d036692004-08-19 13:29:46 +0000489}
490
491static int
492emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype) {
493
494 switch(etype) {
495 case ASN_BASIC_BIT_STRING:
496 OUT("if(st->size > 0) {\n");
497 OUT("\t/* Size in bits */\n");
vlm17dc9eb2004-09-05 10:42:19 +0000498 OUT("\tsize = 8 * (st->size - 1) - (st->buf[0] & 0x7);\n");
vlm1d036692004-08-19 13:29:46 +0000499 OUT("} else {\n");
500 OUT("\tsize = 0;\n");
501 OUT("}\n");
502 break;
503 case ASN_STRING_UniversalString:
504 OUT("size = st->size >> 2;\t/* 4 byte per character */\n");
505 break;
506 case ASN_STRING_BMPString:
507 OUT("size = st->size >> 1;\t/* 2 byte per character */\n");
508 break;
509 case ASN_STRING_UTF8String:
510 OUT("size = UTF8String_length(st, td->name, app_errlog, app_key);\n");
511 OUT("if(size == (size_t)-1) return -1;\n");
512 break;
513 case ASN_CONSTR_SET_OF:
514 case ASN_CONSTR_SEQUENCE_OF:
515 OUT("{ /* Determine the number of elements */\n");
516 INDENT(+1);
vlmb2839012004-08-20 13:37:01 +0000517 OUT("const A_%s_OF(void) *list;\n",
vlm1d036692004-08-19 13:29:46 +0000518 etype==ASN_CONSTR_SET_OF?"SET":"SEQUENCE");
vlmb2839012004-08-20 13:37:01 +0000519 OUT("(const void *)list = sptr;\n");
vlm1d036692004-08-19 13:29:46 +0000520 OUT("size = list->count;\n");
521 INDENT(-1);
522 OUT("}\n");
523 break;
vlmb2839012004-08-20 13:37:01 +0000524 case ASN_BASIC_OCTET_STRING:
525 OUT("size = st->size;\n");
526 break;
vlm1d036692004-08-19 13:29:46 +0000527 default:
vlmb2839012004-08-20 13:37:01 +0000528 if(etype & ASN_STRING_MASK) {
vlm1d036692004-08-19 13:29:46 +0000529 OUT("size = st->size;\n");
530 break;
531 } else {
532 const char *type_name = ASN_EXPR_TYPE2STR(etype);
533 if(!type_name) type_name = arg->expr->Identifier;
534 WARNING("SizeConstraint is not defined for %s",
535 type_name);
536 OUT_NOINDENT("#warning SizeConstraint "
537 "is not defined for %s!\n", type_name);
538 OUT("size = st->size;\n");
539 }
540 return -1;
541 }
542
543 return 0;
544}
545
546static int
vlma447dea2004-09-07 06:31:15 +0000547emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_range_t *r_value) {
vlm1d036692004-08-19 13:29:46 +0000548
549 switch(etype) {
550 case ASN_BASIC_INTEGER:
551 case ASN_BASIC_ENUMERATED:
552 if(arg->flags & A1C_USE_NATIVE_INTEGERS) {
vlmffa21d22004-08-21 07:34:58 +0000553 OUT("value = *(const int *)sptr;\n");
vlm1d036692004-08-19 13:29:46 +0000554 } else {
vlma447dea2004-09-07 06:31:15 +0000555 if(r_value->el_count == 0
556 && (
557 /* Speed-up common case: (0..MAX) */
558 (r_value->left.type == ARE_VALUE
559 && r_value->left.value == 0
560 && r_value->right.type == ARE_MAX)
561 ||
562 /* Speed-up common case: (MIN..-1) */
563 (r_value->left.type == ARE_MIN
564 && r_value->right.type == ARE_VALUE
565 && r_value->right.value == -1)
566 )) {
567 OUT("/* Check if the sign bit is present */\n");
568 OUT("value = st->buf ? ((st->buf[0] & 0x80) ? -1 : 1) : 0;\n");
569 break;
570 }
571
vlm1d036692004-08-19 13:29:46 +0000572 OUT("if(asn1_INTEGER2long(st, &value)) {\n");
573 INDENT(+1);
574 OUT("_ASN_ERRLOG(app_errlog, app_key,\n");
vlm758530a2004-08-22 13:47:59 +0000575 OUT("\t\"%%s: value too large (%%s:%%d)\",\n");
576 OUT("\ttd->name, __FILE__, __LINE__);\n");
vlm1d036692004-08-19 13:29:46 +0000577 OUT("return -1;\n");
578 INDENT(-1);
579 OUT("}\n");
580 }
581 break;
582 case ASN_BASIC_BOOLEAN:
vlmffa21d22004-08-21 07:34:58 +0000583 OUT("value = (*(const int *)sptr) ? 1 : 0;\n");
vlm1d036692004-08-19 13:29:46 +0000584 break;
585 default:
vlmffa21d22004-08-21 07:34:58 +0000586 WARNING("%s:%d: Value cannot be determined "
587 "for constraint check for %s",
588 arg->mod->source_file_name,
589 arg->expr->_lineno,
590 arg->expr->Identifier
591 );
592 OUT_NOINDENT(
593 "#error %s:%d: Value of %s cannot be determined\n",
594 arg->mod->source_file_name,
595 arg->expr->_lineno,
596 arg->expr->Identifier
597 );
vlm1d036692004-08-19 13:29:46 +0000598 break;
599 }
600
601 return 0;
602}
603
604static asn1p_expr_type_e
605_find_terminal_type(arg_t *arg) {
606 asn1p_expr_t *expr;
vlme8423bc2004-08-22 03:10:52 +0000607 expr = asn1f_find_terminal_type_ex(arg->asn, arg->mod, arg->expr);
vlm1d036692004-08-19 13:29:46 +0000608 if(expr) return expr->expr_type;
609 return A1TC_INVALID;
610}
611