effective constraint type for walking past SIZE() or FROM() nodes


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@168 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c
index dd0d5e7..2a78aa1 100644
--- a/libasn1fix/asn1fix.c
+++ b/libasn1fix/asn1fix.c
@@ -54,6 +54,16 @@
 		flags &= ~A1F_DEBUG;
 	}
 
+	/* Allow SIZE() constraint for INTEGER and other types */
+	if(flags & A1F_EXTENDED_SizeConstraint) {
+		arg.flags |= A1F_EXTENDED_SizeConstraint;
+		flags &= ~A1F_EXTENDED_SizeConstraint;
+		if(arg.debug) {
+			arg.debug(-1,
+				"Extended SizeConstraint support enabled");
+		}
+	}
+
 	a1f_replace_me_with_proper_interface_arg = arg;
 
 	/*
@@ -273,16 +283,21 @@
 static int
 asn1f_fix_constraints(arg_t *arg) {
 	asn1p_expr_t *top_parent;
+	asn1p_expr_type_e etype;
 	int rvalue = 0;
 	int ret;
 
-	ret = asn1constraint_resolve(arg, arg->expr->constraints);
+	top_parent = asn1f_find_terminal_type(arg, arg->expr, NULL);
+	if(top_parent)
+		etype = top_parent->expr_type;
+	else	etype = A1TC_INVALID;
+
+	ret = asn1constraint_resolve(arg, arg->expr->constraints, etype, 0);
 	RET2RVAL(ret, rvalue);
 
 	ret = asn1constraint_pullup(arg);
 	RET2RVAL(ret, rvalue);
 
-	top_parent = asn1f_find_terminal_type(arg, arg->expr, NULL);
 	if(top_parent) {
 		static enum asn1p_constraint_type_e test_types[] = {
 			ACT_EL_RANGE, ACT_CT_SIZE, ACT_CT_FROM };
diff --git a/libasn1fix/asn1fix.h b/libasn1fix/asn1fix.h
index 1bed858..c75c81c 100644
--- a/libasn1fix/asn1fix.h
+++ b/libasn1fix/asn1fix.h
@@ -12,7 +12,8 @@
  */
 enum asn1f_flags {
 	A1F_NOFLAGS,
-	A1F_DEBUG		= 0x01,	/* Print debugging output */
+	A1F_DEBUG			= 0x01,	/* Print debugging output */
+	A1F_EXTENDED_SizeConstraint	= 0x02,	/* Enable constraint gen code */
 };
 
 /*
diff --git a/libasn1fix/asn1fix_constraint.c b/libasn1fix/asn1fix_constraint.c
index b7b66c4..4620ec5 100644
--- a/libasn1fix/asn1fix_constraint.c
+++ b/libasn1fix/asn1fix_constraint.c
@@ -120,8 +120,7 @@
 }
 
 int
-asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct) {
-	asn1p_expr_t *top_parent;
+asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) {
 	int rvalue = 0;
 	int ret;
 	int el;
@@ -130,6 +129,18 @@
 
 	/* Don't touch information object classes */
 	switch(ct->type) {
+	case ACT_CT_SIZE:
+	case ACT_CT_FROM:
+		if(effective_type && effective_type != ct->type) {
+			FATAL("%s at line %d: "
+				"Incompatible nested %s within %s",
+				arg->expr->Identifier, ct->_lineno,
+				asn1p_constraint_type2str(ct->type),
+				asn1p_constraint_type2str(effective_type)
+			);
+		}
+		effective_type = ct->type;
+		break;
 	case ACT_CT_WCOMP:
 	case ACT_CT_WCOMPS:
 	case ACT_CA_CRC:
@@ -138,21 +149,26 @@
 		break;
 	}
 
-	top_parent = asn1f_find_terminal_type(arg, arg->expr, 0);
-	if(top_parent) {
-		ret = asn1constraint_compatible(top_parent->expr_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);
 		switch(ret) {
 		case -1:	/* If unknown, assume OK. */
 		case  1:
 			break;
 		case 0:
+			if(effective_type == ACT_CT_SIZE
+			&& (arg->flags & A1F_EXTENDED_SizeConstraint))
+				break;
 		default:
 			FATAL("%s at line %d: "
 				"Constraint type %s is not applicable to %s",
 				arg->expr->Identifier, ct->_lineno,
-				asn1p_constraint_type2str(ct->type),
-				ASN_EXPR_TYPE2STR(top_parent->expr_type)
+				asn1p_constraint_type2str(check_type),
+				ASN_EXPR_TYPE2STR(etype)
 			);
 			rvalue = -1;
 			break;
@@ -163,6 +179,9 @@
 			arg->expr->Identifier, arg->expr->_lineno);
 	}
 
+	/*
+	 * Resolve all possible references, wherever they occur.
+	 */
 	if(ct->value && ct->value->type == ATV_REFERENCED) {
 		ret = _constraint_value_resolve(arg, &ct->value);
 		RET2RVAL(ret, rvalue);
@@ -176,8 +195,12 @@
 		RET2RVAL(ret, rvalue);
 	}
 
+	/*
+	 * Proceed recursively.
+	 */
 	for(el = 0; el < ct->el_count; el++) {
-		ret = asn1constraint_resolve(arg, ct->elements[el]);
+		ret = asn1constraint_resolve(arg, ct->elements[el],
+			etype, effective_type);
 		RET2RVAL(ret, rvalue);
 	}
 
diff --git a/libasn1fix/asn1fix_constraint.h b/libasn1fix/asn1fix_constraint.h
index a04e6a5..9e692ef 100644
--- a/libasn1fix/asn1fix_constraint.h
+++ b/libasn1fix/asn1fix_constraint.h
@@ -4,7 +4,9 @@
 /*
  * Resolve referenced values inside constraints.
  */
-int asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct);
+int asn1constraint_resolve(arg_t *arg, asn1p_constraint_t *ct,
+	asn1p_expr_type_e topmost_parent_expression_type,
+	enum asn1p_constraint_type_e effective_constraint_type);
 
 /*
  * Collect all subtype constraints from all parents of this type and