NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / libasn1compiler / asn1c_constraint.c
1 #include "asn1c_internal.h"
2 #include "asn1c_constraint.h"
3 #include "asn1c_misc.h"
4 #include "asn1c_out.h"
5 #include "asn1c_naming.h"
6
7 #include <asn1fix_crange.h>     /* constraint groker from libasn1fix */
8 #include <asn1fix_export.h>     /* other exportables from libasn1fix */
9
10 static int asn1c_emit_constraint_tables(arg_t *arg, int got_size);
11 static int emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range);
12 static int emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_range_t *r_value);
13 static int emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype);
14 static asn1p_expr_type_e _find_terminal_type(arg_t *arg);
15 static abuf *emit_range_comparison_code(asn1cnst_range_t *range,
16                                           const char *varname,
17                                           asn1c_integer_t natural_start,
18                                           asn1c_integer_t natural_stop);
19 static int native_long_sign(arg_t *arg, asn1cnst_range_t *r);   /* -1, 0, 1 */
20
21 static int
22 ulong_optimization(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_range_t *r_size,
23                                                 asn1cnst_range_t *r_value)
24 {
25         return (!r_size && r_value
26                 && (etype == ASN_BASIC_INTEGER
27                 || etype == ASN_BASIC_ENUMERATED)
28                 && native_long_sign(arg, r_value) == 0);
29 }
30
31 int
32 asn1c_emit_constraint_checking_code(arg_t *arg) {
33         asn1cnst_range_t *r_size;
34         asn1cnst_range_t *r_value;
35         asn1p_expr_t *expr = arg->expr;
36         asn1p_expr_type_e etype;
37         asn1p_constraint_t *ct;
38         int alphabet_table_compiled;
39         int produce_st = 0;
40         int ulong_optimize = 0;
41         int value_unsigned = 0;
42         int ret = 0;
43
44         ct = expr->combined_constraints;
45         if(ct == NULL)
46                 return 1;       /* No additional constraints defined */
47
48         etype = _find_terminal_type(arg);
49
50         r_value=asn1constraint_compute_constraint_range(expr->Identifier, etype, ct, ACT_EL_RANGE,0,0,0);
51         r_size =asn1constraint_compute_constraint_range(expr->Identifier, etype, ct, ACT_CT_SIZE, 0,0,0);
52         if(r_value) {
53                 if(r_value->incompatible
54                 || r_value->empty_constraint
55                 || (r_value->left.type == ARE_MIN
56                         && r_value->right.type == ARE_MAX)
57                 || (etype == ASN_BASIC_BOOLEAN
58                         && r_value->left.value == 0
59                         && r_value->right.value == 1)
60                 ) {
61                         asn1constraint_range_free(r_value);
62                         r_value = 0;
63                 }
64         }
65         if(r_size) {
66                 if(r_size->incompatible
67                 || r_size->empty_constraint
68                 || (r_size->left.value == 0     /* or .type == MIN */
69                         && r_size->right.type == ARE_MAX)
70                 ) {
71                         asn1constraint_range_free(r_size);
72                         r_size = 0;
73                 }
74         }
75
76         /*
77          * Do we really need an "*st = sptr" pointer?
78          */
79         switch(etype) {
80         case ASN_BASIC_INTEGER:
81         case ASN_BASIC_ENUMERATED:
82                 if(asn1c_type_fits_long(arg, arg->expr) == FL_NOTFIT)
83                         produce_st = 1;
84                 break;
85         case ASN_BASIC_REAL:
86         if((arg->flags & A1C_USE_WIDE_TYPES)
87            && asn1c_REAL_fits(arg, arg->expr) == RL_NOTFIT)
88             produce_st = 1;
89                 break;
90         case ASN_BASIC_BIT_STRING:
91         case ASN_BASIC_OCTET_STRING:
92                 produce_st = 1;
93                 break;
94         default:
95                 if(etype & ASN_STRING_MASK)
96                         produce_st = 1;
97                 break;
98         }
99         if(produce_st) {
100                 const char *tname = asn1c_type_name(arg, arg->expr, TNF_SAFE);
101                 OUT("const %s_t *st = (const %s_t *)sptr;\n", tname, tname);
102         }
103
104         if(r_size || r_value) {
105                 if(r_size) {
106                         OUT("size_t size;\n");
107                 }
108                 if(r_value)
109                         switch(etype) {
110                         case ASN_BASIC_INTEGER:
111                         case ASN_BASIC_ENUMERATED:
112                                 if(native_long_sign(arg, r_value) >= 0) {
113                                         ulong_optimize = ulong_optimization(arg, etype, r_size, r_value);
114                                         if(!ulong_optimize) {
115                                                 value_unsigned = 1;
116                                                 OUT("unsigned long value;\n");
117                                         }
118                                 } else {
119                                         OUT("long value;\n");
120                                 }
121                                 break;
122                         case ASN_BASIC_REAL:
123                                 OUT("%s value;\n", c_name(arg).type.constrained_c_name);
124                                 break;
125                         case ASN_BASIC_BOOLEAN:
126                                 OUT("BOOLEAN_t value;\n");
127                                 break;
128                         default:
129                                 break;
130                 }
131         }
132
133         OUT("\n");
134
135         /*
136          * Protection against null input.
137          */
138         OUT("if(!sptr) {\n");
139                 INDENT(+1);
140                 OUT("ASN__CTFAIL(app_key, td, sptr,\n");
141                 OUT("\t\"%%s: value not given (%%s:%%d)\",\n");
142                 OUT("\ttd->name, __FILE__, __LINE__);\n");
143                 OUT("return -1;\n");
144                 INDENT(-1);
145         OUT("}\n");
146         OUT("\n");
147
148         if((r_value) && (!ulong_optimize))
149                 emit_value_determination_code(arg, etype, r_value);
150         if(r_size)
151                 emit_size_determination_code(arg, etype);
152
153         INDENT(-1);
154         REDIR(OT_CTABLES);
155         /* Emit FROM() tables */
156         alphabet_table_compiled =
157                 (asn1c_emit_constraint_tables(arg, r_size?1:0) == 1);
158         REDIR(OT_CODE);
159         INDENT(+1);
160
161         /*
162          * Optimization for unsigned longs.
163          */
164         if(ulong_optimize) {
165                 OUT("\n");
166                 OUT("/* Constraint check succeeded */\n");
167                 OUT("return 0;\n");
168                 goto end;
169         }
170
171         /*
172          * Here is an if() {} else {} consrtaint checking code.
173          */
174         int got_something = 0;
175     int value_unused = 0;
176         OUT("\n");
177         OUT("if(");
178         INDENT(+1);
179                 if(r_size) {
180             abuf *ab = emit_range_comparison_code(r_size, "size", 0, -1);
181             if(ab->length)  {
182                 OUT("(%s)", ab->buffer);
183                 got_something++;
184             }
185             abuf_free(ab);
186                 }
187                 if(r_value) {
188                         if(got_something) { OUT("\n"); OUT(" && "); }
189             abuf *ab;
190             if(etype == ASN_BASIC_BOOLEAN)
191                 ab = emit_range_comparison_code(r_value, "value", 0, 1);
192             else
193                 ab = emit_range_comparison_code(r_value, "value",
194                                                 value_unsigned ? 0 : -1, -1);
195             if(ab->length)  {
196                 OUT("(%s)", ab->buffer);
197                 got_something++;
198             } else {
199                 value_unused = 1;
200             }
201             abuf_free(ab);
202                 }
203                 if(alphabet_table_compiled) {
204                         if(got_something) { OUT("\n"); OUT(" && "); }
205                         OUT("!check_permitted_alphabet_%d(%s)",
206                                 arg->expr->_type_unique_index,
207                                 produce_st ? "st" : "sptr");
208             got_something++;
209         }
210                 if(!got_something) {
211                         OUT("1 /* No applicable constraints whatsoever */");
212                         OUT(") {\n");
213                         INDENT(-1);
214                         if(produce_st) {
215                                 INDENTED(OUT("(void)st; /* Unused variable */\n"));
216                         }
217                         if(value_unused) {
218                                 INDENTED(OUT("(void)value; /* Unused variable */\n"));
219                         }
220                         INDENTED(OUT("/* Nothing is here. See below */\n"));
221                         OUT("}\n");
222                         OUT("\n");
223                         ret = 1;
224                         goto end;
225                 }
226         INDENT(-1);
227         OUT(") {\n");
228                 INDENT(+1);
229                 switch(etype) {
230                 case ASN_CONSTR_SEQUENCE_OF:
231                 case ASN_CONSTR_SET_OF:
232                         OUT("/* Perform validation of the inner elements */\n");
233                         OUT("return td->encoding_constraints.general_constraints(td, sptr, ctfailcb, app_key);\n");
234                         break;
235                 default:
236                         OUT("/* Constraint check succeeded */\n");
237                         OUT("return 0;\n");
238                 }
239                 INDENT(-1);
240         OUT("} else {\n");
241                 INDENT(+1);
242                         OUT("ASN__CTFAIL(app_key, td, sptr,\n");
243                         OUT("\t\"%%s: constraint failed (%%s:%%d)\",\n");
244                         OUT("\ttd->name, __FILE__, __LINE__);\n");
245                         OUT("return -1;\n");
246                 INDENT(-1);
247         OUT("}\n");
248
249 end:
250         if (r_value) asn1constraint_range_free(r_value);
251         if (r_size) asn1constraint_range_free(r_size);
252
253         return ret;
254 }
255
256 static int
257 asn1c_emit_constraint_tables(arg_t *arg, int got_size) {
258         asn1c_integer_t range_start;
259         asn1c_integer_t range_stop;
260         asn1p_expr_type_e etype;
261         asn1cnst_range_t *range;
262         asn1p_constraint_t *ct;
263         int utf8_full_alphabet_check = 0;
264         int max_table_size = 256;
265         int table[256];
266         int use_table;
267
268         ct = arg->expr->combined_constraints;
269         if(!ct) return 0;
270
271         etype = _find_terminal_type(arg);
272
273         range = asn1constraint_compute_constraint_range(arg->expr->Identifier, etype, ct, ACT_CT_FROM, 0,0,0);
274         if(!range) return 0;
275
276         if(range->incompatible
277         || range->empty_constraint) {
278                 asn1constraint_range_free(range);
279                 return 0;
280         }
281
282         if(range->left.type == ARE_MIN
283         && range->right.type == ARE_MAX) {
284                 /*
285                  * The permitted alphabet constraint checker code guarantees
286                  * that either both bounds (left/right) are present, or
287                  * they're absent simultaneously. Thus, this assertion
288                  * legitimately holds true.
289                  */
290                 assert(range->el_count == 0);
291                 /* The full range is specified. Ignore it. */
292                 asn1constraint_range_free(range);
293                 return 0;
294         }
295
296         range_start = range->left.value;
297         range_stop = range->right.value;
298         assert(range->left.type == ARE_VALUE);
299         assert(range->right.type == ARE_VALUE);
300         assert(range_start <= range_stop);
301
302         range_start = 0;        /* Force old behavior */
303
304         /*
305          * Check if we need a test table to check the alphabet.
306          */
307         use_table = 1;
308         if(range->el_count == 0) {
309                 /*
310                  * It's better to have a short if() check
311                  * than waste 1k of table space
312                  */
313                 use_table = 0;
314         }
315         if((range_stop - range_start) > 255)
316                 use_table = 0;
317         if(etype == ASN_STRING_UTF8String) {
318                 if(range_stop >= 0x80)
319                         use_table = 0;
320                 else
321                         max_table_size = 128;
322         }
323
324         if(use_table) {
325                 int cardinal = 0;
326                 int i, n = 0;
327                 int untl;
328                 memset(table, 0, sizeof(table));
329                 for(i = -1; i < range->el_count; i++) {
330                         asn1cnst_range_t *r;
331                         asn1c_integer_t v;
332                         if(i == -1) {
333                                 if(range->el_count) continue;
334                                 r = range;
335                         } else {
336                                 r = range->elements[i];
337                         }
338                         for(v = r->left.value; v <= r->right.value; v++) {
339                                 assert((v - range_start) >= 0);
340                                 assert((v - range_start) < max_table_size);
341                                 table[v - range_start] = ++n;
342                         }
343                 }
344
345                 untl = (range_stop - range_start) + 1;
346                 untl += (untl % 16)?16 - (untl % 16):0;
347                 OUT("static const int permitted_alphabet_table_%d[%d] = {\n",
348                         arg->expr->_type_unique_index, max_table_size);
349                 for(n = 0; n < untl; n++) {
350                         cardinal += table[n] ? 1 : 0;
351                         OUT("%2d,", table[n]);
352                         if(!((n+1) % 16)) {
353                                 int c;
354                                 if(!n || (n-15) + range_start >= 0x80) {
355                                         OUT("\n");
356                                         continue;
357                                 }
358                                 OUT("\t/* ");
359                                 for(c = n - 15; c <= n; c++) {
360                                         if(table[c]) {
361                                                 int a = c + range_start;
362                                                 if(a > 0x20 && a < 0x80)
363                                                         OUT("%c", a);
364                                                 else
365                                                         OUT(".");
366                                         } else {
367                                                 OUT(" ");
368                                         }
369                                 }
370                                 OUT(" */");
371                                 OUT("\n");
372                         }
373                 }
374                 OUT("};\n");
375
376                 if((arg->flags & A1C_GEN_PER)
377                 && (etype & ASN_STRING_KM_MASK)) {
378                     int c;
379                     OUT("static const int permitted_alphabet_code2value_%d[%d] = {\n",
380                         arg->expr->_type_unique_index, cardinal);
381                     for(n = c = 0; c < max_table_size; c++) {
382                         if(table[c]) {
383                                 OUT("%d,", c);
384                                 if(!((++n) % 16)) OUT("\n");
385                         }
386                     }
387                     OUT("};\n");
388                     OUT("\n");
389                     DEBUG("code2value map gen for %s", arg->expr->Identifier);
390                     arg->expr->_mark |= TM_PERFROMCT;
391                 }
392
393                 OUT("\n");
394         } else if(etype == ASN_STRING_UTF8String) {
395                 /*
396                  * UTF8String type is a special case in many respects.
397                  */
398                 if(got_size) {
399                         /*
400                          * Size has been already determined.
401                          * The UTF8String length checker also checks
402                          * for the syntax validity, so we don't have
403                          * to repeat this process twice.
404                          */
405                         asn1constraint_range_free(range);
406                         return 0;
407                 } else {
408                         utf8_full_alphabet_check = 1;
409                 }
410         } else {
411                 /*
412                  * This permitted alphabet check will be
413                  * expressed using conditional statements
414                  * instead of table lookups. Table would be
415                  * to large or otherwise inappropriate (too sparse?).
416                  */
417         }
418
419         OUT("static int check_permitted_alphabet_%d(const void *sptr) {\n",
420                         arg->expr->_type_unique_index);
421         INDENT(+1);
422         if(utf8_full_alphabet_check) {
423                 OUT("if(UTF8String_length((const UTF8String_t *)sptr) < 0)\n");
424                 OUT("\treturn -1; /* Alphabet (sic!) test failed. */\n");
425                 OUT("\n");
426         } else {
427                 if(use_table) {
428                         OUT("const int *table = permitted_alphabet_table_%d;\n",
429                                 arg->expr->_type_unique_index);
430                         emit_alphabet_check_loop(arg, 0);
431                 } else {
432                         emit_alphabet_check_loop(arg, range);
433                 }
434         }
435         OUT("return 0;\n");
436         INDENT(-1);
437         OUT("}\n");
438         OUT("\n");
439
440         asn1constraint_range_free(range);
441
442         return 1;
443 }
444
445 static int
446 emit_alphabet_check_loop(arg_t *arg, asn1cnst_range_t *range) {
447         asn1c_integer_t natural_stop;
448         asn1p_expr_t *terminal;
449         const char *tname;
450
451         terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, arg->expr);
452         if(terminal) {
453                 OUT("/* The underlying type is %s */\n",
454                         ASN_EXPR_TYPE2STR(terminal->expr_type));
455         } else {
456                 terminal = arg->expr;
457         }
458         tname = asn1c_type_name(arg, terminal, TNF_SAFE);
459         OUT("const %s_t *st = (const %s_t *)sptr;\n", tname, tname);
460
461         switch(terminal->expr_type) {
462         case ASN_STRING_UTF8String:
463                 OUT("const uint8_t *ch = st->buf;\n");
464                 OUT("const uint8_t *end = ch + st->size;\n");
465                 OUT("\n");
466                 OUT("for(; ch < end; ch++) {\n");
467                         INDENT(+1);
468                         OUT("uint8_t cv = *ch;\n");
469                         if(!range) OUT("if(cv >= 0x80) return -1;\n");
470                 natural_stop = 0xffffffffUL;
471                 break;
472         case ASN_STRING_UniversalString:
473                 OUT("const uint8_t *ch = st->buf;\n");
474                 OUT("const uint8_t *end = ch + st->size;\n");
475                 OUT("\n");
476                 OUT("if(st->size %% 4) return -1; /* (size%%4)! */\n");
477                 OUT("for(; ch < end; ch += 4) {\n");
478                         INDENT(+1);
479                         OUT("uint32_t cv = (ch[0] << 24)\n");
480                         OUT("\t\t| (ch[1] << 16)\n");
481                         OUT("\t\t| (ch[2] << 8)\n");
482                         OUT("\t\t|  ch[3];\n");
483                         if(!range) OUT("if(cv > 255) return -1;\n");
484                 natural_stop = 0xffffffffUL;
485                 break;
486         case ASN_STRING_BMPString:
487                 OUT("const uint8_t *ch = st->buf;\n");
488                 OUT("const uint8_t *end = ch + st->size;\n");
489                 OUT("\n");
490                 OUT("if(st->size %% 2) return -1; /* (size%%2)! */\n");
491                 OUT("for(; ch < end; ch += 2) {\n");
492                         INDENT(+1);
493                         OUT("uint16_t cv = (ch[0] << 8)\n");
494                         OUT("\t\t| ch[1];\n");
495                         if(!range) OUT("if(cv > 255) return -1;\n");
496                 natural_stop = 0xffff;
497                 break;
498         case ASN_BASIC_OCTET_STRING:
499         default:
500                 OUT("const uint8_t *ch = st->buf;\n");
501                 OUT("const uint8_t *end = ch + st->size;\n");
502                 OUT("\n");
503                 OUT("for(; ch < end; ch++) {\n");
504                         INDENT(+1);
505                         OUT("uint8_t cv = *ch;\n");
506                 natural_stop = 0xff;
507                 break;
508         }
509
510         if(range) {
511         abuf *ab = emit_range_comparison_code(range, "cv", 0, natural_stop);
512         if(ab->length) {
513             OUT("if(!(%s)) return -1;\n", ab->buffer);
514         } else {
515             OUT("(void)cv; /* Unused variable */\n");
516         }
517         } else {
518                 OUT("if(!table[cv]) return -1;\n");
519         }
520
521         INDENT(-1);
522         OUT("}\n");
523
524         return 0;
525 }
526
527 static void
528 abuf_oint(abuf *ab, asn1c_integer_t v) {
529     if(v == (-2147483647L - 1)) {
530         abuf_printf(ab, "(-2147483647L - 1)");
531     } else {
532         abuf_printf(ab, "%s", asn1p_itoa(v));
533     }
534 }
535
536 static abuf *
537 emit_range_comparison_code(asn1cnst_range_t *range, const char *varname,
538                            asn1c_integer_t natural_start,
539                            asn1c_integer_t natural_stop) {
540     abuf *ab = abuf_new();
541
542     if(range->el_count == 0) {
543         int ignore_left =
544             (range->left.type == ARE_MIN)
545             || (natural_start != -1 && range->left.value <= natural_start);
546         int ignore_right =
547             (range->right.type == ARE_MAX)
548             || (natural_stop != -1 && range->right.value >= natural_stop);
549
550         if(ignore_left && ignore_right) {
551             /* Empty constraint comparison */
552         } else if(ignore_left) {
553             abuf_printf(ab, "%s <= ", varname);
554             abuf_oint(ab, range->right.value);
555         } else if(ignore_right) {
556             abuf_printf(ab, "%s >= ", varname);
557             abuf_oint(ab, range->left.value);
558         } else if(range->left.value == range->right.value) {
559             abuf_printf(ab, "%s == ", varname);
560             abuf_oint(ab, range->right.value);
561         } else {
562             abuf_printf(ab, "%s >= ", varname);
563             abuf_oint(ab, range->left.value);
564             abuf_printf(ab, " && ");
565             abuf_printf(ab, "%s <= ", varname);
566             abuf_oint(ab, range->right.value);
567         }
568     } else {
569         for(int i = 0; i < range->el_count; i++) {
570             asn1cnst_range_t *r = range->elements[i];
571
572             abuf *rec = emit_range_comparison_code(r, varname, natural_start,
573                                                    natural_stop);
574             if(rec->length) {
575                 if(ab->length) {
576                     abuf_str(ab, " || ");
577                 }
578                 abuf_str(ab, "(");
579                 abuf_buf(ab, rec);
580                 abuf_str(ab, ")");
581             } else {
582                 /* Ignore this part */
583             }
584             abuf_free(rec);
585         }
586     }
587
588     return ab;
589 }
590
591 static int
592 emit_size_determination_code(arg_t *arg, asn1p_expr_type_e etype) {
593
594         switch(etype) {
595         case ASN_BASIC_BIT_STRING:
596                 OUT("if(st->size > 0) {\n");
597                 OUT("\t/* Size in bits */\n");
598                 OUT("\tsize = 8 * st->size - (st->bits_unused & 0x07);\n");
599                 OUT("} else {\n");
600                 OUT("\tsize = 0;\n");
601                 OUT("}\n");
602                 break;
603         case ASN_STRING_UniversalString:
604                 OUT("size = st->size >> 2;\t/* 4 byte per character */\n");
605                 break;
606         case ASN_STRING_BMPString:
607                 OUT("size = st->size >> 1;\t/* 2 byte per character */\n");
608                 break;
609         case ASN_STRING_UTF8String:
610                 OUT("size = UTF8String_length(st);\n");
611                 OUT("if((ssize_t)size < 0) {\n");
612                 OUT("\tASN__CTFAIL(app_key, td, sptr,\n");
613                 OUT("\t\t\"%%s: UTF-8: broken encoding (%%s:%%d)\",\n");
614                 OUT("\t\ttd->name, __FILE__, __LINE__);\n");
615                 OUT("\treturn -1;\n");
616                 OUT("}\n");
617                 break;
618         case ASN_CONSTR_SET_OF:
619         case ASN_CONSTR_SEQUENCE_OF:
620                 OUT("/* Determine the number of elements */\n");
621                 OUT("size = _A_C%s_FROM_VOID(sptr)->count;\n",
622                         etype==ASN_CONSTR_SET_OF?"SET":"SEQUENCE");
623                 break;
624         case ASN_BASIC_OCTET_STRING:
625                 OUT("size = st->size;\n");
626                 break;
627         default:
628                 if(etype & ASN_STRING_MASK) {
629                         OUT("size = st->size;\n");
630                         break;
631                 } else {
632                         const char *type_name = ASN_EXPR_TYPE2STR(etype);
633                         if(!type_name) type_name = arg->expr->Identifier;
634                         WARNING("SizeConstraint is not defined for %s",
635                                 type_name);
636                         OUT_NOINDENT("#warning SizeConstraint "
637                                 "is not defined for %s!\n", type_name);
638                         OUT("size = st->size;\n");
639                 }
640                 return -1;
641         }
642
643         return 0;
644 }
645
646 static int
647 emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_range_t *r_value) {
648
649         switch(etype) {
650         case ASN_BASIC_INTEGER:
651         case ASN_BASIC_ENUMERATED:
652                 if(asn1c_type_fits_long(arg, arg->expr) == FL_FITS_UNSIGN) {
653                         OUT("value = *(const unsigned long *)sptr;\n");
654                 } else if(asn1c_type_fits_long(arg, arg->expr) != FL_NOTFIT) {
655                         OUT("value = *(const long *)sptr;\n");
656                 } else {
657                         /*
658                          * In some cases we can explore our knowledge of
659                          * underlying INTEGER_t->buf format.
660                          */
661                         if(r_value->el_count == 0
662                         && (
663                                 /* Speed-up common case: (0..MAX) */
664                                 (r_value->left.type == ARE_VALUE
665                                 && r_value->left.value == 0
666                                 && r_value->right.type == ARE_MAX)
667                             ||
668                                 /* Speed-up common case: (MIN..-1) */
669                                 (r_value->left.type == ARE_MIN
670                                 && r_value->right.type == ARE_VALUE
671                                 && r_value->right.value == -1)
672                         )) {
673                                 OUT("/* Check if the sign bit is present */\n");
674                                 OUT("value = st->buf ? ((st->buf[0] & 0x80) ? -1 : 1) : 0;\n");
675                                 break;
676                         }
677
678                         if(native_long_sign(arg, r_value) >= 0) {
679                                 /* Special case for treating unsigned longs */
680                                 OUT("if(asn_INTEGER2ulong(st, &value)) {\n");
681                                 INDENT(+1);
682                                 OUT("ASN__CTFAIL(app_key, td, sptr,\n");
683                                 OUT("\t\"%%s: value too large (%%s:%%d)\",\n");
684                                 OUT("\ttd->name, __FILE__, __LINE__);\n");
685                                 OUT("return -1;\n");
686                                 INDENT(-1);
687                                 OUT("}\n");
688                         } else {
689                                 OUT("if(asn_INTEGER2long(st, &value)) {\n");
690                                 INDENT(+1);
691                                 OUT("ASN__CTFAIL(app_key, td, sptr,\n");
692                                 OUT("\t\"%%s: value too large (%%s:%%d)\",\n");
693                                 OUT("\ttd->name, __FILE__, __LINE__);\n");
694                                 OUT("return -1;\n");
695                                 INDENT(-1);
696                                 OUT("}\n");
697                         }
698                 }
699                 break;
700         case ASN_BASIC_REAL:
701                 if(arg->flags & A1C_USE_WIDE_TYPES) {
702                         OUT("if(asn_REAL2double(st, &value)) {\n");
703                                 INDENT(+1);
704                                 OUT("ASN__CTFAIL(app_key, td, sptr,\n");
705                                 OUT("\t\"%%s: value too large (%%s:%%d)\",\n");
706                                 OUT("\ttd->name, __FILE__, __LINE__);\n");
707                                 OUT("return -1;\n");
708                                 INDENT(-1);
709                         OUT("}\n");
710                 } else {
711                         OUT("value = *(const %s *)sptr;\n", c_name(arg).type.c_name);
712                 }
713                 break;
714         case ASN_BASIC_BOOLEAN:
715                 OUT("value = (*(const long *)sptr) ? 1 : 0;\n");
716                 break;
717         default:
718                 WARNING("%s:%d: Value cannot be determined "
719                         "for constraint check for %s",
720                         arg->expr->module->source_file_name,
721                         arg->expr->_lineno,
722                         arg->expr->Identifier
723                 );
724                 OUT_NOINDENT(
725                         "#error %s:%d: Value of %s cannot be determined\n",
726                         arg->expr->module->source_file_name,
727                         arg->expr->_lineno,
728                         arg->expr->Identifier
729                 );
730                 break;
731         }
732
733         return 0;
734 }
735
736 static asn1p_expr_type_e
737 _find_terminal_type(arg_t *arg) {
738         asn1p_expr_t *expr;
739         expr = asn1f_find_terminal_type_ex(arg->asn, arg->ns, arg->expr);
740         if(expr) return expr->expr_type;
741         return A1TC_INVALID;
742 }
743
744 static int
745 native_long_sign(arg_t *arg, asn1cnst_range_t *r) {
746     if(!(arg->flags & A1C_USE_WIDE_TYPES) && r->left.type == ARE_VALUE
747        && r->left.value >= 0 && r->left.value <= 2147483647
748         && r->right.type == ARE_MAX) {
749         return 1;
750     }
751         if(r->left.type == ARE_VALUE
752         && r->left.value >= 0
753         && r->right.type == ARE_VALUE
754         && r->right.value > 2147483647
755         && r->right.value <= (asn1c_integer_t)(4294967295UL)) {
756                 if(r->el_count == 0
757                 && r->left.value == 0
758                 && r->right.value == 4294967295UL)
759                         return 0;
760                 else
761                         return 1;
762         } else {
763                 return -1;
764         }
765 }