blob: 0e6b0b42365b379e67fcb20dd32e9955b251e70e [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 */
45char *
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 /*
96 * Make sure we have this amount of storage.
97 */
98 if(storage_size <= size) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +080099 if(storage) free(storage);
Lev Walkinf15320b2004-06-03 03:38:44 +0000100 storage = malloc(size + 1);
101 if(storage) {
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800102 storage_size = size + 1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000103 } else {
104 storage_size = 0;
105 return NULL;
106 }
107 }
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 Walkinf15320b2004-06-03 03:38:44 +0000171char *
172asn1c_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 Walkinf15320b2004-06-03 03:38:44 +0000177 char *typename;
178
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 Walkinb85a8132005-08-18 13:38:19 +0000198 tmp.expr = asn1f_class_access_ex(arg->asn,
Lev Walkina00d6b32006-03-21 03:40:38 +0000199 arg->expr->module, arg->expr, expr->rhs_pspecs, expr->reference);
Lev Walkinc2a75092006-03-14 11:52:12 +0000200 if(!tmp.expr) return NULL;
Lev Walkinf15320b2004-06-03 03:38:44 +0000201
Lev Walkinf15320b2004-06-03 03:38:44 +0000202 return asn1c_type_name(&tmp, tmp.expr, _format);
Lev Walkin5a8219a2004-09-08 00:28:57 +0000203 }
204
Lev Walkina00d6b32006-03-21 03:40:38 +0000205 terminal = asn1f_find_terminal_type_ex(arg->asn, expr);
206
Lev Walkinc8285712005-03-04 22:18:20 +0000207 if(_format == TNF_RSAFE) {
Lev Walkinc8285712005-03-04 22:18:20 +0000208 if(terminal && terminal->expr_type & ASN_CONSTR_MASK) {
209 typename = terminal->Identifier;
210 }
211 }
212
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000213 if(_format == TNF_CTYPE) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000214 /*
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000215 * If the component references the type itself,
Lev Walkinc8285712005-03-04 22:18:20 +0000216 * switch to a recursion-safe type naming
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000217 * ("struct foo" instead of "foo_t").
Lev Walkinf15320b2004-06-03 03:38:44 +0000218 */
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000219 if(terminal && terminal == top_parent) {
220 _format = TNF_RSAFE;
Lev Walkin5a8219a2004-09-08 00:28:57 +0000221 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000222 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000223
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800224 if(_format != TNF_RSAFE && terminal && terminal->spec_index != -1) {
Lev Walkina00d6b32006-03-21 03:40:38 +0000225 exprid = terminal;
226 typename = 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000227 }
Lev Walkina00d6b32006-03-21 03:40:38 +0000228
Lev Walkinf15320b2004-06-03 03:38:44 +0000229 break;
230 case ASN_BASIC_INTEGER:
231 case ASN_BASIC_ENUMERATED:
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000232 case ASN_BASIC_REAL:
Lev Walkin082cadc2005-08-14 02:18:27 +0000233 if((expr->expr_type == ASN_BASIC_REAL
Lev Walkin2a744a72013-03-27 01:56:23 -0700234 && !(arg->flags & A1C_USE_WIDE_TYPES))
Lev Walkin082cadc2005-08-14 02:18:27 +0000235 || asn1c_type_fits_long(arg, expr)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000236 switch(_format) {
237 case TNF_CTYPE:
238 case TNF_RSAFE:
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000239 if(expr->expr_type == ASN_BASIC_REAL)
240 return "double";
Lev Walkin8bb57a22007-12-03 13:41:36 +0000241 else if(asn1c_type_fits_long(arg, expr) == FL_FITS_UNSIGN)
242 return "unsigned long";
Lev Walkinf15320b2004-06-03 03:38:44 +0000243 else
Lev Walkin475d91f2005-02-25 12:09:55 +0000244 return "long";
Lev Walkin22b5ed42006-09-13 02:51:20 +0000245 default:
246 typename = 0;
247 switch(expr->expr_type) {
248 case ASN_BASIC_INTEGER:
249 typename = "NativeInteger"; break;
250 case ASN_BASIC_ENUMERATED:
251 typename = "NativeEnumerated"; break;
252 case ASN_BASIC_REAL:
253 typename = "NativeReal"; break;
254 default:
255 break;
256 }
257 break;
Lev Walkinc78cbfb2004-09-14 12:47:45 +0000258 }
Lev Walkin22b5ed42006-09-13 02:51:20 +0000259 if(typename) {
260 if(_format != TNF_INCLUDE)
261 return typename;
262 stdname = 1;
263 break;
Lev Walkinf15320b2004-06-03 03:38:44 +0000264 }
265 }
266 /* Fall through */
267 default:
Lev Walkin0e22b982004-08-25 02:03:26 +0000268 if(expr->expr_type
269 & (ASN_CONSTR_MASK | ASN_BASIC_MASK | ASN_STRING_MASK)) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000270 if(_format == TNF_RSAFE)
271 _format = TNF_CTYPE;
Lev Walkin22b5ed42006-09-13 02:51:20 +0000272 stdname = 1;
Lev Walkinf15320b2004-06-03 03:38:44 +0000273 typename = ASN_EXPR_TYPE2STR(expr->expr_type);
274 } else {
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000275 _format = TNF_RSAFE;
Lev Walkinf15320b2004-06-03 03:38:44 +0000276 typename = expr->Identifier;
277 }
278 }
279
280 switch(_format) {
281 case TNF_UNMODIFIED:
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800282 return asn1c_make_identifier(AMI_MASK_ONLY_SPACES | AMI_NODELIMITER,
283 0, MODULE_NAME_OF(exprid), exprid ? exprid->Identifier : typename, (char*)0);
Lev Walkin22b5ed42006-09-13 02:51:20 +0000284 case TNF_INCLUDE:
285 return asn1c_make_identifier(
286 AMI_MASK_ONLY_SPACES | AMI_NODELIMITER,
Lev Walkinffd035e2010-10-16 01:26:57 -0700287 0, ((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
288 ? "\"" : "<"),
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800289 MODULE_NAME_OF(exprid),
Lev Walkin22b5ed42006-09-13 02:51:20 +0000290 exprid ? exprid->Identifier : typename,
Lev Walkinffd035e2010-10-16 01:26:57 -0700291 ((!stdname || (arg->flags & A1C_INCLUDES_QUOTED))
Vasil Velichkovfebd3d52016-07-18 20:24:49 +0300292 ? ".h\"" : ".h>"), (char*)0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000293 case TNF_SAFE:
Vasil Velichkovfebd3d52016-07-18 20:24:49 +0300294 return asn1c_make_identifier(0, exprid, typename, (char*)0);
Lev Walkinc8285712005-03-04 22:18:20 +0000295 case TNF_CTYPE: /* C type */
Lev Walkina00d6b32006-03-21 03:40:38 +0000296 return asn1c_make_identifier(0, exprid,
Vasil Velichkovfebd3d52016-07-18 20:24:49 +0300297 exprid?"t":typename, exprid?0:"t", (char*)0);
Lev Walkinc8285712005-03-04 22:18:20 +0000298 case TNF_RSAFE: /* Recursion-safe type */
Bi-Ruei, Chiu80fd3062017-05-07 21:00:51 +0800299 return asn1c_make_identifier(AMI_CHECK_RESERVED | AMI_NODELIMITER, 0,
300 "struct", " ", MODULE_NAME_OF(exprid), typename, (char*)0);
Lev Walkinf15320b2004-06-03 03:38:44 +0000301 }
302
Lev Walkin8dd0eed2004-09-17 06:32:12 +0000303 assert(!"unreachable");
Lev Walkinf15320b2004-06-03 03:38:44 +0000304 return typename;
305}
306
Lev Walkin082cadc2005-08-14 02:18:27 +0000307/*
308 * Check whether the specified INTEGER or ENUMERATED type can be represented
Lev Walkin8bb57a22007-12-03 13:41:36 +0000309 * using the generic 'long' or 'unsigned long' type.
Lev Walkin082cadc2005-08-14 02:18:27 +0000310 */
311enum asn1c_fitslong_e
312asn1c_type_fits_long(arg_t *arg, asn1p_expr_t *expr) {
313 asn1cnst_range_t *range = 0;
314 asn1cnst_edge_t left;
315 asn1cnst_edge_t right;
316 asn1p_expr_t *v;
317
318/*
319 * Since we don't know the sizeof(long) on the possible target platform
320 * which will be compiling the code generated by asn1c, let's play it
321 * simple: long's range is equal to or greater than int32_t.
Lev Walkin4c97bd62005-08-15 01:01:24 +0000322 * NOTE: the most negative integer cannot be written in C, as the C99
323 * standard will give it an unsigned type.
324 * It is defined here as a constant expression.
Lev Walkin082cadc2005-08-14 02:18:27 +0000325 */
Lev Walkinc08c3cf2005-08-15 01:04:48 +0000326#define RIGHTMAX 2147483647 /* of 32-bit integer type */
327#define LEFTMIN (-RIGHTMAX-1) /* of 32-bit integer type */
Lev Walkin082cadc2005-08-14 02:18:27 +0000328
329 /* Descend to the terminal type */
330 expr = asn1f_find_terminal_type_ex(arg->asn, expr);
331 if(expr == 0) return FL_NOTFIT;
332
333 /* The "fits into long" operation is relevant only for integer types */
334 switch(expr->expr_type) {
335 case ASN_BASIC_INTEGER:
336 case ASN_BASIC_ENUMERATED:
337 break;
338 default:
339 return FL_NOTFIT;
340 }
341
342 /*
343 * First, evaluate the range of explicitly given identifiers.
344 */
345 TQ_FOR(v, &(expr->members), next) {
346 if(v->expr_type != A1TC_UNIVERVAL)
347 continue;
348 if(v->value->value.v_integer < LEFTMIN
349 || v->value->value.v_integer > RIGHTMAX)
350 return FL_NOTFIT;
351 }
352
Lev Walkin4b553412005-08-14 14:45:44 +0000353 if(!expr->combined_constraints)
Lev Walkin2a744a72013-03-27 01:56:23 -0700354 return (arg->flags & A1C_USE_WIDE_TYPES)
355 ? FL_NOTFIT : FL_PRESUMED;
Lev Walkin4b553412005-08-14 14:45:44 +0000356
Lev Walkin082cadc2005-08-14 02:18:27 +0000357 /*
Lev Walkin4b553412005-08-14 14:45:44 +0000358 * Second, if -fbless-SIZE is given, the (SIZE()) constraint may be
359 * applied (non-standard! but we can deal with this) to the type.
360 * Check the range.
Lev Walkin082cadc2005-08-14 02:18:27 +0000361 */
Lev Walkin4b553412005-08-14 14:45:44 +0000362 range = asn1constraint_compute_PER_range(expr->expr_type,
363 expr->combined_constraints, ACT_CT_SIZE, 0, 0,
364 CPR_simulate_fbless_SIZE);
365 if(range) {
366 if(!range->incompatible) {
367 right = range->right;
368 /* Use 4 instead of sizeof(long) is justified! */
369 if(right.type == ARE_VALUE && right.value <= 4)
Lev Walkin8bb57a22007-12-03 13:41:36 +0000370 return FL_FITS_SIGNED;
Lev Walkin4b553412005-08-14 14:45:44 +0000371 }
372 asn1constraint_range_free(range);
373 }
374
375 /*
376 * Third, pull up the PER visible range of the INTEGER.
377 */
378 range = asn1constraint_compute_PER_range(expr->expr_type,
379 expr->combined_constraints, ACT_EL_RANGE, 0, 0, 0);
Lev Walkine5086e32014-02-10 11:00:51 -0800380
Lev Walkin082cadc2005-08-14 02:18:27 +0000381 if(!range
Lev Walkine5086e32014-02-10 11:00:51 -0800382 /* Commenting out
383 || range->extensible
384 * because this may or may not indicate wide type.
385 */
Lev Walkin334d5cc2014-02-10 11:06:56 -0800386 || (range->extensible && (arg->flags & A1C_USE_WIDE_TYPES))
Lev Walkin082cadc2005-08-14 02:18:27 +0000387 || range->empty_constraint
Lev Walkin082cadc2005-08-14 02:18:27 +0000388 || range->incompatible
389 || range->not_PER_visible
390 ) {
391 asn1constraint_range_free(range);
Lev Walkin2a744a72013-03-27 01:56:23 -0700392 return (arg->flags & A1C_USE_WIDE_TYPES)
393 ? FL_NOTFIT : FL_PRESUMED;
Lev Walkin082cadc2005-08-14 02:18:27 +0000394 }
395
396 left = range->left;
397 right = range->right;
398 asn1constraint_range_free(range);
399
Lev Walkin8bb57a22007-12-03 13:41:36 +0000400 /* Special case for unsigned */
401 if(left.type == ARE_VALUE
402 && left.value >= 0
403 && right.type == ARE_VALUE
404 && right.value > 2147483647
Lev Walkin1b3a1352016-01-10 13:15:02 -0800405 && right.value <= (asn1c_integer_t)(4294967295UL))
Lev Walkin8bb57a22007-12-03 13:41:36 +0000406 return FL_FITS_UNSIGN;
407
408
Lev Walkin082cadc2005-08-14 02:18:27 +0000409 /* If some fixed value is outside of target range, not fit */
410 if(left.type == ARE_VALUE
411 && (left.value < LEFTMIN || left.value > RIGHTMAX))
412 return FL_NOTFIT;
413 if(right.type == ARE_VALUE
414 && (right.value > RIGHTMAX || right.value < LEFTMIN))
415 return FL_NOTFIT;
416
Lev Walkin2a744a72013-03-27 01:56:23 -0700417 /* If the range is open, fits only unless -fwide-types is given */
Lev Walkin082cadc2005-08-14 02:18:27 +0000418 if(left.type != ARE_VALUE || right.type != ARE_VALUE) {
Lev Walkin2a744a72013-03-27 01:56:23 -0700419 return (arg->flags & A1C_USE_WIDE_TYPES)
420 ? FL_NOTFIT : FL_PRESUMED;
Lev Walkin082cadc2005-08-14 02:18:27 +0000421 }
422
Lev Walkin8bb57a22007-12-03 13:41:36 +0000423 return FL_FITS_SIGNED;
Lev Walkin082cadc2005-08-14 02:18:27 +0000424}
425