support for constraints on primitive types while they are being defined


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@782 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c
index 509a0c2..2b48ce8 100644
--- a/libasn1fix/asn1fix.c
+++ b/libasn1fix/asn1fix.c
@@ -385,7 +385,8 @@
 				arg->expr->combined_constraints,
 				test_types[i], 0, 0, 0);
 		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->meta_type,
 				arg->expr->_lineno);
diff --git a/libasn1fix/asn1fix_constraint.c b/libasn1fix/asn1fix_constraint.c
index 441a9fb..808f4e8 100644
--- a/libasn1fix/asn1fix_constraint.c
+++ b/libasn1fix/asn1fix_constraint.c
@@ -3,7 +3,7 @@
 #include "asn1fix_crange.h"
 
 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
 asn1constraint_pullup(arg_t *arg) {
@@ -120,11 +120,12 @@
 
 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) {
+	enum asn1p_constraint_type_e real_constraint_type;
 	unsigned int el;
 	int rvalue = 0;
 	int ret;
 
-	DEBUG("%s", arg->expr->Identifier);
+	DEBUG("(\"%s\")", arg->expr->Identifier);
 
 	if(!ct) return 0;
 
@@ -150,12 +151,11 @@
 		break;
 	}
 
+	real_constraint_type = effective_type ? effective_type : ct->type;
+
 	if(etype != A1TC_INVALID) {
-		enum asn1p_constraint_type_e check_type;
 
-		check_type = effective_type ? effective_type : ct->type;
-
-		ret = asn1constraint_compatible(etype, check_type);
+		ret = asn1constraint_compatible(etype, real_constraint_type);
 		switch(ret) {
 		case -1:	/* If unknown, assume OK. */
 		case  1:
@@ -168,7 +168,7 @@
 			FATAL("%s at line %d: "
 				"Constraint type %s is not applicable to %s",
 				arg->expr->Identifier, ct->_lineno,
-				asn1p_constraint_type2str(check_type),
+				asn1p_constraint_type2str(real_constraint_type),
 				ASN_EXPR_TYPE2STR(etype)
 			);
 			rvalue = -1;
@@ -184,15 +184,18 @@
 	 * Resolve all possible references, wherever they occur.
 	 */
 	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);
 	}
 	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);
 	}
 	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);
 	}
 
@@ -231,31 +234,26 @@
 
 
 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 *tmp_expr;
 	arg_t tmp_arg;
 	int rvalue = 0;
 	int ret;
 
-	tmp_expr = asn1f_lookup_symbol(arg, mod, (*value)->value.reference);
-	if(tmp_expr == NULL) {
-		FATAL("Cannot find symbol %s (%s) "
-			"used in %s subtype constraint at line %d",
-			asn1f_printable_reference((*value)->value.reference),
-			mod->Identifier,
-			arg->expr->Identifier,
-			arg->expr->_lineno);
-		assert((*value)->type == ATV_REFERENCED);
-		return -1;
-	}
+	(void)mod;
 
-	static_expr = *tmp_expr;
+	DEBUG("(\"%s\", within <%s>)",
+		asn1f_printable_value(*value),
+		asn1p_constraint_type2str(real_ctype));
+
+	static_expr = *arg->expr;
 	static_expr.value = *value;
+	static_expr.meta_type = AMT_VALUE;
 	tmp_arg = *arg;
-	tmp_arg.mod = tmp_expr->module;
+	tmp_arg.mod = arg->expr->module;
 	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);
 	assert(static_expr.value);
 	*value = static_expr.value;
diff --git a/libasn1fix/asn1fix_derefv.c b/libasn1fix/asn1fix_derefv.c
index 261425c..76f49a3 100644
--- a/libasn1fix/asn1fix_derefv.c
+++ b/libasn1fix/asn1fix_derefv.c
@@ -9,7 +9,7 @@
 	int r_value = 0;
 
 	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 */
 			r_value = -1;
 		}
@@ -42,7 +42,7 @@
 		tmpexpr.meta_type = AMT_VALUE;
 		tmpexpr.marker.default_value = 0;
 		tmpexpr.value = expr->marker.default_value;
-		if(asn1f_value_resolve(&tmparg, &tmpexpr))
+		if(asn1f_value_resolve(&tmparg, &tmpexpr, 0))
 			r_value = -1;
 		expr->marker.default_value = tmpexpr.value;
 	}
diff --git a/libasn1fix/asn1fix_integer.c b/libasn1fix/asn1fix_integer.c
index e0304bd..892e927 100644
--- a/libasn1fix/asn1fix_integer.c
+++ b/libasn1fix/asn1fix_integer.c
@@ -76,7 +76,7 @@
 			/*
 			 * 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 */
 				rvalue = -1;
 				continue;
diff --git a/libasn1fix/asn1fix_value.c b/libasn1fix/asn1fix_value.c
index c40d58a..7a1da99 100644
--- a/libasn1fix/asn1fix_value.c
+++ b/libasn1fix/asn1fix_value.c
@@ -3,7 +3,7 @@
 static int _asn1f_copy_value(arg_t *arg, asn1p_expr_t *to,asn1p_expr_t *from);
 
 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 *value_expr;
 	asn1p_expr_t *type_expr;
@@ -16,8 +16,12 @@
 	if(expr->value->type != ATV_REFERENCED)
 		return 0;
 
-	DEBUG("(=\"%s\", %x)",
-		asn1f_printable_value(expr->value), expr->expr_type);
+	DEBUG("(=\"%s\", %x%s%s)",
+		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.
@@ -39,7 +43,7 @@
 	 */
 	value_expr = asn1f_find_terminal_value(arg, 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),
 			value_expr->Identifier, value_expr->_lineno);
 	} else {
@@ -54,11 +58,11 @@
 	WITH_MODULE(value_expr->module,
 		val_type_expr = asn1f_find_terminal_type(arg, value_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),
 			val_type_expr->Identifier, val_type_expr->_lineno);
 	} 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));
 		return -1;
 	}
@@ -67,14 +71,24 @@
 	 * 4. Check compatibility between the type of the current expression
 	 * 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) {
 		switch(type_expr->expr_type) {
 		case ASN_BASIC_INTEGER:
 		case ASN_BASIC_ENUMERATED:
-			FATAL("Incompatible type of %s at %d with %s at %d",
-			type_expr->Identifier, type_expr->_lineno,
-			val_type_expr->Identifier, val_type_expr->_lineno);
+			FATAL("Incompatible type of \"%s\" (%s) at line %d "
+			"with \"%s\" (%s) at line %d",
+			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;
 		case ASN_BASIC_OBJECT_IDENTIFIER:
 			/*
@@ -85,9 +99,14 @@
 		default:
 			break;
 		}
-		WARNING("\tIncompatible type of %s at %d with %s at %d",
-			type_expr->Identifier, type_expr->_lineno,
-			val_type_expr->Identifier, val_type_expr->_lineno);
+		WARNING("Incompatible type of \"%s\" (%s) at line %d "
+			"with \"%s\" (%s) at line %d",
+			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;
 	}
 
@@ -105,7 +124,7 @@
 		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,
 		asn1f_printable_value(expr->value));
 
@@ -162,7 +181,7 @@
 	identifier = value_expr->value->value.reference->components[0].name;
 
 	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,
 		identifier, value_expr->_lineno,
 		child_expr
diff --git a/libasn1fix/asn1fix_value.h b/libasn1fix/asn1fix_value.h
index 7234035..067894a 100644
--- a/libasn1fix/asn1fix_value.h
+++ b/libasn1fix/asn1fix_value.h
@@ -15,7 +15,8 @@
  * -1/EEXIST:	Reference is not compatible with the desired type.
  * -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