Commit 9288d1c2 authored by Lev Walkin's avatar Lev Walkin

support for constraints on primitive types while they are being defined

parent c92a7464
...@@ -385,7 +385,8 @@ asn1f_check_constraints(arg_t *arg) { ...@@ -385,7 +385,8 @@ asn1f_check_constraints(arg_t *arg) {
arg->expr->combined_constraints, arg->expr->combined_constraints,
test_types[i], 0, 0, 0); test_types[i], 0, 0, 0);
if(!range && errno == EPERM) { if(!range && errno == EPERM) {
FATAL("This error happened for %s (%d) at line %d", FATAL("This error happened for \"%s\" (meta %d) "
"at line %d",
arg->expr->Identifier, arg->expr->Identifier,
arg->expr->meta_type, arg->expr->meta_type,
arg->expr->_lineno); arg->expr->_lineno);
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include "asn1fix_crange.h" #include "asn1fix_crange.h"
static void _remove_exceptions(arg_t *arg, asn1p_constraint_t *ct); static void _remove_exceptions(arg_t *arg, asn1p_constraint_t *ct);
static int _constraint_value_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_value_t **value); static int constraint_value_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype);
int int
asn1constraint_pullup(arg_t *arg) { asn1constraint_pullup(arg_t *arg) {
...@@ -120,11 +120,12 @@ asn1constraint_pullup(arg_t *arg) { ...@@ -120,11 +120,12 @@ asn1constraint_pullup(arg_t *arg) {
int int
asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) { asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) {
enum asn1p_constraint_type_e real_constraint_type;
unsigned int el; unsigned int el;
int rvalue = 0; int rvalue = 0;
int ret; int ret;
DEBUG("%s", arg->expr->Identifier); DEBUG("(\"%s\")", arg->expr->Identifier);
if(!ct) return 0; if(!ct) return 0;
...@@ -150,12 +151,11 @@ asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, ...@@ -150,12 +151,11 @@ asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct,
break; break;
} }
if(etype != A1TC_INVALID) { real_constraint_type = effective_type ? effective_type : ct->type;
enum asn1p_constraint_type_e check_type;
check_type = effective_type ? effective_type : ct->type; if(etype != A1TC_INVALID) {
ret = asn1constraint_compatible(etype, check_type); ret = asn1constraint_compatible(etype, real_constraint_type);
switch(ret) { switch(ret) {
case -1: /* If unknown, assume OK. */ case -1: /* If unknown, assume OK. */
case 1: case 1:
...@@ -168,7 +168,7 @@ asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, ...@@ -168,7 +168,7 @@ asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct,
FATAL("%s at line %d: " FATAL("%s at line %d: "
"Constraint type %s is not applicable to %s", "Constraint type %s is not applicable to %s",
arg->expr->Identifier, ct->_lineno, arg->expr->Identifier, ct->_lineno,
asn1p_constraint_type2str(check_type), asn1p_constraint_type2str(real_constraint_type),
ASN_EXPR_TYPE2STR(etype) ASN_EXPR_TYPE2STR(etype)
); );
rvalue = -1; rvalue = -1;
...@@ -184,15 +184,18 @@ asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, ...@@ -184,15 +184,18 @@ asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct,
* Resolve all possible references, wherever they occur. * Resolve all possible references, wherever they occur.
*/ */
if(ct->value && ct->value->type == ATV_REFERENCED) { if(ct->value && ct->value->type == ATV_REFERENCED) {
ret = _constraint_value_resolve(arg, mod, &ct->value); ret = constraint_value_resolve(arg, mod,
&ct->value, real_constraint_type);
RET2RVAL(ret, rvalue); RET2RVAL(ret, rvalue);
} }
if(ct->range_start && ct->range_start->type == ATV_REFERENCED) { if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
ret = _constraint_value_resolve(arg, mod, &ct->range_start); ret = constraint_value_resolve(arg, mod,
&ct->range_start, real_constraint_type);
RET2RVAL(ret, rvalue); RET2RVAL(ret, rvalue);
} }
if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) { if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
ret = _constraint_value_resolve(arg, mod, &ct->range_stop); ret = constraint_value_resolve(arg, mod,
&ct->range_stop, real_constraint_type);
RET2RVAL(ret, rvalue); RET2RVAL(ret, rvalue);
} }
...@@ -231,31 +234,26 @@ _remove_exceptions(arg_t *arg, asn1p_constraint_t *ct) { ...@@ -231,31 +234,26 @@ _remove_exceptions(arg_t *arg, asn1p_constraint_t *ct) {
static int static int
_constraint_value_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_value_t **value) { constraint_value_resolve(arg_t *arg, asn1p_module_t *mod,
asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype) {
asn1p_expr_t static_expr; asn1p_expr_t static_expr;
asn1p_expr_t *tmp_expr;
arg_t tmp_arg; arg_t tmp_arg;
int rvalue = 0; int rvalue = 0;
int ret; int ret;
tmp_expr = asn1f_lookup_symbol(arg, mod, (*value)->value.reference); (void)mod;
if(tmp_expr == NULL) {
FATAL("Cannot find symbol %s (%s) " DEBUG("(\"%s\", within <%s>)",
"used in %s subtype constraint at line %d", asn1f_printable_value(*value),
asn1f_printable_reference((*value)->value.reference), asn1p_constraint_type2str(real_ctype));
mod->Identifier,
arg->expr->Identifier,
arg->expr->_lineno);
assert((*value)->type == ATV_REFERENCED);
return -1;
}
static_expr = *tmp_expr; static_expr = *arg->expr;
static_expr.value = *value; static_expr.value = *value;
static_expr.meta_type = AMT_VALUE;
tmp_arg = *arg; tmp_arg = *arg;
tmp_arg.mod = tmp_expr->module; tmp_arg.mod = arg->expr->module;
tmp_arg.expr = &static_expr; tmp_arg.expr = &static_expr;
ret = asn1f_fix_dereference_values(&tmp_arg); ret = asn1f_value_resolve(&tmp_arg, &static_expr, &real_ctype);
RET2RVAL(ret, rvalue); RET2RVAL(ret, rvalue);
assert(static_expr.value); assert(static_expr.value);
*value = static_expr.value; *value = static_expr.value;
......
...@@ -9,7 +9,7 @@ asn1f_fix_dereference_values(arg_t *arg) { ...@@ -9,7 +9,7 @@ asn1f_fix_dereference_values(arg_t *arg) {
int r_value = 0; int r_value = 0;
if(expr->value && expr->meta_type == AMT_VALUE) { if(expr->value && expr->meta_type == AMT_VALUE) {
if(asn1f_value_resolve(arg, expr)) { if(asn1f_value_resolve(arg, expr, 0)) {
/* This function will emit messages */ /* This function will emit messages */
r_value = -1; r_value = -1;
} }
...@@ -42,7 +42,7 @@ asn1f_fix_dereference_defaults(arg_t *arg) { ...@@ -42,7 +42,7 @@ asn1f_fix_dereference_defaults(arg_t *arg) {
tmpexpr.meta_type = AMT_VALUE; tmpexpr.meta_type = AMT_VALUE;
tmpexpr.marker.default_value = 0; tmpexpr.marker.default_value = 0;
tmpexpr.value = expr->marker.default_value; tmpexpr.value = expr->marker.default_value;
if(asn1f_value_resolve(&tmparg, &tmpexpr)) if(asn1f_value_resolve(&tmparg, &tmpexpr, 0))
r_value = -1; r_value = -1;
expr->marker.default_value = tmpexpr.value; expr->marker.default_value = tmpexpr.value;
} }
......
...@@ -76,7 +76,7 @@ asn1f_fix_integer(arg_t *arg) { ...@@ -76,7 +76,7 @@ asn1f_fix_integer(arg_t *arg) {
/* /*
* Resolve the value, once and for all. * Resolve the value, once and for all.
*/ */
if(asn1f_value_resolve(arg, iv)) { if(asn1f_value_resolve(arg, iv, 0)) {
/* This function will emit messages */ /* This function will emit messages */
rvalue = -1; rvalue = -1;
continue; continue;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
static int _asn1f_copy_value(arg_t *arg, asn1p_expr_t *to,asn1p_expr_t *from); static int _asn1f_copy_value(arg_t *arg, asn1p_expr_t *to,asn1p_expr_t *from);
int int
asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) { asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr, enum asn1p_constraint_type_e *opt_constr_type) {
asn1p_expr_t *val_type_expr; asn1p_expr_t *val_type_expr;
asn1p_expr_t *value_expr; asn1p_expr_t *value_expr;
asn1p_expr_t *type_expr; asn1p_expr_t *type_expr;
...@@ -16,8 +16,12 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) { ...@@ -16,8 +16,12 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) {
if(expr->value->type != ATV_REFERENCED) if(expr->value->type != ATV_REFERENCED)
return 0; return 0;
DEBUG("(=\"%s\", %x)", DEBUG("(=\"%s\", %x%s%s)",
asn1f_printable_value(expr->value), expr->expr_type); asn1f_printable_value(expr->value), expr->expr_type,
opt_constr_type ? ", " : "",
opt_constr_type
? asn1p_constraint_type2str(*opt_constr_type) : ""
);
/* /*
* 1. Find the terminal type for this assignment. * 1. Find the terminal type for this assignment.
...@@ -39,7 +43,7 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) { ...@@ -39,7 +43,7 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) {
*/ */
value_expr = asn1f_find_terminal_value(arg, expr); value_expr = asn1f_find_terminal_value(arg, expr);
if(value_expr) { if(value_expr) {
DEBUG("\tTerminal value for %s->%s is %s at line %d", DEBUG("Terminal value for %s->%s is %s at line %d",
expr->Identifier, asn1f_printable_value(expr->value), expr->Identifier, asn1f_printable_value(expr->value),
value_expr->Identifier, value_expr->_lineno); value_expr->Identifier, value_expr->_lineno);
} else { } else {
...@@ -54,11 +58,11 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) { ...@@ -54,11 +58,11 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) {
WITH_MODULE(value_expr->module, WITH_MODULE(value_expr->module,
val_type_expr = asn1f_find_terminal_type(arg, value_expr)); val_type_expr = asn1f_find_terminal_type(arg, value_expr));
if(val_type_expr) { if(val_type_expr) {
DEBUG("\tTerminal type of value %s->%s is %s at line %d", DEBUG("Terminal type of value %s->%s is %s at line %d",
expr->Identifier, asn1f_printable_value(expr->value), expr->Identifier, asn1f_printable_value(expr->value),
val_type_expr->Identifier, val_type_expr->_lineno); val_type_expr->Identifier, val_type_expr->_lineno);
} else { } else {
FATAL("\tTerminal type of value %s->%s not found", FATAL("Terminal type of value %s->%s not found",
expr->Identifier, asn1f_printable_value(expr->value)); expr->Identifier, asn1f_printable_value(expr->value));
return -1; return -1;
} }
...@@ -67,14 +71,24 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) { ...@@ -67,14 +71,24 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) {
* 4. Check compatibility between the type of the current expression * 4. Check compatibility between the type of the current expression
* and the type of the discovered value. * and the type of the discovered value.
*/ */
ret = asn1f_check_type_compatibility(arg, type_expr, val_type_expr); if(opt_constr_type)
ret = asn1constraint_compatible(val_type_expr->expr_type,
*opt_constr_type);
else
ret = asn1f_check_type_compatibility(arg,
type_expr, val_type_expr);
if(ret == -1) { if(ret == -1) {
switch(type_expr->expr_type) { switch(type_expr->expr_type) {
case ASN_BASIC_INTEGER: case ASN_BASIC_INTEGER:
case ASN_BASIC_ENUMERATED: case ASN_BASIC_ENUMERATED:
FATAL("Incompatible type of %s at %d with %s at %d", FATAL("Incompatible type of \"%s\" (%s) at line %d "
type_expr->Identifier, type_expr->_lineno, "with \"%s\" (%s) at line %d",
val_type_expr->Identifier, val_type_expr->_lineno); type_expr->Identifier,
ASN_EXPR_TYPE2STR(type_expr->expr_type),
type_expr->_lineno,
val_type_expr->Identifier,
ASN_EXPR_TYPE2STR(val_type_expr->expr_type),
val_type_expr->_lineno);
return -1; return -1;
case ASN_BASIC_OBJECT_IDENTIFIER: case ASN_BASIC_OBJECT_IDENTIFIER:
/* /*
...@@ -85,9 +99,14 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) { ...@@ -85,9 +99,14 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) {
default: default:
break; break;
} }
WARNING("\tIncompatible type of %s at %d with %s at %d", WARNING("Incompatible type of \"%s\" (%s) at line %d "
type_expr->Identifier, type_expr->_lineno, "with \"%s\" (%s) at line %d",
val_type_expr->Identifier, val_type_expr->_lineno); type_expr->Identifier,
ASN_EXPR_TYPE2STR(type_expr->expr_type),
type_expr->_lineno,
val_type_expr->Identifier,
ASN_EXPR_TYPE2STR(val_type_expr->expr_type),
val_type_expr->_lineno);
return 1; return 1;
} }
...@@ -105,7 +124,7 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) { ...@@ -105,7 +124,7 @@ asn1f_value_resolve(arg_t *arg, asn1p_expr_t *expr) {
return -1; return -1;
} }
DEBUG("\tFinal value for \"%s\" at line %d is %s", DEBUG("Final value for \"%s\" at line %d is %s",
expr->Identifier, expr->_lineno, expr->Identifier, expr->_lineno,
asn1f_printable_value(expr->value)); asn1f_printable_value(expr->value));
...@@ -162,7 +181,7 @@ asn1f_look_value_in_type(arg_t *arg, ...@@ -162,7 +181,7 @@ asn1f_look_value_in_type(arg_t *arg,
identifier = value_expr->value->value.reference->components[0].name; identifier = value_expr->value->value.reference->components[0].name;
child_expr = asn1f_lookup_child(type_expr, identifier); child_expr = asn1f_lookup_child(type_expr, identifier);
DEBUG("\tLooking into a type %s at line %d for %s at line %d: %s", DEBUG("Looking into a type %s at line %d for %s at line %d: %s",
type_expr->Identifier, type_expr->_lineno, type_expr->Identifier, type_expr->_lineno,
identifier, value_expr->_lineno, identifier, value_expr->_lineno,
child_expr child_expr
......
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
* -1/EEXIST: Reference is not compatible with the desired type. * -1/EEXIST: Reference is not compatible with the desired type.
* -1/ESRCH: Cannot find the terminal reference. * -1/ESRCH: Cannot find the terminal reference.
*/ */
int asn1f_value_resolve(arg_t *arg, asn1p_expr_t *tc); int asn1f_value_resolve(arg_t *arg, asn1p_expr_t *tc,
const enum asn1p_constraint_type_e *opt_constr_type);
/* /*
* Check if a value in value_expr refers to the enumeration or integer element * Check if a value in value_expr refers to the enumeration or integer element
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment