blob: deeba8f7379e3f13c222caf8d2a09ead65071aec [file] [log] [blame]
Lev Walkin84cd58e2004-08-19 13:29:46 +00001#include "asn1c_internal.h"
2#include "asn1c_constraint.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00003#include "asn1c_misc.h"
4#include "asn1c_out.h"
Lev Walkin84cd58e2004-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
Lev Walkin59004fa2004-08-20 13:37:01 +00009static int asn1c_emit_constraint_tables(arg_t *arg, int got_size);
Lev Walkin84cd58e2004-08-19 13:29:46 +000010static int emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range);
11static int emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype);
12static 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;
Lev Walkin59004fa2004-08-20 13:37:01 +000028 int produce_st = 0;
Lev Walkin84cd58e2004-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
36 r_value=asn1constraint_compute_PER_range(etype, ct, ACT_EL_RANGE, 0, 0);
37 r_size = asn1constraint_compute_PER_range(etype, ct, ACT_CT_SIZE, 0, 0);
38 if(r_value) {
39 if(r_value->not_PER_visible
40 || r_value->extensible
41 || r_value->empty_constraint
42 || (r_value->left.type == ARE_MIN
43 && r_value->right.type == ARE_MAX)
44 || (etype == ASN_BASIC_BOOLEAN
45 && r_value->left.value == 0
46 && r_value->right.value == 1)
47 ) {
48 asn1constraint_range_free(r_value);
49 r_value = 0;
50 }
51 }
52 if(r_size) {
53 if(r_size->not_PER_visible
54 || r_size->extensible
55 || r_size->empty_constraint
56 || (r_size->left.value == 0 /* or .type == MIN */
57 && r_size->right.type == ARE_MAX)
58 ) {
59 asn1constraint_range_free(r_size);
60 r_size = 0;
61 }
62 }
63
Lev Walkin59004fa2004-08-20 13:37:01 +000064 /*
65 * Do we really need an "*st = sptr" pointer?
66 */
67 switch(etype) {
68 case ASN_BASIC_INTEGER:
69 case ASN_BASIC_ENUMERATED:
70 if(!(arg->flags & A1C_USE_NATIVE_INTEGERS))
71 produce_st = 1;
72 break;
Lev Walkin02b137d2004-08-21 07:34:58 +000073 case ASN_BASIC_BIT_STRING:
Lev Walkin59004fa2004-08-20 13:37:01 +000074 case ASN_BASIC_OCTET_STRING:
75 produce_st = 1;
76 break;
77 default:
78 if(etype & ASN_STRING_MASK)
79 produce_st = 1;
80 break;
81 }
82 if(produce_st)
Lev Walkin02b137d2004-08-21 07:34:58 +000083 OUT("const %s_t *st = sptr;\n",
84 asn1c_type_name(arg, arg->expr, TNF_SAFE));
Lev Walkin84cd58e2004-08-19 13:29:46 +000085
86 if(r_size || r_value) {
87 if(r_size) {
88 OUT("size_t size;\n");
89 }
90 if(r_value)
91 switch(etype) {
92 case ASN_BASIC_INTEGER:
93 case ASN_BASIC_ENUMERATED:
94 OUT("long value;\n");
95 break;
96 case ASN_BASIC_BOOLEAN:
97 OUT("int value;\n");
98 break;
99 default:
100 break;
101 }
102 }
103
104 OUT("\n");
105
106 /*
107 * Protection against null input.
108 */
109 OUT("if(!sptr) {\n");
110 INDENT(+1);
111 OUT("_ASN_ERRLOG(app_errlog, app_key,\n");
112 OUT("\t\"%%s: value not given\", td->name);\n");
113 OUT("return -1;\n");
114 INDENT(-1);
115 OUT("}\n");
116 OUT("\n");
117
118 if(r_value)
119 emit_value_determination_code(arg, etype);
120 if(r_size)
121 emit_size_determination_code(arg, etype);
122
Lev Walkin59004fa2004-08-20 13:37:01 +0000123 INDENT(-1);
124 REDIR(OT_CTABLES);
125 /* Emit FROM() tables */
126 asn1c_emit_constraint_tables(arg, r_size?1:0);
127 REDIR(OT_CODE);
128 INDENT(+1);
129
Lev Walkin84cd58e2004-08-19 13:29:46 +0000130 /*
131 * Here is an if() {} else {} constaint checking code.
132 */
133 OUT("\n");
134 OUT("if(");
135 INDENT(+1);
136 if(r_size) {
137 if(got_something++) { OUT("\n"); OUT(" && "); }
138 OUT("(");
139 emit_range_comparison_code(arg, r_size, "size", 0, -1);
140 OUT(")");
141 }
142 if(r_value) {
143 if(got_something++) { OUT("\n"); OUT(" && "); }
144 OUT("(");
145 if(etype == ASN_BASIC_BOOLEAN)
146 emit_range_comparison_code(arg, r_value,
147 "value", 0, 1);
148 else
149 emit_range_comparison_code(arg, r_value,
150 "value", -1, -1);
151 OUT(")");
152 }
153 if(ct->_compile_mark) {
154 if(got_something++) { OUT("\n"); OUT(" && "); }
155 OUT("check_permitted_alphabet_%d(sptr)",
156 ct->_compile_mark);
157 }
158 if(!got_something) {
159 OUT("1 /* No applicable constraints whatsoever */");
Lev Walkin59004fa2004-08-20 13:37:01 +0000160 OUT(") {\n");
161 INDENT(-1);
162 INDENTED(OUT("/* Nothing is here. See below */\n"));
163 OUT("}\n");
164 OUT("\n");
165 return 1;
Lev Walkin84cd58e2004-08-19 13:29:46 +0000166 }
167 INDENT(-1);
168 OUT(") {\n");
169 INDENT(+1);
170 OUT("/* Constraint check succeeded */\n");
Lev Walkin6db2f092004-08-22 12:37:35 +0000171 OUT("return 0;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000172 INDENT(-1);
173 OUT("} else {\n");
174 INDENT(+1);
175 OUT("_ASN_ERRLOG(app_errlog, app_key,\n");
176 OUT("\t\"%%s: constraint failed\", td->name);\n");
177 OUT("return -1;\n");
178 INDENT(-1);
179 OUT("}\n");
180
181 return 0;
182}
183
Lev Walkin59004fa2004-08-20 13:37:01 +0000184static int
185asn1c_emit_constraint_tables(arg_t *arg, int got_size) {
Lev Walkin84cd58e2004-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;
Lev Walkin59004fa2004-08-20 13:37:01 +0000190 asn1p_constraint_t *ct;
191 int utf8_full_alphabet_check = 0;
192 int max_table_size = 256;
Lev Walkin84cd58e2004-08-19 13:29:46 +0000193 int table[256];
194 int use_table;
195
Lev Walkin59004fa2004-08-20 13:37:01 +0000196 ct = arg->expr->combined_constraints;
Lev Walkin84cd58e2004-08-19 13:29:46 +0000197 if(!ct) return 0;
198
199 etype = _find_terminal_type(arg);
200
201 range = asn1constraint_compute_PER_range(etype, ct, ACT_CT_FROM, 0, 0);
202 if(!range) return 0;
203
204 if(range->not_PER_visible
205 || range->extensible
206 || range->empty_constraint) {
207 asn1constraint_range_free(range);
208 return 0;
209 }
210
211 range_start = range->left.value;
212 range_stop = range->right.value;
213 assert(range->left.type == ARE_VALUE);
214 assert(range->right.type == ARE_VALUE);
215 assert(range_start <= range_stop);
216
217 range_start = 0; /* Force old behavior */
218
219 /*
220 * Check if we need a test table to check the alphabet.
221 */
222 use_table = 1;
Lev Walkin59004fa2004-08-20 13:37:01 +0000223 if(range->el_count == 0) {
224 /*
225 * It's better to have a short if() check
226 * than waste 4k of table space
227 */
228 use_table = 0;
229 }
Lev Walkin84cd58e2004-08-19 13:29:46 +0000230 if((range_stop - range_start) > 255)
231 use_table = 0;
Lev Walkin59004fa2004-08-20 13:37:01 +0000232 if(etype == ASN_STRING_UTF8String) {
233 if(range_stop >= 0x80)
234 use_table = 0;
235 else
236 max_table_size = 128;
237 }
Lev Walkin84cd58e2004-08-19 13:29:46 +0000238
239 if(!ct->_compile_mark)
240 ct->_compile_mark = ++global_compile_mark;
241
242 if(use_table) {
243 int i, n = 0;
244 int untl;
245 memset(table, 0, sizeof(table));
246 for(i = -1; i < range->el_count; i++) {
247 asn1cnst_range_t *r;
248 asn1_integer_t v;
249 if(i == -1) {
250 if(range->el_count) continue;
251 r = range;
252 } else {
253 r = range->elements[i];
254 }
255 for(v = r->left.value; v <= r->right.value; v++) {
256 assert((v - range_start) >= 0);
Lev Walkin59004fa2004-08-20 13:37:01 +0000257 assert((v - range_start) < max_table_size);
Lev Walkin84cd58e2004-08-19 13:29:46 +0000258 table[v - range_start] = ++n;
259 }
260 }
261
Lev Walkin84cd58e2004-08-19 13:29:46 +0000262 untl = (range_stop - range_start) + 1;
263 untl += (untl % 16)?16 - (untl % 16):0;
Lev Walkin59004fa2004-08-20 13:37:01 +0000264 OUT("static int permitted_alphabet_table_%d[%d] = {\n",
265 ct->_compile_mark, max_table_size);
Lev Walkin84cd58e2004-08-19 13:29:46 +0000266 for(n = 0; n < untl; n++) {
267 OUT("%d,", table[n]?1:0);
268 if(!((n+1) % 16)) {
269 int c;
270 if(!n) {
271 OUT("\n");
272 continue;
273 }
274 OUT("\t/* ");
275 for(c = n - 15; c <= n; c++) {
276 if(table[c]) {
277 int a = c + range_start;
278 if(a > 0x20 && a < 0x80)
279 OUT("%c", a);
280 else
281 OUT(".");
282 } else {
283 OUT(" ");
284 }
285 }
286 OUT(" */");
287 OUT("\n");
288 }
289 }
290 OUT("};\n");
291 OUT("\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000292 } else if(etype == ASN_STRING_UTF8String) {
293 /*
294 * UTF8String type is a special case in many respects.
295 */
296 assert(range_stop > 255); /* This one's unobvious */
297 if(got_size) {
298 /*
299 * Size has been already determined.
300 * The UTF8String length checker also checks
301 * for the syntax validity, so we don't have
302 * to repeat this process twice.
303 */
304 ct->_compile_mark = 0; /* Don't generate code */
305 asn1constraint_range_free(range);
306 return 0;
307 } else {
308 utf8_full_alphabet_check = 1;
309 }
310 } else {
311 /*
312 * This permitted alphabet check will be
313 * expressed using conditional statements
314 * instead of table lookups. Table would be
315 * to large or otherwise inappropriate (too sparse?).
316 */
Lev Walkin84cd58e2004-08-19 13:29:46 +0000317 }
318
319 OUT("static int check_permitted_alphabet_%d(const void *sptr) {\n",
320 ct->_compile_mark);
Lev Walkin59004fa2004-08-20 13:37:01 +0000321 INDENT(+1);
322 if(utf8_full_alphabet_check) {
323 OUT("if(UTF8String_length((UTF8String_t *)sptr, td->name, \n");
324 OUT("\tapp_errlog, app_key) == -1)\n");
Lev Walkin775885e2004-08-22 12:47:03 +0000325 OUT("\t\treturn -1; /* Alphabet (sic!) test failed. */\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000326 OUT("\n");
327 } else {
Lev Walkin84cd58e2004-08-19 13:29:46 +0000328 if(use_table) {
329 OUT("int *table = permitted_alphabet_table_%d;\n",
330 ct->_compile_mark);
331 emit_alphabet_check_loop(arg, 0);
332 } else {
333 emit_alphabet_check_loop(arg, range);
334 }
Lev Walkin59004fa2004-08-20 13:37:01 +0000335 }
Lev Walkin775885e2004-08-22 12:47:03 +0000336 OUT("return 0;\n");
Lev Walkin59004fa2004-08-20 13:37:01 +0000337 INDENT(-1);
Lev Walkin84cd58e2004-08-19 13:29:46 +0000338 OUT("}\n");
339 OUT("\n");
340
341 asn1constraint_range_free(range);
342
343 return 0;
344}
345
346static int
347emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range) {
Lev Walkin84cd58e2004-08-19 13:29:46 +0000348 asn1_integer_t natural_stop;
Lev Walkin634a3b82004-08-22 03:30:05 +0000349 asn1p_expr_t *terminal;
Lev Walkin84cd58e2004-08-19 13:29:46 +0000350
Lev Walkin634a3b82004-08-22 03:30:05 +0000351 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->mod, arg->expr);
352 if(terminal) {
353 OUT("/* The underlying type is %s */\n",
354 ASN_EXPR_TYPE2STR(terminal->expr_type));
355 } else {
356 terminal = arg->expr;
357 }
Lev Walkin02b137d2004-08-21 07:34:58 +0000358 OUT("const %s_t *st = sptr;\n",
Lev Walkin634a3b82004-08-22 03:30:05 +0000359 asn1c_type_name(arg, terminal, TNF_SAFE));
Lev Walkin84cd58e2004-08-19 13:29:46 +0000360
Lev Walkin634a3b82004-08-22 03:30:05 +0000361 switch(terminal->expr_type) {
Lev Walkin84cd58e2004-08-19 13:29:46 +0000362 case ASN_STRING_UTF8String:
Lev Walkin02b137d2004-08-21 07:34:58 +0000363 OUT("const uint8_t *ch = st->buf;\n");
364 OUT("const uint8_t *end = ch + st->size;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000365 OUT("\n");
366 OUT("for(; ch < end; ch++) {\n");
367 INDENT(+1);
368 OUT("uint8_t cv = *ch;\n");
Lev Walkin775885e2004-08-22 12:47:03 +0000369 if(!range) OUT("if(cv >= 0x80) return -1;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000370 natural_stop = 0xffffffffUL;
371 break;
372 case ASN_STRING_UniversalString:
Lev Walkin02b137d2004-08-21 07:34:58 +0000373 OUT("const uint32_t *ch = st->buf;\n");
374 OUT("const uint32_t *end = ch + st->size;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000375 OUT("\n");
Lev Walkin775885e2004-08-22 12:47:03 +0000376 OUT("if(st->size % 4) return -1; /* (size%4)! */\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000377 OUT("for(; ch < end; ch++) {\n");
378 INDENT(+1);
Lev Walkin02b137d2004-08-21 07:34:58 +0000379 OUT("uint32_t cv = (((const uint8_t *)ch)[0] << 24)\n");
380 OUT("\t\t| (((const uint8_t *)ch)[1] << 16)\n");
381 OUT("\t\t| (((const uint8_t *)ch)[2] << 8)\n");
382 OUT("\t\t| ((const uint8_t *)ch)[3];\n");
Lev Walkin775885e2004-08-22 12:47:03 +0000383 if(!range) OUT("if(cv > 255) return -1;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000384 natural_stop = 0xffffffffUL;
385 break;
386 case ASN_STRING_BMPString:
Lev Walkin02b137d2004-08-21 07:34:58 +0000387 OUT("const uint16_t *ch = st->buf;\n");
388 OUT("const uint16_t *end = ch + st->size;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000389 OUT("\n");
Lev Walkin775885e2004-08-22 12:47:03 +0000390 OUT("if(st->size % 2) return -1; /* (size%2)! */\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000391 OUT("for(; ch < end; ch++) {\n");
392 INDENT(+1);
Lev Walkin02b137d2004-08-21 07:34:58 +0000393 OUT("uint16_t cv = (((const uint8_t *)ch)[0] << 8)\n");
394 OUT("\t\t| ((const uint8_t *)ch)[1];\n");
Lev Walkin775885e2004-08-22 12:47:03 +0000395 if(!range) OUT("if(cv > 255) return -1;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000396 natural_stop = 0xffff;
397 break;
398 case ASN_BASIC_OCTET_STRING:
399 default:
Lev Walkin02b137d2004-08-21 07:34:58 +0000400 OUT("const uint8_t *ch = st->buf;\n");
401 OUT("const uint8_t *end = ch + st->size;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000402 OUT("\n");
403 OUT("for(; ch < end; ch++) {\n");
404 INDENT(+1);
405 OUT("uint8_t cv = *ch;\n");
406 natural_stop = 0xff;
407 break;
408 }
409
410 if(range) {
411 OUT("if(!(");
412 emit_range_comparison_code(arg, range, "cv", 0, natural_stop);
Lev Walkin775885e2004-08-22 12:47:03 +0000413 OUT(")) return -1;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000414 } else {
Lev Walkin775885e2004-08-22 12:47:03 +0000415 OUT("if(!table[cv]) return -1;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000416 }
417
418 INDENT(-1);
419 OUT("}\n");
420
421 return 0;
422}
423
424static int
425emit_range_comparison_code(arg_t *arg, asn1cnst_range_t *range, const char *varname, asn1_integer_t natural_start, asn1_integer_t natural_stop) {
426 int ignore_left;
427 int ignore_right;
Lev Walkin59004fa2004-08-20 13:37:01 +0000428 int generated_something = 0;
Lev Walkin84cd58e2004-08-19 13:29:46 +0000429 int i;
430
431 for(i = -1; i < range->el_count; i++) {
432 asn1cnst_range_t *r;
433 if(i == -1) {
434 if(range->el_count) continue;
435 r = range;
436 } else {
437 if(i) OUT(" || ");
438 r = range->elements[i];
439 }
440
441 if(r != range) OUT("(");
442
443 ignore_left = (r->left.type == ARE_MIN)
444 || (natural_start != -1
445 && r->left.value <= natural_start);
446 ignore_right = (r->right.type == ARE_MAX)
447 || (natural_stop != -1
448 && r->right.value >= natural_stop);
449 if(ignore_left && ignore_right) {
450 OUT("1 /* Constraint matches natural range of %s */",
451 varname);
452 continue;
453 }
454
455 if(ignore_left) {
456 OUT("%s <= %lld", varname,
457 (long long)r->right.value);
458 } else if(ignore_right) {
459 OUT("%s >= %lld", varname,
460 (long long)r->left.value);
461 } else if(r->left.value == r->right.value) {
462 OUT("%s == %lld", varname,
463 (long long)r->right.value);
464 } else {
465 OUT("%s >= %lld && %s <= %lld",
466 varname,
467 (long long)r->left.value,
468 varname,
469 (long long)r->right.value);
470 }
471 if(r != range) OUT(")");
Lev Walkin59004fa2004-08-20 13:37:01 +0000472 generated_something = 1;
Lev Walkin84cd58e2004-08-19 13:29:46 +0000473 }
474
Lev Walkin59004fa2004-08-20 13:37:01 +0000475 return generated_something;
Lev Walkin84cd58e2004-08-19 13:29:46 +0000476}
477
478static int
479emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype) {
480
481 switch(etype) {
482 case ASN_BASIC_BIT_STRING:
483 OUT("if(st->size > 0) {\n");
484 OUT("\t/* Size in bits */\n");
485 OUT("\tsize = (st->size - 1) - (st->buf[0] & 0x7);\n");
486 OUT("} else {\n");
487 OUT("\tsize = 0;\n");
488 OUT("}\n");
489 break;
490 case ASN_STRING_UniversalString:
491 OUT("size = st->size >> 2;\t/* 4 byte per character */\n");
492 break;
493 case ASN_STRING_BMPString:
494 OUT("size = st->size >> 1;\t/* 2 byte per character */\n");
495 break;
496 case ASN_STRING_UTF8String:
497 OUT("size = UTF8String_length(st, td->name, app_errlog, app_key);\n");
498 OUT("if(size == (size_t)-1) return -1;\n");
499 break;
500 case ASN_CONSTR_SET_OF:
501 case ASN_CONSTR_SEQUENCE_OF:
502 OUT("{ /* Determine the number of elements */\n");
503 INDENT(+1);
Lev Walkin59004fa2004-08-20 13:37:01 +0000504 OUT("const A_%s_OF(void) *list;\n",
Lev Walkin84cd58e2004-08-19 13:29:46 +0000505 etype==ASN_CONSTR_SET_OF?"SET":"SEQUENCE");
Lev Walkin59004fa2004-08-20 13:37:01 +0000506 OUT("(const void *)list = sptr;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000507 OUT("size = list->count;\n");
508 INDENT(-1);
509 OUT("}\n");
510 break;
Lev Walkin59004fa2004-08-20 13:37:01 +0000511 case ASN_BASIC_OCTET_STRING:
512 OUT("size = st->size;\n");
513 break;
Lev Walkin84cd58e2004-08-19 13:29:46 +0000514 default:
Lev Walkin59004fa2004-08-20 13:37:01 +0000515 if(etype & ASN_STRING_MASK) {
Lev Walkin84cd58e2004-08-19 13:29:46 +0000516 OUT("size = st->size;\n");
517 break;
518 } else {
519 const char *type_name = ASN_EXPR_TYPE2STR(etype);
520 if(!type_name) type_name = arg->expr->Identifier;
521 WARNING("SizeConstraint is not defined for %s",
522 type_name);
523 OUT_NOINDENT("#warning SizeConstraint "
524 "is not defined for %s!\n", type_name);
525 OUT("size = st->size;\n");
526 }
527 return -1;
528 }
529
530 return 0;
531}
532
533static int
534emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype) {
535
536 switch(etype) {
537 case ASN_BASIC_INTEGER:
538 case ASN_BASIC_ENUMERATED:
539 if(arg->flags & A1C_USE_NATIVE_INTEGERS) {
Lev Walkin02b137d2004-08-21 07:34:58 +0000540 OUT("value = *(const int *)sptr;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000541 } else {
542 OUT("if(asn1_INTEGER2long(st, &value)) {\n");
543 INDENT(+1);
544 OUT("_ASN_ERRLOG(app_errlog, app_key,\n");
545 OUT("\t\"%%s: value too large\", td->name);\n");
546 OUT("return -1;\n");
547 INDENT(-1);
548 OUT("}\n");
549 }
550 break;
551 case ASN_BASIC_BOOLEAN:
Lev Walkin02b137d2004-08-21 07:34:58 +0000552 OUT("value = (*(const int *)sptr) ? 1 : 0;\n");
Lev Walkin84cd58e2004-08-19 13:29:46 +0000553 break;
554 default:
Lev Walkin02b137d2004-08-21 07:34:58 +0000555 WARNING("%s:%d: Value cannot be determined "
556 "for constraint check for %s",
557 arg->mod->source_file_name,
558 arg->expr->_lineno,
559 arg->expr->Identifier
560 );
561 OUT_NOINDENT(
562 "#error %s:%d: Value of %s cannot be determined\n",
563 arg->mod->source_file_name,
564 arg->expr->_lineno,
565 arg->expr->Identifier
566 );
Lev Walkin84cd58e2004-08-19 13:29:46 +0000567 break;
568 }
569
570 return 0;
571}
572
573static asn1p_expr_type_e
574_find_terminal_type(arg_t *arg) {
575 asn1p_expr_t *expr;
Lev Walkinde6fbe02004-08-22 03:10:52 +0000576 expr = asn1f_find_terminal_type_ex(arg->asn, arg->mod, arg->expr);
Lev Walkin84cd58e2004-08-19 13:29:46 +0000577 if(expr) return expr->expr_type;
578 return A1TC_INVALID;
579}
580