aboutsummaryrefslogtreecommitdiffstats
path: root/libasn1compiler
diff options
context:
space:
mode:
authorvlm <vlm@59561ff5-6e30-0410-9f3c-9617f08c8826>2005-08-14 02:18:27 +0000
committervlm <vlm@59561ff5-6e30-0410-9f3c-9617f08c8826>2005-08-14 02:18:27 +0000
commit75b3a53e15faa16aa5030449d5842846799d4be7 (patch)
tree7a875ab66bf5a6ceb92831e06fccd81abe3b656f /libasn1compiler
parent96853d8f426df5f715ba88c2c0a1d0b3c7f83e93 (diff)
PER visible constraints are used to select the native representation for INTEGER types
git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@957 59561ff5-6e30-0410-9f3c-9617f08c8826
Diffstat (limited to 'libasn1compiler')
-rw-r--r--libasn1compiler/asn1c_C.c23
-rw-r--r--libasn1compiler/asn1c_constraint.c5
-rw-r--r--libasn1compiler/asn1c_misc.c88
-rw-r--r--libasn1compiler/asn1c_misc.h15
4 files changed, 115 insertions, 16 deletions
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index f91da76f..d39018ee 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -218,29 +218,26 @@ asn1c_lang_C_type_BIT_STRING(arg_t *arg) {
asn1p_expr_t *expr = arg->expr;
asn1p_expr_t *v;
int el_count = expr_elements_count(arg, expr);
- int eidx = 0;
if(el_count) {
+ int eidx = 0;
REDIR(OT_DEPS);
OUT("typedef enum ");
out_name_chain(arg, 1);
OUT(" {\n");
TQ_FOR(v, &(expr->members), next) {
- switch(v->expr_type) {
- case A1TC_UNIVERVAL:
- OUT("\t");
- out_name_chain(arg, 0);
- OUT("_%s", MKID(v->Identifier));
- OUT("\t= %" PRIdASN "%s\n",
- v->value->value.v_integer,
- (eidx+1 < el_count) ? "," : "");
- eidx++;
- break;
- default:
+ eidx++;
+ if(v->expr_type != A1TC_UNIVERVAL) {
OUT("/* Unexpected BIT STRING element: %s */\n",
v->Identifier);
- break;
+ continue;
}
+ OUT("\t");
+ out_name_chain(arg, 0);
+ OUT("_%s", MKID(v->Identifier));
+ OUT("\t= %" PRIdASN "%s\n",
+ v->value->value.v_integer,
+ (eidx < el_count) ? "," : "");
}
OUT("} ");
out_name_chain(arg, 0);
diff --git a/libasn1compiler/asn1c_constraint.c b/libasn1compiler/asn1c_constraint.c
index d75313d2..372730fc 100644
--- a/libasn1compiler/asn1c_constraint.c
+++ b/libasn1compiler/asn1c_constraint.c
@@ -62,6 +62,9 @@ asn1c_emit_constraint_checking_code(arg_t *arg) {
switch(etype) {
case ASN_BASIC_INTEGER:
case ASN_BASIC_ENUMERATED:
+ if(asn1c_type_fits_long(arg, arg->expr) == FL_NOTFIT)
+ produce_st = 1;
+ break;
case ASN_BASIC_REAL:
if(!(arg->flags & A1C_USE_NATIVE_TYPES))
produce_st = 1;
@@ -556,7 +559,7 @@ emit_value_determination_code(arg_t *arg, asn1p_expr_type_e etype, asn1cnst_rang
switch(etype) {
case ASN_BASIC_INTEGER:
case ASN_BASIC_ENUMERATED:
- if(arg->flags & A1C_USE_NATIVE_TYPES) {
+ if(asn1c_type_fits_long(arg, arg->expr) != FL_NOTFIT) {
OUT("value = *(const long *)sptr;\n");
} else {
if(r_value->el_count == 0
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 <asn1fix_export.h>
+#include <asn1fix_crange.h> /* constraint groker from libasn1fix */
+#include <asn1fix_export.h> /* 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;
+}
+
diff --git a/libasn1compiler/asn1c_misc.h b/libasn1compiler/asn1c_misc.h
index eab75674..8da261df 100644
--- a/libasn1compiler/asn1c_misc.h
+++ b/libasn1compiler/asn1c_misc.h
@@ -24,4 +24,19 @@ enum tnfmt {
};
char *asn1c_type_name(arg_t *arg, asn1p_expr_t *expr, enum tnfmt _format);
+/*
+ * Check whether the specified INTEGER or ENUMERATED type can be represented
+ * using the generic 'long' type.
+ * Return values:
+ * FL_NOTFIT: No, it cannot be represented using long.
+ * FL_FITSOK: It can be represented using long.
+ * FL_FORCED: Probably can't, but -fnative-types is in force.
+ */
+enum asn1c_fitslong_e {
+ FL_NOTFIT,
+ FL_FITSOK,
+ FL_FORCED,
+};
+enum asn1c_fitslong_e asn1c_type_fits_long(arg_t *arg, asn1p_expr_t *expr);
+
#endif /* _ASN1_COMPILER_MISC_H_ */