more support for parametrized type; additional ANY support


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@246 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/libasn1fix/asn1fix_constr.c b/libasn1fix/asn1fix_constr.c
index fab78d3..8c9dd38 100644
--- a/libasn1fix/asn1fix_constr.c
+++ b/libasn1fix/asn1fix_constr.c
@@ -1,7 +1,10 @@
 #include "asn1fix_internal.h"
 
+#define	AFT_IMAGINARY_ANY	1	/* _fetch_tag() flag */
+
 static int _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v);
 static int _asn1f_compare_tags(arg_t *arg, asn1p_expr_t *a, asn1p_expr_t *b);
+static int _asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr);
 
 int
 asn1f_pull_components_of(arg_t *arg) {
@@ -77,6 +80,9 @@
 	return r_value;
 }
 
+/*
+ * Fix extensibility parts inside constructed types (SEQUENCE, SET, CHOICE).
+ */
 int
 asn1f_fix_constr_ext(arg_t *arg) {
 	asn1p_expr_t *expr = arg->expr;
@@ -103,6 +109,10 @@
 	TQ_INIT(&ext_list);
 	cur_list = (void *)&root_list;
 
+	/*
+	 * Split the set of fields into two lists, the root list
+	 * and the extensions list.
+	 */
 	while((v = TQ_REMOVE(&(expr->members), next))) {
 		if(v->expr_type == A1TC_EXTENSIBLE) {
 			ext_count++;
@@ -161,16 +171,30 @@
 
 
 int
-asn1f_fix_constr_tag(arg_t *arg) {
+asn1f_fix_constr_tag(arg_t *arg, int fix_top_level) {
 	asn1p_expr_t *expr = arg->expr;
 	asn1p_expr_t *v;
-	int fl_impl_tags = 0;
-	int fl_auto_tags = 0;
 	int root_tagged = 0;	/* The root component is manually tagged */
 	int ext_tagged = 0;	/* The extensions are manually tagged */
 	int component_number = 0;
 	int r_value = 0;
 
+	DEBUG("%s(%s) for line %d", __func__,
+		expr->Identifier, expr->_lineno);
+
+	/*
+	 * Fix the top-level type itself first.
+	 */
+	if(fix_top_level) {
+		if(expr->tag.tag_class == TC_NOCLASS)
+			return r_value;
+
+		if(_asn1f_fix_type_tag(arg, expr))
+			r_value = -1;
+
+		return r_value;
+	}
+
 	switch(expr->expr_type) {
 	case ASN_CONSTR_SEQUENCE:
 	case ASN_CONSTR_SET:
@@ -180,14 +204,7 @@
 		return 0;
 	}
 
-	fl_impl_tags = (arg->mod->module_flags & MSF_IMPLICIT_TAGS);
-	fl_auto_tags = (arg->mod->module_flags & MSF_AUTOMATIC_TAGS);
-
-	DEBUG("%s(%s) {%d, %d} for line %d", __func__,
-		expr->Identifier, fl_impl_tags, fl_auto_tags, expr->_lineno);
-
 	TQ_FOR(v, &(expr->members), next) {
-		int must_explicit = 0;
 
 		if(v->expr_type == A1TC_EXTENSIBLE) {
 			component_number++;
@@ -196,43 +213,18 @@
 
 		if(v->tag.tag_class == TC_NOCLASS) {
 			continue;
-		} else {
-			switch(component_number) {
-			case 0: case 2:
-				root_tagged = 1; break;
-			default:
-				ext_tagged = 1; break;
-			}
 		}
 
-		must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, v);
-
-		if(fl_impl_tags) {
-			if(v->tag.tag_mode != TM_EXPLICIT) {
-				if(must_explicit)
-					v->tag.tag_mode = TM_EXPLICIT;
-				else
-					v->tag.tag_mode = TM_IMPLICIT;
-			}
-		} else {
-			if(v->tag.tag_mode == TM_DEFAULT) {
-				v->tag.tag_mode = TM_EXPLICIT;
-			}
+		switch(component_number) {
+		case 0: case 2:
+			root_tagged = 1; break;
+		default:
+			ext_tagged = 1; break;
 		}
 
-		/*
-		 * Perform a final sanity check.
-		 */
-		if(must_explicit) {
-			if(v->tag.tag_mode == TM_IMPLICIT) {
-				FATAL("%s tagged in IMPLICIT mode "
-					"but must be EXPLICIT at line %d",
-					v->Identifier, v->_lineno);
-				r_value = -1;
-			} else {
-				v->tag.tag_mode = TM_EXPLICIT;
-			}
-		}
+		if(_asn1f_fix_type_tag(arg, v))
+			r_value = -1;
+
 	}
 
 	if(ext_tagged && !root_tagged) {
@@ -241,13 +233,51 @@
 			"but root components are not",
 			expr->Identifier, expr->_lineno);
 		r_value = -1;
-	} else if(!root_tagged && !ext_tagged && fl_auto_tags) {
+	} else if(!root_tagged && !ext_tagged
+			&& (arg->mod->module_flags & MSF_AUTOMATIC_TAGS)) {
+		/* Make a decision on automatic tagging */
 		expr->auto_tags_OK = 1;
 	}
 
 	return r_value;
 }
 
+static int
+_asn1f_fix_type_tag(arg_t *arg, asn1p_expr_t *expr) {
+	int must_explicit = _asn1f_check_if_tag_must_be_explicit(arg, expr);
+	int fl_impl_tags = (arg->mod->module_flags & MSF_IMPLICIT_TAGS);
+	int r_value = 0;
+
+	if(fl_impl_tags) {
+		if(expr->tag.tag_mode != TM_EXPLICIT) {
+			if(must_explicit)
+				expr->tag.tag_mode = TM_EXPLICIT;
+			else
+				expr->tag.tag_mode = TM_IMPLICIT;
+		}
+	} else {
+		if(expr->tag.tag_mode == TM_DEFAULT) {
+			expr->tag.tag_mode = TM_EXPLICIT;
+		}
+	}
+
+	/*
+	 * Perform a final sanity check.
+	 */
+	if(must_explicit) {
+		if(expr->tag.tag_mode == TM_IMPLICIT) {
+			FATAL("%s tagged in IMPLICIT mode "
+				"but must be EXPLICIT at line %d",
+				expr->Identifier, expr->_lineno);
+			r_value = -1;
+		} else {
+			expr->tag.tag_mode = TM_EXPLICIT;
+		}
+	}
+
+	return r_value;
+}
+
 int
 asn1f_fix_constr_autotag(arg_t *arg) {
 	asn1p_expr_t *expr = arg->expr;
@@ -333,11 +363,25 @@
 
 static int
 _asn1f_check_if_tag_must_be_explicit(arg_t *arg, asn1p_expr_t *v) {
+	struct asn1p_type_tag_s tag;
+	struct asn1p_type_tag_s save_tag;
 	asn1p_expr_t *reft;
+	int ret;
+
+	/*
+	 * Fetch the _next_ tag for this type.
+	 */
+	save_tag = v->tag;			/* Save existing tag */
+	memset(&v->tag, 0, sizeof(v->tag));	/* Remove it temporarily */
+	ret = asn1f_fetch_tag(arg->asn, arg->mod, v, &tag, 0);
+	v->tag = save_tag;			/* Restore the tag back */
+
+	if(ret == 0) return 0;	/* If found tag, it's okay */
 
 	reft = asn1f_find_terminal_type(arg, v);
 	if(reft) {
 		switch(reft->expr_type) {
+		case ASN_TYPE_ANY:
 		case ASN_CONSTR_CHOICE:
 			return 1;
 		default:
@@ -357,8 +401,8 @@
 	int ra, rb;
 	int ret;
 
-	ra = asn1f_fetch_tag(arg->asn, arg->mod, a, &ta);
-	rb = asn1f_fetch_tag(arg->asn, arg->mod, b, &tb);
+	ra = asn1f_fetch_tag(arg->asn, arg->mod, a, &ta, AFT_IMAGINARY_ANY);
+	rb = asn1f_fetch_tag(arg->asn, arg->mod, b, &tb, AFT_IMAGINARY_ANY);
 
 	/*
 	 * If both tags are explicitly or implicitly given, use them.
@@ -367,8 +411,12 @@
 		/*
 		 * Simple case: fetched both tags.
 		 */
-		if(ta.tag_value == tb.tag_value
-		&& ta.tag_class == tb.tag_class) {
+
+		if((ta.tag_value == tb.tag_value
+			&& ta.tag_class == tb.tag_class)
+		|| ta.tag_value == -1	/* Spread IMAGINARY ANY tag... */
+		|| tb.tag_value == -1	/* ...it is an evil virus, fear it! */
+		) {
 			char *p = (a->expr_type == A1TC_EXTENSIBLE)
 				?"potentially ":"";
 			FATAL("Component \"%s\" at line %d %shas the same tag "