blob: 8cfafc0e09231d587e60ff1bb4f8080a21656ebf [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#include "asn1c_internal.h"
Lev Walkin59004fa2004-08-20 13:37:01 +00002#include "asn1c_misc.h"
3
Lev Walkin082cadc2005-08-14 02:18:27 +00004#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
5#include <asn1fix_export.h> /* other exportable stuff from libasn1fix */
Lev Walkinf15320b2004-06-03 03:38:44 +00006
Lev Walkinf15320b2004-06-03 03:38:44 +00007/*
Ozbolt Menegatti11a3d682016-10-24 15:22:57 +02008 * Checks that the given string is not a reserved C/C++ keyword [1],[2].
9 * _* keywords not included, since asn1 identifiers cannot begin with hyphen [3]
10 * [1] ISO/IEC 9899:2011 (C11), 6.4.1
11 * [2] ISO/IEC 14882:2014 (C++14), 2.12
12 * [3] ISO/IEC 8824-1:2003 (asn1) 11.3
Lev Walkin801fabc2005-01-28 12:18:50 +000013 */
14static char *res_kwd[] = {
Ozbolt Menegatti11a3d682016-10-24 15:22:57 +020015 /* C */
16 "auto", "break", "case", "char", "const", "continue", "default", "do",
17 "double", "else", "enum", "extern", "float", "for", "goto", "if",
18 "inline", "int", "long", "register", "restrict", "return", "short",
19 "signed", "sizeof", "static", "struct", "switch", "typedef", "union",
20 "unsigned", "void", "volatile", "while",
21 /* C++ */
22 "alignas", "alignof", "and", "and_eq", "asm", "bitand", "bitor", "bool",
23 "catch", "char16_t", "char32_t", "class", "compl", "const_cast",
24 "constexpr", "decltype", "delete", "delete", "dynamic_cast",
25 "explicit", "export", "false", "friend", "mutable", "namespace", "new",
26 "noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq",
27 "private", "protected", "public", "reinterpret_cast", "static_assert",
28 "static_cast", "template", "this", "thread_local", "throw", "true", "try",
29 "typeid", "typename", "using", "virtual", "wchar_t", "xor", "xor_eq"
Lev Walkin3fe2e122005-03-03 21:29:27 +000030};
Lev Walkin801fabc2005-01-28 12:18:50 +000031static int
32reserved_keyword(const char *str) {
Lev Walkinc46b7cb2006-08-18 02:27:55 +000033 size_t i;
Lev Walkin801fabc2005-01-28 12:18:50 +000034 for(i = 0 ; i < sizeof(res_kwd)/sizeof(res_kwd[0]); i++) {
35 if(strcmp(str, res_kwd[i]) == 0)
36 return 1;
37 }
38 return 0;
39}
40
41/*
Lev Walkinf15320b2004-06-03 03:38:44 +000042 * Construct identifier from multiple parts.
43 * Convert unsafe characters to underscores.
44 */
Lev Walkinb46156d2017-09-05 02:53:05 -070045const char *
Lev Walkina00d6b32006-03-21 03:40:38 +000046asn1c_make_identifier(enum ami_flags_e flags, asn1p_expr_t *expr, ...) {
Lev Walkinf15320b2004-06-03 03:38:44 +000047 static char *storage;
48 static int storage_size;
49 int nodelimiter = 0;
50 va_list ap;
51 char *str;
Lev Walkin801fabc2005-01-28 12:18:50 +000052 char *nextstr;
Lev Walkina00d6b32006-03-21 03:40:38 +000053 char *first = 0;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080054 ssize_t size = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000055 char *p;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080056 char *prefix = NULL;
57 char *sptr[4], **psptr = &sptr[0];
58 int sptr_cnt = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +000059
Lev Walkina00d6b32006-03-21 03:40:38 +000060 if(expr) {
61 /*
62 * Estimate the necessary storage size
63 */
64 if(expr->Identifier == NULL)
65 return "Member";
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080066 /*
67 * Add MODULE name to resolve clash
68 */
69 if(expr->_mark & TM_NAMECLASH) {
70 size += strlen(expr->module->ModuleName) + 2;
71 sptr[sptr_cnt++] = expr->module->ModuleName;
72 }
73 sptr[sptr_cnt++] = expr->Identifier;
74
75 size += strlen(expr->Identifier);
Lev Walkina00d6b32006-03-21 03:40:38 +000076 if(expr->spec_index != -1) {
77 static char buf[32];
Lev Walkina00d6b32006-03-21 03:40:38 +000078 size += 1 + snprintf(buf, sizeof buf, "%dP%d",
79 expr->_lineno, expr->spec_index);
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080080 sptr[sptr_cnt++] = (char *)&buf;
Lev Walkina00d6b32006-03-21 03:40:38 +000081 }
82 } else {
83 size = -1;
84 }
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080085 sptr[sptr_cnt++] = (char *)0;
Lev Walkinf15320b2004-06-03 03:38:44 +000086
Lev Walkina00d6b32006-03-21 03:40:38 +000087 va_start(ap, expr);
Lev Walkinf15320b2004-06-03 03:38:44 +000088 while((str = va_arg(ap, char *)))
89 size += 1 + strlen(str);
90 va_end(ap);
Lev Walkina00d6b32006-03-21 03:40:38 +000091 if(size == -1) return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +000092
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080093 if(prefix)
94 size += 1 + strlen(prefix);
Lev Walkinf15320b2004-06-03 03:38:44 +000095 /*
Lev Walkinf4cbbe72017-06-27 08:19:11 -070096 * Make sure we have the required amount of storage.
Lev Walkinf15320b2004-06-03 03:38:44 +000097 */
98 if(storage_size <= size) {
Lev Walkinf4cbbe72017-06-27 08:19:11 -070099 char *tmp = malloc(size + 1);
100 if(tmp) {
101 free(storage);
102 storage = tmp;
103 storage_size = size + 1;
104 } else {
105 return NULL;
106 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000107 }
108
109 /*
110 * Fill-in the storage.
111 */
Lev Walkina00d6b32006-03-21 03:40:38 +0000112 va_start(ap, expr);
Lev Walkinf15320b2004-06-03 03:38:44 +0000113 p = storage;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800114 if(prefix) {
115 strcpy(storage, prefix);
116 p += strlen(prefix);
117 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000118 nextstr = "";
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800119 for(str = 0; str || nextstr; str = nextstr) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000120 int subst_made = 0;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800121 nextstr = *(psptr) ? *(psptr++) : va_arg(ap, char *);
Lev Walkina00d6b32006-03-21 03:40:38 +0000122
123 if(str == 0) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800124 str = first = nextstr;
125 nextstr = *(psptr) ? *(psptr++) : va_arg(ap, char *);
126 if (!first) continue;
Lev Walkina00d6b32006-03-21 03:40:38 +0000127 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000128
129 if(str[0] == ' ' && str[1] == '\0') {
130 *p++ = ' ';
131 nodelimiter = 1; /* No delimiter */
132 continue;
133 }
134
Lev Walkin22b5ed42006-09-13 02:51:20 +0000135 if(str != first && !nodelimiter && !(flags & AMI_NODELIMITER))
Lev Walkinf15320b2004-06-03 03:38:44 +0000136 *p++ = '_'; /* Delimiter between tokens */
137 nodelimiter = 0;
138
Lev Walkin801fabc2005-01-28 12:18:50 +0000139 /*
140 * If it is a single argument, check that it does not clash
141 * with C/C++ language keywords.
142 */
143 if((flags & AMI_CHECK_RESERVED)
Lev Walkina00d6b32006-03-21 03:40:38 +0000144 && str == first && !nextstr && reserved_keyword(str)) {
Lev Walkin801fabc2005-01-28 12:18:50 +0000145 *p++ = toupper(*str++);
146 /* Fall through */
147 }
148
Lev Walkinf15320b2004-06-03 03:38:44 +0000149 for(; *str; str++) {
150 if(isalnum(*str)) {
151 *p++ = *str;
152 subst_made = 0;
153 } else if(!subst_made++) {
Lev Walkin801fabc2005-01-28 12:18:50 +0000154 if((flags & AMI_MASK_ONLY_SPACES)
155 && !isspace(*str)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000156 *p ++ = *str;
157 } else {
158 *p++ = '_';
159 }
160 }
161 }
162 }
163 va_end(ap);
164 *p = '\0';
165
166 assert((p - storage) <= storage_size);
167
168 return storage;
169}
170
Lev Walkincf3f6eb2017-08-23 04:34:15 -0700171const char *
Lev Walkinf15320b2004-06-03 03:38:44 +0000172asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) {
Lev Walkina00d6b32006-03-21 03:40:38 +0000173 asn1p_expr_t *exprid = 0;
Lev Walkin5a8219a2004-09-08 00:28:57 +0000174 asn1p_expr_t *top_parent;
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800175 asn1p_expr_t *terminal = 0;
Lev Walkin22b5ed42006-09-13 02:51:20 +0000176 int stdname = 0;
Lev Walkincf3f6eb2017-08-23 04:34:15 -0700177 const char *typename;
Lev Walkinf15320b2004-06-03 03:38:44 +0000178
Lev Walkin5a8219a2004-09-08 00:28:57 +0000179 /* Rewind to the topmost parent expression */
180 if((top_parent = expr->parent_expr))
181 while(top_parent->parent_expr)
182 top_parent = top_parent->parent_expr;
183
Lev Walkin725883b2006-10-09 12:07:58 +0000184 if(0) DEBUG("asn1c_type_name(%s: 0x%x)",
185 expr->Identifier, expr->expr_type);
Lev Walkinc2a75092006-03-14 11:52:12 +0000186
Lev Walkinf15320b2004-06-03 03:38:44 +0000187 switch(expr->expr_type) {
188 case A1TC_REFERENCE:
189 typename = expr->reference->components[
190 expr->reference->comp_count-1].name;
191 if(typename[0] == '&') {
192 arg_t tmp = *arg;
193
194 /*
195 * This is a reference to a type defined in a class.
196 * Resolve it and use instead.
197 */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700198 tmp.expr = WITH_MODULE_NAMESPACE(
199 arg->expr->module, expr_ns,
200 asn1f_class_access_ex(arg->asn, arg->expr->module, expr_ns,
201 arg->expr, expr->rhs_pspecs,
202 expr->reference));
203 if(!tmp.expr) return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000204
Lev Walkinf15320b2004-06-03 03:38:44 +0000205 return asn1c_type_name(&tmp, tmp.expr, _format);
Lev Walkin5a8219a2004-09-08 00:28:57 +0000206 }
207
Lev Walkinc0e03b92017-08-22 01:48:23 -0700208 terminal = WITH_MODULE_NAMESPACE(
209 expr->module, expr_ns,
Bi-Ruei, Chiu3ed43b22017-10-06 18:46:25 +0800210 (expr->meta_type == AMT_TYPEREF) ?
211 asn1f_lookup_symbol_ex(arg->asn, expr_ns, expr, expr->reference) :
212 asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
Lev Walkina00d6b32006-03-21 03:40:38 +0000213
Lev Walkinc0e03b92017-08-22 01:48:23 -0700214 if(_format == TNF_RSAFE) {
Lev Walkinc8285712005-03-04 22:18:20 +0000215 if(terminal && terminal->expr_type & ASN_CONSTR_MASK) {
216 typename = terminal->Identifier;
217 }
218 }
219
Lev Walkinb5450702017-10-04 02:52:57 -0700220 if(_format == TNF_CTYPE || _format == TNF_CONSTYPE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000221 /*
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000222 * If the component references the type itself,
Lev Walkinc8285712005-03-04 22:18:20 +0000223 * switch to a recursion-safe type naming
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000224 * ("struct foo" instead of "foo_t").
Lev Walkinf15320b2004-06-03 03:38:44 +0000225 */
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000226 if(terminal && terminal == top_parent) {
227 _format = TNF_RSAFE;
Lev Walkin5a8219a2004-09-08 00:28:57 +0000228 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000229 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000230
Bi-Ruei, Chiu94f0b642017-06-29 01:34:23 +0800231 if(_format != TNF_RSAFE && terminal && ((terminal->spec_index != -1) || (terminal->_mark & TM_NAMECLASH))) {
Lev Walkina00d6b32006-03-21 03:40:38 +0000232 exprid = terminal;
233 typename = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000234 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000235
Lev Walkinf15320b2004-06-03 03:38:44 +0000236 break;
237 case ASN_BASIC_INTEGER:
238 case ASN_BASIC_ENUMERATED:
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000239 case ASN_BASIC_REAL:
Lev Walkin43292722017-10-05 00:33:32 -0700240 if((expr->expr_type == ASN_BASIC_REAL
241 && (_format == TNF_CONSTYPE || !(arg->flags & A1C_USE_WIDE_TYPES)
242 || asn1c_REAL_fits(arg, expr) != RL_NOTFIT))
243 || asn1c_type_fits_long(arg, expr)) {
244 switch(_format) {
Lev Walkinb5450702017-10-04 02:52:57 -0700245 case TNF_CONSTYPE:
246 if(expr->expr_type == ASN_BASIC_REAL) {
247 return "double";
248 } else if(asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
249 return "unsigned long";
250 } else {
251 return "long";
252 }
253 case TNF_CTYPE:
254 case TNF_RSAFE:
255 if(expr->expr_type == ASN_BASIC_REAL) {
256 asn1cnst_range_t *range = asn1constraint_compute_OER_range(
257 expr->Identifier, ASN_BASIC_REAL,
258 expr->combined_constraints, ACT_EL_RANGE, 0, 0, 0);
259 if(range->narrowing == NARROW_FLOAT32) {
260 asn1constraint_range_free(range);
261 return "float";
262 } else {
263 asn1constraint_range_free(range);
264 return "double";
265 }
266 } else if(asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN) {
267 return "unsigned long";
268 } else {
269 return "long";
270 }
271 default:
Lev Walkin22b5ed42006-09-13 02:51:20 +0000272 typename = 0;
273 switch(expr->expr_type) {
274 case ASN_BASIC_INTEGER:
275 typename = "NativeInteger"; break;
276 case ASN_BASIC_ENUMERATED:
277 typename = "NativeEnumerated"; break;
278 case ASN_BASIC_REAL:
279 typename = "NativeReal"; break;
280 default:
281 break;
282 }
283 break;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000284 }
Lev Walkin22b5ed42006-09-13 02:51:20 +0000285 if(typename) {
286 if(_format != TNF_INCLUDE)
287 return typename;
288 stdname = 1;
289 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000290 }
291 }
292 /* Fall through */
293 default:
Lev Walkin0e22b982004-08-25 02:03:26 +0000294 if(expr->expr_type
295 & (ASN_CONSTR_MASK | ASN_BASIC_MASK | ASN_STRING_MASK)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000296 if(_format == TNF_RSAFE)
297 _format = TNF_CTYPE;
Lev Walkin22b5ed42006-09-13 02:51:20 +0000298 stdname = 1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000299 typename = ASN_EXPR_TYPE2STR(expr->expr_type);
300 } else {
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000301 _format = TNF_RSAFE;
Lev Walkinf15320b2004-06-03 03:38:44 +0000302 typename = expr->Identifier;
303 }
304 }
305
306 switch(_format) {
307 case TNF_UNMODIFIED:
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800308 return asn1c_make_identifier(AMI_MASK_ONLY_SPACES | AMI_NODELIMITER,
309 0, MODULE_NAME_OF(exprid), exprid ? exprid->Identifier : typename, (char*)0);
Lev Walkin22b5ed42006-09-13 02:51:20 +0000310 case TNF_INCLUDE:
311 return asn1c_make_identifier(
312 AMI_MASK_ONLY_SPACES | AMI_NODELIMITER,
Lev Walkinffd035e2010-10-16 01:26:57 -0700313 0, ((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
314 ? "\"" : "<"),
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800315 MODULE_NAME_OF(exprid),
Lev Walkin22b5ed42006-09-13 02:51:20 +0000316 exprid ? exprid->Identifier : typename,
Lev Walkinffd035e2010-10-16 01:26:57 -0700317 ((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
Vasil Velichkovfebd3d52016-07-18 20:24:49 +0300318 ? ".h\"" : ".h>"), (char*)0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000319 case TNF_SAFE:
Vasil Velichkovfebd3d52016-07-18 20:24:49 +0300320 return asn1c_make_identifier(0, exprid, typename, (char*)0);
Lev Walkinc8285712005-03-04 22:18:20 +0000321 case TNF_CTYPE: /* C type */
Lev Walkinb5450702017-10-04 02:52:57 -0700322 case TNF_CONSTYPE: /* C type */
Lev Walkina00d6b32006-03-21 03:40:38 +0000323 return asn1c_make_identifier(0, exprid,
Vasil Velichkovfebd3d52016-07-18 20:24:49 +0300324 exprid?"t":typename, exprid?0:"t", (char*)0);
Lev Walkinc8285712005-03-04 22:18:20 +0000325 case TNF_RSAFE: /* Recursion-safe type */
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800326 return asn1c_make_identifier(AMI_CHECK_RESERVED | AMI_NODELIMITER, 0,
327 "struct", " ", MODULE_NAME_OF(exprid), typename, (char*)0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000328 }
329
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000330 assert(!"unreachable");
Lev Walkinf15320b2004-06-03 03:38:44 +0000331 return typename;
332}
333
Lev Walkin43292722017-10-05 00:33:32 -0700334static asn1p_expr_type_e
335expr_get_type(arg_t *arg, asn1p_expr_t *expr) {
336 asn1p_expr_t *terminal;
337 terminal = asn1f_find_terminal_type_ex(arg->asn, arg->ns, expr);
338 if(terminal) return terminal->expr_type;
339 return A1TC_INVALID;
340}
341
342enum asn1c_fitsfloat_e
343asn1c_REAL_fits(arg_t *arg, asn1p_expr_t *expr) {
344 asn1p_expr_type_e etype = expr_get_type(arg, arg->expr);
345 if(etype == ASN_BASIC_REAL) {
346 asn1cnst_range_t *range = asn1constraint_compute_OER_range(
347 expr->Identifier, etype, expr->combined_constraints, ACT_EL_RANGE,
348 0, 0, 0);
349 enum asn1c_fitsfloat_e fits;
350 switch(range->narrowing) {
351 case NARROW_FLOAT32:
352 fits = RL_FITS_FLOAT32;
353 break;
354 case NARROW_DOUBLE64:
355 fits = RL_FITS_DOUBLE64;
356 break;
357 default:
358 fits = RL_NOTFIT;
359 break;
360 }
361 asn1constraint_range_free(range);
362 return fits;
363 } else {
364 return 0;
365 }
366}
367
Lev Walkin082cadc2005-08-14 02:18:27 +0000368/*
369 * Check whether the specified INTEGER or ENUMERATED type can be represented
Lev Walkin8bb57a22007-12-03 13:41:36 +0000370 * using the generic 'long' or 'unsigned long' type.
Lev Walkin082cadc2005-08-14 02:18:27 +0000371 */
372enum asn1c_fitslong_e
373asn1c_type_fits_long(arg_t *arg, asn1p_expr_t *expr) {
374 asn1cnst_range_t *range = 0;
375 asn1cnst_edge_t left;
376 asn1cnst_edge_t right;
377 asn1p_expr_t *v;
378
379/*
380 * Since we don't know the sizeof(long) on the possible target platform
381 * which will be compiling the code generated by asn1c, let's play it
382 * simple: long's range is equal to or greater than int32_t.
Lev Walkin4c97bd62005-08-15 01:01:24 +0000383 * NOTE: the most negative integer cannot be written in C, as the C99
384 * standard will give it an unsigned type.
385 * It is defined here as a constant expression.
Lev Walkin082cadc2005-08-14 02:18:27 +0000386 */
Lev Walkinc08c3cf2005-08-15 01:04:48 +0000387#define RIGHTMAX 2147483647 /* of 32-bit integer type */
388#define LEFTMIN (-RIGHTMAX-1) /* of 32-bit integer type */
Lev Walkin082cadc2005-08-14 02:18:27 +0000389
390 /* Descend to the terminal type */
Lev Walkinc0e03b92017-08-22 01:48:23 -0700391 expr = WITH_MODULE_NAMESPACE(
392 expr->module, expr_ns,
393 asn1f_find_terminal_type_ex(arg->asn, expr_ns, expr));
394 if(expr == 0) return FL_NOTFIT;
Lev Walkin082cadc2005-08-14 02:18:27 +0000395
396 /* The "fits into long" operation is relevant only for integer types */
397 switch(expr->expr_type) {
398 case ASN_BASIC_INTEGER:
399 case ASN_BASIC_ENUMERATED:
400 break;
401 default:
402 return FL_NOTFIT;
403 }
404
405 /*
406 * First, evaluate the range of explicitly given identifiers.
407 */
408 TQ_FOR(v, &(expr->members), next) {
409 if(v->expr_type != A1TC_UNIVERVAL)
410 continue;
411 if(v->value->value.v_integer < LEFTMIN
412 || v->value->value.v_integer > RIGHTMAX)
413 return FL_NOTFIT;
414 }
415
Lev Walkin4b553412005-08-14 14:45:44 +0000416 if(!expr->combined_constraints)
Lev Walkin2a744a72013-03-27 01:56:23 -0700417 return (arg->flags & A1C_USE_WIDE_TYPES)
418 ? FL_NOTFIT : FL_PRESUMED;
Lev Walkin4b553412005-08-14 14:45:44 +0000419
Lev Walkin082cadc2005-08-14 02:18:27 +0000420 /*
Lev Walkin4b553412005-08-14 14:45:44 +0000421 * Second, if -fbless-SIZE is given, the (SIZE()) constraint may be
422 * applied (non-standard! but we can deal with this) to the type.
423 * Check the range.
Lev Walkin082cadc2005-08-14 02:18:27 +0000424 */
Lev Walkina28cbb92017-07-31 20:20:17 -0700425 range = asn1constraint_compute_constraint_range(expr->Identifier,
426 expr->expr_type,
Lev Walkin4b553412005-08-14 14:45:44 +0000427 expr->combined_constraints, ACT_CT_SIZE, 0, 0,
428 CPR_simulate_fbless_SIZE);
429 if(range) {
430 if(!range->incompatible) {
431 right = range->right;
432 /* Use 4 instead of sizeof(long) is justified! */
433 if(right.type == ARE_VALUE && right.value <= 4)
Lev Walkin8bb57a22007-12-03 13:41:36 +0000434 return FL_FITS_SIGNED;
Lev Walkin4b553412005-08-14 14:45:44 +0000435 }
436 asn1constraint_range_free(range);
437 }
438
439 /*
440 * Third, pull up the PER visible range of the INTEGER.
441 */
Lev Walkina28cbb92017-07-31 20:20:17 -0700442 range = asn1constraint_compute_PER_range(expr->Identifier, expr->expr_type,
Lev Walkin4b553412005-08-14 14:45:44 +0000443 expr->combined_constraints, ACT_EL_RANGE, 0, 0, 0);
Lev Walkine5086e32014-02-10 11:00:51 -0800444
Lev Walkin082cadc2005-08-14 02:18:27 +0000445 if(!range
Lev Walkine5086e32014-02-10 11:00:51 -0800446 /* Commenting out
447 || range->extensible
448 * because this may or may not indicate wide type.
449 */
Lev Walkin334d5cc2014-02-10 11:06:56 -0800450 || (range->extensible && (arg->flags & A1C_USE_WIDE_TYPES))
Lev Walkin082cadc2005-08-14 02:18:27 +0000451 || range->empty_constraint
Lev Walkin082cadc2005-08-14 02:18:27 +0000452 || range->incompatible
453 || range->not_PER_visible
454 ) {
455 asn1constraint_range_free(range);
Lev Walkin2a744a72013-03-27 01:56:23 -0700456 return (arg->flags & A1C_USE_WIDE_TYPES)
457 ? FL_NOTFIT : FL_PRESUMED;
Lev Walkin082cadc2005-08-14 02:18:27 +0000458 }
459
460 left = range->left;
461 right = range->right;
462 asn1constraint_range_free(range);
463
Lev Walkin8bb57a22007-12-03 13:41:36 +0000464 /* Special case for unsigned */
Lev Walkine0f2a5b2017-08-30 20:02:29 -0700465 if(!(arg->flags & A1C_USE_WIDE_TYPES) && left.type == ARE_VALUE
Lev Walkin48e82d12017-10-19 03:06:35 -0700466 && left.value >= 0 && left.value <= 2147483647
467 && right.type == ARE_MAX) {
Lev Walkine0f2a5b2017-08-30 20:02:29 -0700468 return FL_FITS_UNSIGN;
Lev Walkin48e82d12017-10-19 03:06:35 -0700469 }
470 if(left.type == ARE_VALUE
Lev Walkin8bb57a22007-12-03 13:41:36 +0000471 && left.value >= 0
472 && right.type == ARE_VALUE
473 && right.value > 2147483647
Lev Walkin1b3a1352016-01-10 13:15:02 -0800474 && right.value <= (asn1c_integer_t)(4294967295UL))
Lev Walkin8bb57a22007-12-03 13:41:36 +0000475 return FL_FITS_UNSIGN;
476
477
Lev Walkin082cadc2005-08-14 02:18:27 +0000478 /* If some fixed value is outside of target range, not fit */
479 if(left.type == ARE_VALUE
480 && (left.value < LEFTMIN || left.value > RIGHTMAX))
481 return FL_NOTFIT;
482 if(right.type == ARE_VALUE
483 && (right.value > RIGHTMAX || right.value < LEFTMIN))
484 return FL_NOTFIT;
485
Lev Walkin2a744a72013-03-27 01:56:23 -0700486 /* If the range is open, fits only unless -fwide-types is given */
Lev Walkin082cadc2005-08-14 02:18:27 +0000487 if(left.type != ARE_VALUE || right.type != ARE_VALUE) {
Lev Walkin2a744a72013-03-27 01:56:23 -0700488 return (arg->flags & A1C_USE_WIDE_TYPES)
489 ? FL_NOTFIT : FL_PRESUMED;
Lev Walkin082cadc2005-08-14 02:18:27 +0000490 }
491
Lev Walkin8bb57a22007-12-03 13:41:36 +0000492 return FL_FITS_SIGNED;
Lev Walkin082cadc2005-08-14 02:18:27 +0000493}
494