From 082cadcaaa610df424a1327656abb3055c9f6873 Mon Sep 17 00:00:00 2001 From: Lev Walkin Date: Sun, 14 Aug 2005 02:18:27 +0000 Subject: PER visible constraints are used to select the native representation for INTEGER types --- libasn1compiler/asn1c_misc.c | 88 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 86 insertions(+), 2 deletions(-) (limited to 'libasn1compiler/asn1c_misc.c') diff --git a/libasn1compiler/asn1c_misc.c b/libasn1compiler/asn1c_misc.c index 8c5bb628..bcf062f3 100644 --- a/libasn1compiler/asn1c_misc.c +++ b/libasn1compiler/asn1c_misc.c @@ -1,7 +1,8 @@ #include "asn1c_internal.h" #include "asn1c_misc.h" -#include +#include /* constraint groker from libasn1fix */ +#include /* other exportable stuff from libasn1fix */ /* * Checks that the given string is not a reserved C/C++ keyword. @@ -189,7 +190,9 @@ asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) { case ASN_BASIC_INTEGER: case ASN_BASIC_ENUMERATED: case ASN_BASIC_REAL: - if((arg->flags & A1C_USE_NATIVE_TYPES)) { + if((expr->expr_type == ASN_BASIC_REAL + && (arg->flags & A1C_USE_NATIVE_TYPES)) + || asn1c_type_fits_long(arg, expr)) { switch(_format) { case TNF_CTYPE: case TNF_RSAFE: @@ -239,3 +242,84 @@ asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format) { return typename; } +/* + * Check whether the specified INTEGER or ENUMERATED type can be represented + * using the generic 'long' type. + */ +enum asn1c_fitslong_e +asn1c_type_fits_long(arg_t *arg, asn1p_expr_t *expr) { + asn1cnst_range_t *range = 0; + asn1cnst_edge_t left; + asn1cnst_edge_t right; + asn1p_expr_t *v; + +/* + * Since we don't know the sizeof(long) on the possible target platform + * which will be compiling the code generated by asn1c, let's play it + * simple: long's range is equal to or greater than int32_t. + */ +#define LEFTMIN INT32_MIN +#define RIGHTMAX INT32_MAX + + /* Descend to the terminal type */ + expr = asn1f_find_terminal_type_ex(arg->asn, expr); + if(expr == 0) return FL_NOTFIT; + + /* The "fits into long" operation is relevant only for integer types */ + switch(expr->expr_type) { + case ASN_BASIC_INTEGER: + case ASN_BASIC_ENUMERATED: + break; + default: + return FL_NOTFIT; + } + + /* + * First, evaluate the range of explicitly given identifiers. + */ + TQ_FOR(v, &(expr->members), next) { + if(v->expr_type != A1TC_UNIVERVAL) + continue; + if(v->value->value.v_integer < LEFTMIN + || v->value->value.v_integer > RIGHTMAX) + return FL_NOTFIT; + } + + /* + * Second, pull up the PER visible range of the INTEGER. + */ + if(expr->combined_constraints) + range = asn1constraint_compute_PER_range(expr->expr_type, + expr->combined_constraints, ACT_EL_RANGE, 0, 0, 0); + if(!range + || range->empty_constraint + || range->extensible + || range->incompatible + || range->not_PER_visible + ) { + asn1constraint_range_free(range); + return (arg->flags & A1C_USE_NATIVE_TYPES) + ? FL_FORCED : FL_NOTFIT; + } + + left = range->left; + right = range->right; + asn1constraint_range_free(range); + + /* If some fixed value is outside of target range, not fit */ + if(left.type == ARE_VALUE + && (left.value < LEFTMIN || left.value > RIGHTMAX)) + return FL_NOTFIT; + if(right.type == ARE_VALUE + && (right.value > RIGHTMAX || right.value < LEFTMIN)) + return FL_NOTFIT; + + /* If the range is open, fits only if -fnative-types is given */ + if(left.type != ARE_VALUE || right.type != ARE_VALUE) { + return (arg->flags & A1C_USE_NATIVE_TYPES) + ? FL_FORCED : FL_NOTFIT; + } + + return FL_FITSOK; +} + -- cgit v1.2.3