anti-clash


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@685 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/libasn1fix/asn1fix.c b/libasn1fix/asn1fix.c
index 7bfb903..f120853 100644
--- a/libasn1fix/asn1fix.c
+++ b/libasn1fix/asn1fix.c
@@ -18,6 +18,7 @@
 static int asn1f_fix_constructed(arg_t *arg);	/* For SEQUENCE/SET/CHOICE */
 static int asn1f_resolve_constraints(arg_t *arg); /* For subtype constraints */
 static int asn1f_check_constraints(arg_t *arg);	/* For subtype constraints */
+static int asn1f_check_duplicate(arg_t *arg);
 
 arg_t a1f_replace_me_with_proper_interface_arg;
 
@@ -78,6 +79,7 @@
 
 	/*
 	 * Process each module in the list.
+	 * PHASE I.
 	 */
 	TQ_FOR(arg.mod, &(asn->modules), mod_next) {
 		int ret = asn1f_fix_module__phase_1(&arg);
@@ -88,6 +90,7 @@
 		if(ret == -1) fatals++;
 		if(ret == 1) warnings++;
 	}
+	/* PHASE II. */
 	TQ_FOR(arg.mod, &(asn->modules), mod_next) {
 		int ret = asn1f_fix_module__phase_2(&arg);
 		if(ret == -1) fatals++;
@@ -145,11 +148,14 @@
 
 	/*
 	 * Do various non-recursive transformations.
-	 * Order is not important.
 	 */
 	TQ_FOR(expr, &(arg->mod->members), next) {
 		arg->expr = expr;
 
+		/* Check whether this type is a duplicate */
+		ret = asn1f_check_duplicate(arg);
+		RET2RVAL(ret, rvalue);
+
 		if(expr->meta_type == AMT_PARAMTYPE)
 			/* Do not process the parametrized type just yet */
 			continue;
@@ -257,7 +263,7 @@
 	TQ_FOR(expr, &(arg->mod->members), next) {
 		arg->expr = expr;
 
-		if(arg->expr->meta_type == AMT_PARAMTYPE)
+		if(expr->meta_type == AMT_PARAMTYPE)
 			/* Do not process the parametrized types here */
 			continue;
 
@@ -388,6 +394,46 @@
 	return rvalue;
 }
 
+static int
+asn1f_check_duplicate(arg_t *arg) {
+	arg_t tmparg = *arg;
+
+	/*
+	 * This is a linear scan in search of a similar type.
+	 * The linear scan is just fine for the task, no need to over-optimize.
+	 */
+	TQ_FOR(tmparg.mod, &arg->asn->modules, mod_next) {
+		TQ_FOR(tmparg.expr, &(tmparg.mod->members), next) {
+			assert(tmparg.expr->Identifier);
+			assert(arg->expr->Identifier);
+			if(tmparg.expr == arg->expr) break;
+
+			if(strcmp(tmparg.expr->Identifier,
+				arg->expr->Identifier) == 0) {
+				int diff_files = strcmp(arg->mod->source_file_name, tmparg.mod->source_file_name) ? 1 : 0;
+				FATAL("ASN.1 expression \"%s\" at line %d of module %s\n"
+				"clashes with expression \"%s\" at line %d of module %s"
+				"%s%s%s.\n"
+				"Please rename either instance to resolve the conflict",
+					arg->expr->Identifier,
+					arg->expr->_lineno,
+					arg->mod->Identifier,
+					tmparg.expr->Identifier,
+					tmparg.expr->_lineno,
+					tmparg.mod->Identifier,
+					diff_files ? " (" : "",
+					diff_files ? tmparg.mod->source_file_name : "",
+					diff_files ? ")" : ""
+				);
+				return -1;
+			}
+		}
+		if(tmparg.mod == arg->mod) break;
+	}
+
+	return 0;
+}
+
 /*
  * Print everything to stderr
  */
diff --git a/libasn1fix/asn1fix_param.c b/libasn1fix/asn1fix_param.c
index 1ecdeb1..46ee3ba 100644
--- a/libasn1fix/asn1fix_param.c
+++ b/libasn1fix/asn1fix_param.c
@@ -83,6 +83,9 @@
 	void *p;
 	int ret;
 
+	DEBUG("asn1f_parametrize(%s <= %s)",
+		expr->Identifier, ptype->Identifier);
+
 	/*
 	 * The algorithm goes like that:
 	 * 1. Replace the expression's type with parametrized type.
@@ -127,6 +130,7 @@
 asn1f_param_process_recursive(arg_t *arg, asn1p_expr_t *expr, asn1p_expr_t *ptype, asn1p_expr_t *actargs) {
 	asn1p_expr_t *child;
 
+
 	TQ_FOR(child, &(expr->members), next) {
 		asn1p_expr_t *ra;
 		asn1p_expr_t *ne;	/* new expression (clone) */
@@ -232,6 +236,11 @@
 		DEBUG("_process_constraints(%s), ra=%s",
 			asn1f_printable_reference(ref), ra->Identifier);
 
+		if(ra->expr_type == A1TC_PARAMETRIZED) {
+			DEBUG("Double parametrization");
+		}
+
+		assert(ra->Identifier);
 		str = strdup(ra->Identifier);
 		if(!str) return -1;