refactored tagging support

diff --git a/libasn1fix/asn1fix_tags.c b/libasn1fix/asn1fix_tags.c
index 20066e6..6d88798 100644
--- a/libasn1fix/asn1fix_tags.c
+++ b/libasn1fix/asn1fix_tags.c
@@ -2,14 +2,20 @@
 
 #define	ADD_TAG(skip, newtag)	do {					\
 	void *__p;							\
-	if(skip) { skip--; break; }					\
+	if(skip) {							\
+		if(newtag.tag_mode != TM_IMPLICIT)			\
+			skip--;						\
+		break;							\
+	} else {							\
+		if(newtag.tag_mode == TM_IMPLICIT)			\
+			skip++;						\
+	}								\
 	__p = realloc((*tags),						\
 		sizeof(struct asn1p_type_tag_s) * (count + 1));		\
 	if(!__p) return -1;						\
 	*tags = __p;							\
 	(*tags)[count++] = newtag;					\
 	if((flags & AFT_FETCH_OUTMOST)) return count;			\
-	if(newtag.tag_mode == TM_IMPLICIT) skip++;			\
 } while(0)
 
 static int
@@ -46,11 +52,33 @@
 	}
 
 	if(expr->meta_type == AMT_TYPEREF) {
-		expr = asn1f_lookup_symbol(arg, expr->module, expr->reference);
-		if(expr == NULL) return -1;
+		asn1p_expr_t *nexpr;
+		nexpr = asn1f_lookup_symbol(arg, expr->module, expr->reference);
+		if(nexpr == NULL) {
+			if(errno != EEXIST)	/* -fknown-extern-type */
+				return -1;
+			if(!count)
+				return 0;	/* OK */
+			if((*tags)[count-1].tag_mode == TM_IMPLICIT) {
+				WARNING("Tagging mode for %s "
+					"is IMPLICIT, assuming %s "
+					"has exactly one tag",
+					expr->Identifier,
+					asn1f_printable_reference(expr->reference)
+				);
+				return count;
+			}
+			FATAL("Tagging mode %s -> %s "
+				"dangerously incompatible",
+				expr->Identifier,
+				asn1f_printable_reference(expr->reference)
+			);
+			return -1;
+		} else {
+			arg->expr = nexpr;
+		}
 		if(expr->_mark & TM_RECURSION)
 			return -1;
-		arg->expr = expr;
 		expr->_mark |= TM_RECURSION;
 		count = asn1f_fetch_tags_impl(arg, tags, count, skip, flags);
 		expr->_mark &= ~TM_RECURSION;