inner structures tagging fix. see 0.9.5 comment in ChangeLog


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@311 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/asn1c/tests/check-25.c b/asn1c/tests/check-25.c
index eba3ddf..782fc86 100644
--- a/asn1c/tests/check-25.c
+++ b/asn1c/tests/check-25.c
@@ -15,7 +15,7 @@
 	2,	/* L */
   150,
   70,
-	/* b BOOLEAN */
+	/* b [2] IMPLICIT BOOLEAN */
 	128 | 2,		/* [2] */
 	1,	/* L */
   0xff,
@@ -26,30 +26,35 @@
 	10,			/* [UNIVERSAL 10] */
 	1,	/* L */
   222,
+	/* e OCTET STRING */
 	4,			/* [UNIVERSAL 4] */
 	3,	/* L */
 	'x',
 	'y',
 	'z',
-	/* f OCTET STRING */
-	32 | 4,			/* [UNIVERSAL 4], constructed */
+	/*
+	 * X.690 specifies that inner structures must be tagged by
+	 * stripping off the outer tag for each subsequent level.
+	 */
+	/* f [5] IMPLICIT VisibleString */
+	128 | 32 | 5,		/* [5], constructed */
 	128,	/* L indefinite */
-		4,		/* [UNIVERSAL 4], primitive */
+		26,	/* [UNIVERSAL 26] (VisibleString), primitive */
 		2,
   'l',
   'o',
-		32 | 4,		/* [UNIVERSAL 4], recursively constructed */
+		32 | 26,	/* [UNIVERSAL 26], recursively constructed */
 		128,
-			4,
+			4,	/* [UNIVERSAL 4] (OCTET STRING), primitive */
 			1,
   'v',
-			4,
+			4,	/* [UNIVERSAL 4], primitive */
 			2,
   'e',
   '_',
 		0,
 		0,
-		4,		/* [UNIVERSAL 4], primitive */
+		26,	/* [UNIVERSAL 26], primitive */
 		2,
   'i',
   't',
@@ -61,8 +66,8 @@
 	2,	/* Skip 2 bits */
 	147,
 	150,	/* => 148 */
-	/* h BIT STRING */
-	32 | 3,			/* [UNIVERSAL 3], constructed */
+	/* h [7] BIT STRING */
+	128 | 32 | 7,			/* [7], constructed */
 	128,	/* L indefinite */
 		3,			/* [UNIVERSAL 3], primitive */
 		3,	/* L */
@@ -73,7 +78,7 @@
 		2,	/* L */
 		1,	/* Skip 1 bit */
 		143,	/* => 142 */
-	0,	/* End of f */
+	0,	/* End of h */
 	0,
 	0,	/* End of the whole structure */
 	0,
diff --git a/libasn1compiler/asn1c_C.c b/libasn1compiler/asn1c_C.c
index c448795..485e990 100644
--- a/libasn1compiler/asn1c_C.c
+++ b/libasn1compiler/asn1c_C.c
@@ -29,9 +29,15 @@
 static int expr_better_indirect(arg_t *arg, asn1p_expr_t *expr);
 static int expr_elements_count(arg_t *arg, asn1p_expr_t *expr);
 static int emit_member_table(arg_t *arg, asn1p_expr_t *expr);
-static int emit_tags_vector(arg_t *arg, asn1p_expr_t *expr);
 static int emit_tag2member_map(arg_t *arg, tag2el_t *tag2el, int tag2el_count);
 
+enum tvm_compat {
+	_TVM_SAME	= 0,	/* tags and all_tags are same */
+	_TVM_SUBSET	= 1,	/* tags are subset of all_tags */
+	_TVM_DIFFERENT	= 2,	/* tags and all_tags are different */
+};
+static enum tvm_compat emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tc, int *atc);
+
 enum etd_cp {
 	ETD_CP_UNKNOWN		= -2,
 	ETD_CP_EITHER		= -1,
@@ -42,7 +48,7 @@
 	ETD_NO_SPECIFICS,
 	ETD_HAS_SPECIFICS
 };
-static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int elements_count, enum etd_cp, enum etd_spec);
+static int emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_count, int all_tags_count, int elements_count, enum etd_cp, enum etd_spec);
 
 #define	C99_MODE	(!(arg->flags & A1C_NO_C99))
 #define	UNNAMED_UNIONS	(arg->flags & A1C_UNNAMED_UNIONS)
@@ -175,6 +181,8 @@
 	tag2el_t *tag2el = NULL;
 	int tag2el_count = 0;
 	int tags_count;
+	int all_tags_count;
+	enum tvm_compat tv_mode;
 	char *p;
 
 	/*
@@ -212,9 +220,9 @@
 	OUT("};\n");
 
 	/*
-	 * Print out asn1_DEF_<type>_tags[] vector.
+	 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
 	 */
-	tags_count = emit_tags_vector(arg, expr);
+	tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
 
 	/*
 	 * Tags to elements map.
@@ -238,7 +246,7 @@
 	/*
 	 * Emit asn1_DEF_xxx table.
 	 */
-	emit_type_DEF(arg, expr, tags_count, elements,
+	emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
 			ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
 
 	REDIR(OT_TYPE_DECLS);
@@ -322,6 +330,8 @@
 	tag2el_t *tag2el = NULL;
 	int tag2el_count = 0;
 	int tags_count;
+	int all_tags_count;
+	enum tvm_compat tv_mode;
 	char *p;
 
 	/*
@@ -359,9 +369,9 @@
 	OUT("};\n");
 
 	/*
-	 * Print out asn1_DEF_<type>_tags[] vector.
+	 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
 	 */
-	tags_count = emit_tags_vector(arg, expr);
+	tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
 
 	/*
 	 * Tags to elements map.
@@ -417,7 +427,7 @@
 	/*
 	 * Emit asn1_DEF_xxx table.
 	 */
-	emit_type_DEF(arg, expr, tags_count, elements,
+	emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
 			ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
 
 	REDIR(OT_TYPE_DECLS);
@@ -483,6 +493,8 @@
 	asn1p_expr_t *expr = arg->expr;
 	asn1p_expr_t *v;
 	int tags_count;
+	int all_tags_count;
+	enum tvm_compat tv_mode;
 	char *p;
 
 	/*
@@ -511,9 +523,9 @@
 	OUT("};\n");
 
 	/*
-	 * Print out asn1_DEF_<type>_tags[] vector.
+	 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
 	 */
-	tags_count = emit_tags_vector(arg, expr);
+	tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
 
 	p = MKID(expr->Identifier);
 	OUT("static asn1_SET_OF_specifics_t asn1_DEF_%s_specs = {\n", p);
@@ -526,7 +538,7 @@
 	/*
 	 * Emit asn1_DEF_xxx table.
 	 */
-	emit_type_DEF(arg, expr, tags_count, 1,
+	emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 1,
 			ETD_CP_CONSTRUCTED, ETD_HAS_SPECIFICS);
 
 	REDIR(OT_TYPE_DECLS);
@@ -600,6 +612,8 @@
 	tag2el_t *tag2el = NULL;
 	int tag2el_count = 0;
 	int tags_count;
+	int all_tags_count;
+	enum tvm_compat tv_mode;
 	char *p;
 
 	/*
@@ -641,9 +655,11 @@
 		/*
 		 * Our parent structure has already taken this into account.
 		 */
-		tags_count = 0;
+		tv_mode = _TVM_SAME;
+		tags_count = all_tags_count = 0;
 	} else {
-		tags_count = emit_tags_vector(arg, expr);
+		tv_mode = emit_tags_vectors(arg, expr,
+			&tags_count, &all_tags_count);
 	}
 
 	/*
@@ -668,7 +684,7 @@
 	/*
 	 * Emit asn1_DEF_xxx table.
 	 */
-	emit_type_DEF(arg, expr, tags_count, elements,
+	emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, elements,
 			ETD_CP_CONSTRUCTED /*either?!*/, ETD_HAS_SPECIFICS);
 
 	REDIR(OT_TYPE_DECLS);
@@ -724,6 +740,8 @@
 asn1c_lang_C_type_SIMPLE_TYPE(arg_t *arg) {
 	asn1p_expr_t *expr = arg->expr;
 	int tags_count;
+	int all_tags_count;
+	enum tvm_compat tv_mode;
 	char *p;
 
 	if(arg->embed) {
@@ -754,11 +772,11 @@
 	REDIR(OT_STAT_DEFS);
 
 	/*
-	 * Print out asn1_DEF_<type>_tags[] vector.
+	 * Print out asn1_DEF_<type>_[all_]tags[] vectors.
 	 */
-	tags_count = emit_tags_vector(arg, expr);
+	tv_mode = emit_tags_vectors(arg, expr, &tags_count, &all_tags_count);
 
-	emit_type_DEF(arg, expr, tags_count, 0,
+	emit_type_DEF(arg, expr, tv_mode, tags_count, all_tags_count, 0,
 			ETD_CP_UNKNOWN, ETD_NO_SPECIFICS);
 
 	REDIR(OT_CODE);
@@ -816,9 +834,11 @@
 	OUT("td->free_struct    = asn1_DEF_%s.free_struct;\n",    type_name);
 	OUT("td->print_struct   = asn1_DEF_%s.print_struct;\n",   type_name);
 	if(!terminal && !tags_count) {
-	  OUT("/* The next two lines are because of -fknown-extern-type */\n");
+	  OUT("/* The next four lines are here because of -fknown-extern-type */\n");
 	  OUT("td->tags           = asn1_DEF_%s.tags;\n",         type_name);
 	  OUT("td->tags_count     = asn1_DEF_%s.tags_count;\n",   type_name);
+	  OUT("td->all_tags       = asn1_DEF_%s.all_tags;\n",     type_name);
+	  OUT("td->all_tags_count = asn1_DEF_%s.all_tags_count;\n",type_name);
 	  OUT("/* End of these lines */\n");
 	}
 	OUT("td->last_tag_form  = asn1_DEF_%s.last_tag_form;\n",  type_name);
@@ -1122,33 +1142,77 @@
 	return 0;;
 }
 
-static int
-emit_tags_vector(arg_t *arg, asn1p_expr_t *expr) {
-	struct asn1p_type_tag_s *tags = 0;
+static enum tvm_compat
+emit_tags_vectors(arg_t *arg, asn1p_expr_t *expr, int *tags_count_r, int *all_tags_count_r) {
+	struct asn1p_type_tag_s *tags = 0;	/* Effective tags */
+	struct asn1p_type_tag_s *all_tags = 0;	/* The full array */
 	int tags_count = 0;
+	int all_tags_count = 0;
+	enum tvm_compat tv_mode = _TVM_SAME;
 	int i;
 
 	/* Fetch a chain of tags */
 	tags_count = asn1f_fetch_tags(arg->asn, arg->mod, expr, &tags, 0);
-	if(tags_count <= 0)
-		return 0;
+	if(tags_count < 0) return -1;
 
-	OUT("static ber_tlv_tag_t asn1_DEF_%s_tags[] = {\n",
-		MKID(expr->Identifier));
-	INDENT(+1);
-
-	/* Print the array of collected tags */
-	for(i = 0; i < tags_count; i++) {
-		if(i) OUT(",\n");
-		_print_tag(arg, &tags[i]);
+	/* Fetch a chain of tags */
+	all_tags_count = asn1f_fetch_tags(arg->asn, arg->mod, expr,
+		&all_tags, AFT_FULL_COLLECT);
+	if(all_tags_count < 0) {
+		if(tags) free(tags);
+		return -1;
 	}
 
-	OUT("\n");
-	INDENT(-1);
-	OUT("};\n");
+	assert(tags_count <= all_tags_count);
+	assert((tags_count?0:1) == (all_tags_count?0:1));
 
-	free(tags);
-	return tags_count;
+	if(tags_count <= all_tags_count) {
+		for(i = 0; i < tags_count; i++) {
+			if(tags[i].tag_value != all_tags[i].tag_value
+			|| tags[i].tag_class != all_tags[i].tag_class) {
+				tv_mode = _TVM_DIFFERENT;
+				break;
+			}
+		}
+		if(i == tags_count && tags_count < all_tags_count)
+			tv_mode = _TVM_SUBSET;
+	} else {
+		tv_mode = _TVM_DIFFERENT;
+	}
+
+#define	EMIT_TAGS_TABLE(name, tags, tags_count)	do {			\
+		OUT("static ber_tlv_tag_t asn1_DEF_%s%s_tags[] = {\n",	\
+			MKID(expr->Identifier), name);			\
+		INDENT(+1);						\
+		/* Print the array of collected tags */			\
+		for(i = 0; i < tags_count; i++) {			\
+			if(i) OUT(",\n");				\
+			_print_tag(arg, &tags[i]);			\
+		}							\
+		OUT("\n");						\
+		INDENT(-1);						\
+		OUT("};\n");						\
+	} while(0)
+
+	if(tags_count) {
+		if(tv_mode == _TVM_SUBSET)
+			EMIT_TAGS_TABLE("", all_tags, all_tags_count);
+		else
+			EMIT_TAGS_TABLE("", tags, tags_count);
+	}
+
+	if(all_tags_count) {
+		if(tv_mode == _TVM_DIFFERENT)
+			EMIT_TAGS_TABLE("_all", all_tags, all_tags_count);
+	}
+
+	if(tags) free(tags);
+	if(all_tags) free(all_tags);
+
+	*tags_count_r = tags_count;
+	*all_tags_count_r = all_tags_count;
+
+	return tv_mode;
 }
 
 static int
@@ -1293,14 +1357,14 @@
 }
 
 static int
-emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, int tags_count, int elements_count, enum etd_cp cp, enum etd_spec spec) {
+emit_type_DEF(arg_t *arg, asn1p_expr_t *expr, enum tvm_compat tv_mode, int tags_count, int all_tags_count, int elements_count, enum etd_cp cp, enum etd_spec spec) {
 	char *p;
 
 	p = MKID(expr->Identifier);
 	if(HIDE_INNER_DEFS)
 		OUT("static /* Use -fall-defs-global to expose */\n");
 	OUT("asn1_TYPE_descriptor_t asn1_DEF_%s = {\n", p);
-	INDENTED(
+	INDENT(+1);
 		OUT("\"%s\",\n", expr->_anonymous_type?"":expr->Identifier);
 
 		if(expr->expr_type & ASN_CONSTR_MASK) {
@@ -1324,11 +1388,29 @@
 		if(tags_count) {
 			OUT("asn1_DEF_%s_tags,\n", p);
 			OUT("sizeof(asn1_DEF_%s_tags)\n", p);
-			OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
-				p, tags_count);
+			OUT("\t/sizeof(asn1_DEF_%s_tags[0])", p);
+			if(tv_mode == _TVM_SUBSET
+			&& tags_count != all_tags_count)
+				OUT(" - %d", all_tags_count - tags_count);
+			OUT(", /* %d */\n", tags_count);
 		} else {
-			OUT("0,\t/* No explicit tags (pointer) */\n");
-			OUT("0,\t/* No explicit tags (count) */\n");
+			OUT("0,\t/* No effective tags (pointer) */\n");
+			OUT("0,\t/* No effective tags (count) */\n");
+		}
+
+		if(all_tags_count && tv_mode == _TVM_DIFFERENT) {
+			OUT("asn1_DEF_%s_all_tags,\n", p);
+			OUT("sizeof(asn1_DEF_%s_all_tags)\n", p);
+			OUT("\t/sizeof(asn1_DEF_%s_all_tags[0]), /* %d */\n",
+				p, all_tags_count);
+		} else if(all_tags_count) {
+			OUT("asn1_DEF_%s_tags,\t/* Same as above */\n", p);
+			OUT("sizeof(asn1_DEF_%s_tags)\n", p);
+			OUT("\t/sizeof(asn1_DEF_%s_tags[0]), /* %d */\n",
+				p, all_tags_count);
+		} else {
+			OUT("0,\t/* No tags (pointer) */\n");
+			OUT("0,\t/* No tags (count) */\n");
 		}
 
 		switch(cp) {
@@ -1371,7 +1453,7 @@
 		case ETD_HAS_SPECIFICS:
 			OUT("&asn1_DEF_%s_specs\t/* Additional specs */\n", p);
 		}
-	);
+	INDENT(-1);
 	OUT("};\n");
 	OUT("\n");
 
diff --git a/libasn1fix/asn1fix_tags.c b/libasn1fix/asn1fix_tags.c
index 6d88798..ed08513 100644
--- a/libasn1fix/asn1fix_tags.c
+++ b/libasn1fix/asn1fix_tags.c
@@ -2,7 +2,7 @@
 
 #define	ADD_TAG(skip, newtag)	do {					\
 	void *__p;							\
-	if(skip) {							\
+	if(skip && !(flags & AFT_FULL_COLLECT)) {			\
 		if(newtag.tag_mode != TM_IMPLICIT)			\
 			skip--;						\
 		break;							\
diff --git a/libasn1fix/asn1fix_tags.h b/libasn1fix/asn1fix_tags.h
index 394c3e8..a4c31ad 100644
--- a/libasn1fix/asn1fix_tags.h
+++ b/libasn1fix/asn1fix_tags.h
@@ -4,6 +4,7 @@
 enum asn1f_aft_flags_e {
 	AFT_IMAGINARY_ANY	= 0x01,	/* Treat ANY tag as [IMAGINARY ANY] */
 	AFT_FETCH_OUTMOST	= 0x02,	/* Fetch only outmost tag */
+	AFT_FULL_COLLECT	= 0x04,	/* Collect all tags */
 };
 
 /*
diff --git a/skeletons/BIT_STRING.c b/skeletons/BIT_STRING.c
index 7f1aa09..a43a22a 100644
--- a/skeletons/BIT_STRING.c
+++ b/skeletons/BIT_STRING.c
@@ -21,6 +21,9 @@
 	asn1_DEF_BIT_STRING_tags,
 	sizeof(asn1_DEF_BIT_STRING_tags)
 	  / sizeof(asn1_DEF_BIT_STRING_tags[0]),
+	asn1_DEF_BIT_STRING_tags,	/* Same as above */
+	sizeof(asn1_DEF_BIT_STRING_tags)
+	  / sizeof(asn1_DEF_BIT_STRING_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	(void *)-1	/* Special indicator that this is a BIT STRING */
diff --git a/skeletons/BMPString.c b/skeletons/BMPString.c
index 87aacea..3e779cc 100644
--- a/skeletons/BMPString.c
+++ b/skeletons/BMPString.c
@@ -8,7 +8,8 @@
  * BMPString basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_BMPString_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (30 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (30 << 2)),	/* [UNIVERSAL 30] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_BMPString = {
 	"BMPString",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_BMPString_tags,
 	sizeof(asn1_DEF_BMPString_tags)
+	  / sizeof(asn1_DEF_BMPString_tags[0]) - 1,
+	asn1_DEF_BMPString_tags,
+	sizeof(asn1_DEF_BMPString_tags)
 	  / sizeof(asn1_DEF_BMPString_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/BOOLEAN.c b/skeletons/BOOLEAN.c
index b7b4795..5ba2e4f 100644
--- a/skeletons/BOOLEAN.c
+++ b/skeletons/BOOLEAN.c
@@ -19,7 +19,9 @@
 	BOOLEAN_free,
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_BOOLEAN_tags,
-	sizeof(asn1_DEF_BOOLEAN_tags)/sizeof(asn1_DEF_BOOLEAN_tags[0]),
+	sizeof(asn1_DEF_BOOLEAN_tags) / sizeof(asn1_DEF_BOOLEAN_tags[0]),
+	asn1_DEF_BOOLEAN_tags,	/* Same as above */
+	sizeof(asn1_DEF_BOOLEAN_tags) / sizeof(asn1_DEF_BOOLEAN_tags[0]),
 	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/skeletons/ENUMERATED.c b/skeletons/ENUMERATED.c
index 9c8db29..ed908b5 100644
--- a/skeletons/ENUMERATED.c
+++ b/skeletons/ENUMERATED.c
@@ -19,7 +19,9 @@
 	INTEGER_free,			/* Implemented in terms of INTEGER */
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_ENUMERATED_tags,
-	sizeof(asn1_DEF_ENUMERATED_tags)/sizeof(asn1_DEF_ENUMERATED_tags[0]),
+	sizeof(asn1_DEF_ENUMERATED_tags) / sizeof(asn1_DEF_ENUMERATED_tags[0]),
+	asn1_DEF_ENUMERATED_tags,	/* Same as above */
+	sizeof(asn1_DEF_ENUMERATED_tags) / sizeof(asn1_DEF_ENUMERATED_tags[0]),
 	0,	/* Primitive */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/skeletons/GeneralString.c b/skeletons/GeneralString.c
index feef7cc..dfca2ca 100644
--- a/skeletons/GeneralString.c
+++ b/skeletons/GeneralString.c
@@ -8,7 +8,8 @@
  * GeneralString basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_GeneralString_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (27 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (27 << 2)),	/* [UNIVERSAL 27] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_GeneralString = {
 	"GeneralString",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_GeneralString_tags,
 	sizeof(asn1_DEF_GeneralString_tags)
+	  / sizeof(asn1_DEF_GeneralString_tags[0]) - 1,
+	asn1_DEF_GeneralString_tags,
+	sizeof(asn1_DEF_GeneralString_tags)
 	  / sizeof(asn1_DEF_GeneralString_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index c66c314..6a89b2d 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -85,6 +85,9 @@
 	asn1_DEF_GeneralizedTime_tags,
 	sizeof(asn1_DEF_GeneralizedTime_tags)
 	  / sizeof(asn1_DEF_GeneralizedTime_tags[0]),
+	asn1_DEF_GeneralizedTime_tags,	/* Same as above */
+	sizeof(asn1_DEF_GeneralizedTime_tags)
+	  / sizeof(asn1_DEF_GeneralizedTime_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/skeletons/GraphicString.c b/skeletons/GraphicString.c
index f6d0ae9..ceb247d 100644
--- a/skeletons/GraphicString.c
+++ b/skeletons/GraphicString.c
@@ -8,7 +8,8 @@
  * GraphicString basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_GraphicString_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (25 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (25 << 2)),	/* [UNIVERSAL 25] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_GraphicString = {
 	"GraphicString",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_GraphicString_tags,
 	sizeof(asn1_DEF_GraphicString_tags)
+	  / sizeof(asn1_DEF_GraphicString_tags[0]) - 1,
+	asn1_DEF_GraphicString_tags,
+	sizeof(asn1_DEF_GraphicString_tags)
 	  / sizeof(asn1_DEF_GraphicString_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/IA5String.c b/skeletons/IA5String.c
index 33f38a6..9fc308b 100644
--- a/skeletons/IA5String.c
+++ b/skeletons/IA5String.c
@@ -8,7 +8,8 @@
  * IA5String basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_IA5String_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (22 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (22 << 2)),	/* [UNIVERSAL 22] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_IA5String = {
 	"IA5String",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_IA5String_tags,
 	sizeof(asn1_DEF_IA5String_tags)
+	  / sizeof(asn1_DEF_IA5String_tags[0]) - 1,
+	asn1_DEF_IA5String_tags,
+	sizeof(asn1_DEF_IA5String_tags)
 	  / sizeof(asn1_DEF_IA5String_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index 14e91c6..5bfcf1f 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -21,7 +21,9 @@
 	INTEGER_free,
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_INTEGER_tags,
-	sizeof(asn1_DEF_INTEGER_tags)/sizeof(asn1_DEF_INTEGER_tags[0]),
+	sizeof(asn1_DEF_INTEGER_tags) / sizeof(asn1_DEF_INTEGER_tags[0]),
+	asn1_DEF_INTEGER_tags,	/* Same as above */
+	sizeof(asn1_DEF_INTEGER_tags) / sizeof(asn1_DEF_INTEGER_tags[0]),
 	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/skeletons/ISO646String.c b/skeletons/ISO646String.c
index 7ce5496..8a99cbc 100644
--- a/skeletons/ISO646String.c
+++ b/skeletons/ISO646String.c
@@ -8,7 +8,8 @@
  * ISO646String basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_ISO646String_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (26 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)),	/* [UNIVERSAL 26] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_ISO646String = {
 	"ISO646String",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_ISO646String_tags,
 	sizeof(asn1_DEF_ISO646String_tags)
+	  / sizeof(asn1_DEF_ISO646String_tags[0]) - 1,
+	asn1_DEF_ISO646String_tags,
+	sizeof(asn1_DEF_ISO646String_tags)
 	  / sizeof(asn1_DEF_ISO646String_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/NULL.c b/skeletons/NULL.c
index 42afa7e..36796b8 100644
--- a/skeletons/NULL.c
+++ b/skeletons/NULL.c
@@ -20,7 +20,9 @@
 	BOOLEAN_free,
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_NULL_tags,
-	sizeof(asn1_DEF_NULL_tags)/sizeof(asn1_DEF_NULL_tags[0]),
+	sizeof(asn1_DEF_NULL_tags) / sizeof(asn1_DEF_NULL_tags[0]),
+	asn1_DEF_NULL_tags,	/* Same as above */
+	sizeof(asn1_DEF_NULL_tags) / sizeof(asn1_DEF_NULL_tags[0]),
 	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/skeletons/NativeEnumerated.c b/skeletons/NativeEnumerated.c
index 9c4fd8f..53ce501 100644
--- a/skeletons/NativeEnumerated.c
+++ b/skeletons/NativeEnumerated.c
@@ -26,7 +26,9 @@
 	NativeInteger_free,
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_NativeEnumerated_tags,
-	sizeof(asn1_DEF_NativeEnumerated_tags)/sizeof(asn1_DEF_NativeEnumerated_tags[0]),
+	sizeof(asn1_DEF_NativeEnumerated_tags) / sizeof(asn1_DEF_NativeEnumerated_tags[0]),
+	asn1_DEF_NativeEnumerated_tags,	/* Same as above */
+	sizeof(asn1_DEF_NativeEnumerated_tags) / sizeof(asn1_DEF_NativeEnumerated_tags[0]),
 	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c
index 60321cc..98fee96 100644
--- a/skeletons/NativeInteger.c
+++ b/skeletons/NativeInteger.c
@@ -28,7 +28,9 @@
 	NativeInteger_free,
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_NativeInteger_tags,
-	sizeof(asn1_DEF_NativeInteger_tags)/sizeof(asn1_DEF_NativeInteger_tags[0]),
+	sizeof(asn1_DEF_NativeInteger_tags) / sizeof(asn1_DEF_NativeInteger_tags[0]),
+	asn1_DEF_NativeInteger_tags,	/* Same as above */
+	sizeof(asn1_DEF_NativeInteger_tags) / sizeof(asn1_DEF_NativeInteger_tags[0]),
 	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/skeletons/NumericString.c b/skeletons/NumericString.c
index a70bb5d..a23e39f 100644
--- a/skeletons/NumericString.c
+++ b/skeletons/NumericString.c
@@ -8,7 +8,8 @@
  * NumericString basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_NumericString_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (18 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (18 << 2)),	/* [UNIVERSAL 18] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_NumericString = {
 	"NumericString",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_NumericString_tags,
 	sizeof(asn1_DEF_NumericString_tags)
+	  / sizeof(asn1_DEF_NumericString_tags[0]) - 1,
+	asn1_DEF_NumericString_tags,
+	sizeof(asn1_DEF_NumericString_tags)
 	  / sizeof(asn1_DEF_NumericString_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index a44349e..c55410d 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -24,6 +24,9 @@
 	asn1_DEF_OBJECT_IDENTIFIER_tags,
 	sizeof(asn1_DEF_OBJECT_IDENTIFIER_tags)
 	    / sizeof(asn1_DEF_OBJECT_IDENTIFIER_tags[0]),
+	asn1_DEF_OBJECT_IDENTIFIER_tags,	/* Same as above */
+	sizeof(asn1_DEF_OBJECT_IDENTIFIER_tags)
+	    / sizeof(asn1_DEF_OBJECT_IDENTIFIER_tags[0]),
 	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -98,7 +101,7 @@
 
 int
 OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbuf, unsigned int rvsize) {
-	unsigned LE = 1;	/* Little endian (x86) */
+	unsigned LE __attribute__ ((unused)) = 1; /* Little endian (x86) */
 	uint8_t *arcend = arcbuf + arclen;	/* End of arc */
 	void *rvstart = rvbuf;	/* Original start of the value buffer */
 	unsigned int cache = 0;	/* No more than 14 significant bits */
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index 6589334..e0af730 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #include <OCTET_STRING.h>
@@ -23,6 +23,9 @@
 	asn1_DEF_OCTET_STRING_tags,
 	sizeof(asn1_DEF_OCTET_STRING_tags)
 	  / sizeof(asn1_DEF_OCTET_STRING_tags[0]),
+	asn1_DEF_OCTET_STRING_tags,	/* Same as above */
+	sizeof(asn1_DEF_OCTET_STRING_tags)
+	  / sizeof(asn1_DEF_OCTET_STRING_tags[0]),
 	-1,	/* Both ways are fine (primitive and constructed) */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -54,6 +57,7 @@
 		size_t _ns = ctx->step;	/* Allocated */			\
 		if(_ns <= (size_t)(st->size + _bs)) {			\
 			void *ptr;					\
+			/* Be nice and round to the memory allocator */	\
 			do { _ns = _ns ? _ns<<2 : 16; }			\
 			    while(_ns <= (size_t)(st->size + _bs));	\
 			ptr = REALLOC(st->buf, _ns);			\
@@ -81,6 +85,7 @@
  */
 struct _stack_el {
 	ber_tlv_len_t	left;	/* What's left to read */
+	int	cont_level;	/* Depth of subcontainment */
 	int	want_nulls;	/* Want null "end of content" octets? */
 	int	bits_chopped;	/* Flag in BIT STRING mode */
 	struct _stack_el *prev;
@@ -95,17 +100,23 @@
 _add_stack_el(struct _stack *st) {
 	struct _stack_el *nel;
 
+	/*
+	 * Reuse the old stack frame or allocate a new one.
+	 */
 	if(st->cur_ptr && st->cur_ptr->next) {
 		nel = st->cur_ptr->next;
 		nel->left = 0;
 		nel->want_nulls = 0;
 		nel->bits_chopped = 0;
+		/* Retain nel->cont_level, it's correct. */
 	} else {
 		(void *)nel = CALLOC(1, sizeof(struct _stack_el));
 		if(nel == NULL)
 			return NULL;
 	
 		if(st->tail) {
+			/* Increase a subcontainment depth */
+			nel->cont_level = st->tail->cont_level + 1;
 			st->tail->next = nel;
 		}
 		nel->prev = st->tail;
@@ -136,13 +147,16 @@
 	OCTET_STRING_t *st = (OCTET_STRING_t *)*os_structure;
 	ber_dec_rval_t rval;
 	ber_dec_ctx_t *ctx;
-	ber_tlv_tag_t terminal_tag;	/* Inner tag for constructed types */
 	ssize_t consumed_myself = 0;
 	struct _stack *stck;	/* A stack structure */
 	struct _stack_el *sel;	/* Stack element */
 	int tlv_constr;
-	int is_bit_str = 0;	/* See below under switch(td->specifics) */
-	int is_ANY_type = 0;	/* See below under switch(td->specifics) */
+	enum type_type_e {
+		_TT_GENERIC	= 0,	/* Just a random OCTET STRING */
+		_TT_BIT_STRING	= -1,	/* BIT STRING type, a special case */
+		_TT_ANY		= 1,	/* ANY type, a special case too */
+	} type_type
+		= (enum type_type_e)(int)td->specifics;	/* An ugly hack */
 
 	ASN_DEBUG("Decoding %s as %s (%ld)",
 		td->name, "OCTET STRING", (long)size);
@@ -159,25 +173,6 @@
 	/* Restore parsing context */
 	ctx = &st->_ber_dec_ctx;
 
-	switch((int)td->specifics) {
-	case 0:
-		terminal_tag = asn1_DEF_OCTET_STRING_tags[0];	/* [U4] */
-		break;
-	case -1:	/* BIT STRING */
-		/*
-		 * This is some sort of a hack.
-		 * The OCTET STRING decoder is being used in BIT STRING mode.
-		 */
-		is_bit_str = 1;
-		terminal_tag = ASN_TAG_CLASS_UNIVERSAL | (3 << 2);
-		break;
-	default:	/* Just in case; fall through */
-	case  1:	/* ANY type */
-		is_ANY_type = 1;
-		terminal_tag = -1;
-		break;
-	}
-
 	switch(ctx->phase) {
 	case 0:
 		/*
@@ -212,7 +207,7 @@
 					stck->cur_ptr->left,
 					stck->cur_ptr->want_nulls);
 #endif
-				if(is_bit_str) {
+				if(type_type == _TT_BIT_STRING) {
 					/* Number of meaningless tail bits */
 					APPEND("\0", 1);
 				}
@@ -224,7 +219,8 @@
 			 * Jump into stackless primitive decoding.
 			 */
 			_CH_PHASE(ctx, 3);
-			if(is_ANY_type) APPEND(buf_ptr, rval.consumed);
+			if(type_type == _TT_ANY)
+				APPEND(buf_ptr, rval.consumed);
 			ADVANCE(rval.consumed);
 			goto phase3;
 		}
@@ -241,6 +237,7 @@
 	  do {
 		ber_tlv_tag_t tlv_tag;
 		ber_tlv_len_t tlv_len;
+		ber_tlv_tag_t expected_tag;
 		ssize_t tl, ll;
 
 		ASN_DEBUG("fetch tag(size=%d), %sstack, left=%d, want0=%d",
@@ -271,7 +268,7 @@
 			&& ((uint8_t *)buf_ptr)[1] == 0)
 		{
 			ADVANCE(2);
-			if(is_ANY_type) APPEND("\0\0", 2);
+			if(type_type == _TT_ANY) APPEND("\0\0", 2);
 
 			ASN_DEBUG("Eat EOC; wn=%d--", sel->want_nulls);
 
@@ -294,8 +291,38 @@
 			}
 
 			continue;
-		} else if(tlv_tag != terminal_tag
-				&& terminal_tag != (ber_tlv_tag_t)-1) {
+		}
+
+		/*
+		 * Set up expected tags,
+		 * depending on ASN.1 type being decoded.
+		 */
+		switch(type_type) {
+		case _TT_BIT_STRING:
+			/* X.690: 8.6.4.1, NOTE 2 */
+			/* Fall through */
+		case _TT_GENERIC:
+		default:
+			if(sel) {
+				int level = sel->cont_level;
+				if(level < td->all_tags_count) {
+					expected_tag = td->all_tags[level];
+					break;
+				} else if(td->all_tags_count) {
+					expected_tag = td->all_tags
+						[td->all_tags_count - 1];
+					break;
+				}
+				/* else, Fall through */
+			}
+			/* Fall through */
+		case _TT_ANY:
+			expected_tag = tlv_tag;
+			break;
+		}
+
+
+		if(tlv_tag != expected_tag) {
 			char buf[2][32];
 			ber_tlv_tag_snprint(tlv_tag,
 				buf[0], sizeof(buf[0]));
@@ -313,17 +340,18 @@
 		if(sel) {
 			sel->want_nulls = (tlv_len==-1);
 			sel->left = tlv_len;
-			ASN_DEBUG("+EXPECT2 left=%d wn=%d",
-				sel->left, sel->want_nulls);
+			ASN_DEBUG("+EXPECT2 left=%d wn=%d, clvl=%d",
+				sel->left, sel->want_nulls, sel->cont_level);
 		} else {
 			RETURN(RC_FAIL);
 		}
 
-		if(is_ANY_type) APPEND(buf_ptr, tl + ll);
+		if(type_type == _TT_ANY) APPEND(buf_ptr, tl + ll);
 		ADVANCE(tl+ll);
 	  } while(tlv_constr);
 		if(sel == NULL) {
 			/* Finished operation, "phase out" */
+			ASN_DEBUG("Phase out");
 			_CH_PHASE(ctx, +3);
 			break;
 		}
@@ -343,7 +371,8 @@
 		len = ((ber_tlv_len_t)size < sel->left)
 				? (ber_tlv_len_t)size : sel->left;
 		if(len > 0) {
-			if(is_bit_str && sel->bits_chopped == 0) {
+			if(type_type == _TT_BIT_STRING
+			&& sel->bits_chopped == 0) {
 				/*
 				 * Finalize the previous chunk:
 				 * strip down unused bits.
@@ -394,7 +423,7 @@
 	/*
 	 * BIT STRING-specific processing.
 	 */
-	if(is_bit_str && st->size >= 2) {
+	if(type_type == _TT_BIT_STRING && st->size >= 2) {
 		/* Finalize BIT STRING: zero out unused bits. */
 		st->buf[st->size-1] &= 0xff << st->buf[0];
 	}
diff --git a/skeletons/ObjectDescriptor.c b/skeletons/ObjectDescriptor.c
index 1f82e2b..5017918 100644
--- a/skeletons/ObjectDescriptor.c
+++ b/skeletons/ObjectDescriptor.c
@@ -8,7 +8,8 @@
  * ObjectDescriptor basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_ObjectDescriptor_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (7 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (7 << 2)),	/* [UNIVERSAL 7] IMPLICIT ... */
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_ObjectDescriptor = {
 	"ObjectDescriptor",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_ObjectDescriptor_tags,
 	sizeof(asn1_DEF_ObjectDescriptor_tags)
+	  / sizeof(asn1_DEF_ObjectDescriptor_tags[0]) - 1,
+	asn1_DEF_ObjectDescriptor_tags,
+	sizeof(asn1_DEF_ObjectDescriptor_tags)
 	  / sizeof(asn1_DEF_ObjectDescriptor_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/PrintableString.c b/skeletons/PrintableString.c
index 89cbf8d..c37de49 100644
--- a/skeletons/PrintableString.c
+++ b/skeletons/PrintableString.c
@@ -8,7 +8,8 @@
  * PrintableString basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_PrintableString_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (19 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (19 << 2)),	/* [UNIVERSAL 19] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_PrintableString = {
 	"PrintableString",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_PrintableString_tags,
 	sizeof(asn1_DEF_PrintableString_tags)
+	  / sizeof(asn1_DEF_PrintableString_tags[0]) - 1,
+	asn1_DEF_PrintableString_tags,
+	sizeof(asn1_DEF_PrintableString_tags)
 	  / sizeof(asn1_DEF_PrintableString_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c
index f1948f8..bee795c 100644
--- a/skeletons/RELATIVE-OID.c
+++ b/skeletons/RELATIVE-OID.c
@@ -24,6 +24,9 @@
 	asn1_DEF_RELATIVE_OID_tags,
 	sizeof(asn1_DEF_RELATIVE_OID_tags)
 	    / sizeof(asn1_DEF_RELATIVE_OID_tags[0]),
+	asn1_DEF_RELATIVE_OID_tags,	/* Same as above */
+	sizeof(asn1_DEF_RELATIVE_OID_tags)
+	    / sizeof(asn1_DEF_RELATIVE_OID_tags[0]),
 	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/skeletons/T61String.c b/skeletons/T61String.c
index 5226374..b306a5b 100644
--- a/skeletons/T61String.c
+++ b/skeletons/T61String.c
@@ -8,7 +8,8 @@
  * T61String basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_T61String_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (20 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (20 << 2)),	/* [UNIVERSAL 20] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_T61String = {
 	"T61String",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_T61String_tags,
 	sizeof(asn1_DEF_T61String_tags)
+	  / sizeof(asn1_DEF_T61String_tags[0]) - 1,
+	asn1_DEF_T61String_tags,
+	sizeof(asn1_DEF_T61String_tags)
 	  / sizeof(asn1_DEF_T61String_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/TeletexString.c b/skeletons/TeletexString.c
index b46caed..09f3eb6 100644
--- a/skeletons/TeletexString.c
+++ b/skeletons/TeletexString.c
@@ -8,7 +8,8 @@
  * TeletexString basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_TeletexString_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (20 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (20 << 2)),	/* [UNIVERSAL 20] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)),	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_TeletexString = {
 	"TeletexString",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_TeletexString_tags,
 	sizeof(asn1_DEF_TeletexString_tags)
+	  / sizeof(asn1_DEF_TeletexString_tags[0]) - 1,
+	asn1_DEF_TeletexString_tags,
+	sizeof(asn1_DEF_TeletexString_tags)
 	  / sizeof(asn1_DEF_TeletexString_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/UTCTime.c b/skeletons/UTCTime.c
index c574e4e..029a43e 100644
--- a/skeletons/UTCTime.c
+++ b/skeletons/UTCTime.c
@@ -27,6 +27,9 @@
 	asn1_DEF_UTCTime_tags,
 	sizeof(asn1_DEF_UTCTime_tags)
 	  / sizeof(asn1_DEF_UTCTime_tags[0]),
+	asn1_DEF_UTCTime_tags,	/* Same as above */
+	sizeof(asn1_DEF_UTCTime_tags)
+	  / sizeof(asn1_DEF_UTCTime_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/skeletons/UTF8String.c b/skeletons/UTF8String.c
index 384600a..40fef39 100644
--- a/skeletons/UTF8String.c
+++ b/skeletons/UTF8String.c
@@ -8,7 +8,8 @@
  * UTF8String basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_UTF8String_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (12 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (12 << 2)),	/* [UNIVERSAL 12] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2)),	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_UTF8String = {
 	"UTF8String",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_UTF8String_tags,
 	sizeof(asn1_DEF_UTF8String_tags)
+	  / sizeof(asn1_DEF_UTF8String_tags[0]) - 1,
+	asn1_DEF_UTF8String_tags,
+	sizeof(asn1_DEF_UTF8String_tags)
 	  / sizeof(asn1_DEF_UTF8String_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/UniversalString.c b/skeletons/UniversalString.c
index 35e7bea..1498896 100644
--- a/skeletons/UniversalString.c
+++ b/skeletons/UniversalString.c
@@ -8,7 +8,8 @@
  * UniversalString basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_UniversalString_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (28 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (28 << 2)),	/* [UNIVERSAL 28] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_UniversalString = {
 	"UniversalString",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_UniversalString_tags,
 	sizeof(asn1_DEF_UniversalString_tags)
+	  / sizeof(asn1_DEF_UniversalString_tags[0]) - 1,
+	asn1_DEF_UniversalString_tags,
+	sizeof(asn1_DEF_UniversalString_tags)
 	  / sizeof(asn1_DEF_UniversalString_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/VideotexString.c b/skeletons/VideotexString.c
index 772c66c..6d2eaeb 100644
--- a/skeletons/VideotexString.c
+++ b/skeletons/VideotexString.c
@@ -8,7 +8,8 @@
  * VideotexString basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_VideotexString_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (21 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (21 << 2)),	/* [UNIVERSAL 21] IMPLICIT */
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_VideotexString = {
 	"VideotexString",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_VideotexString_tags,
 	sizeof(asn1_DEF_VideotexString_tags)
+	  / sizeof(asn1_DEF_VideotexString_tags[0]) - 1,
+	asn1_DEF_VideotexString_tags,
+	sizeof(asn1_DEF_VideotexString_tags)
 	  / sizeof(asn1_DEF_VideotexString_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/VisibleString.c b/skeletons/VisibleString.c
index 18a27fa..9ddb0f1 100644
--- a/skeletons/VisibleString.c
+++ b/skeletons/VisibleString.c
@@ -8,7 +8,8 @@
  * VisibleString basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_VisibleString_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (26 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)),	/* [UNIVERSAL 26] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))	/* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_VisibleString = {
 	"VisibleString",
@@ -20,6 +21,9 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_VisibleString_tags,
 	sizeof(asn1_DEF_VisibleString_tags)
+	  / sizeof(asn1_DEF_VisibleString_tags[0]) - 1,
+	asn1_DEF_VisibleString_tags,
+	sizeof(asn1_DEF_VisibleString_tags)
 	  / sizeof(asn1_DEF_VisibleString_tags[0]),
 	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h
index 1918b5c..15a6726 100644
--- a/skeletons/constr_TYPE.h
+++ b/skeletons/constr_TYPE.h
@@ -70,10 +70,13 @@
 	asn_outmost_tag_f  *outmost_tag;	/* <optional, internal> */
 
 	/*
-	 * Tags that are expected, with some of their vital properties.
+	 * Tags that are expected to occur.
 	 */
-	ber_tlv_tag_t *tags;	/* At least one tag must be specified */
+	ber_tlv_tag_t *tags;	/* Effective tags sequence for this type */
 	int tags_count;		/* Number of tags which are expected */
+	ber_tlv_tag_t *all_tags;/* Every tag for BER/containment */
+	int all_tags_count;	/* Number of tags */
+
 	int last_tag_form;	/* Acceptable form of the tag (prim, constr) */
 
 	/*
@@ -92,12 +95,13 @@
 /*
  * An element of the constructed type, i.e. SEQUENCE, SET, CHOICE.
  */
+  enum asn1_TYPE_flags_e {
+	ATF_NOFLAGS,
+	ATF_POINTER	= 0x01,	/* Represented by the pointer */
+	ATF_OPEN_TYPE	= 0x02,	/* ANY type, without meaningful tag */
+  };
 typedef struct asn1_TYPE_member_s {
-	enum asn1_TYPE_flags_e {
-		ATF_NOFLAGS,
-		ATF_POINTER	= 0x01,	/* Represented by the pointer */
-		ATF_OPEN_TYPE	= 0x02,	/* ANY type, without meaningful tag */
-	} flags;			/* Element's presentation flags */
+	enum asn1_TYPE_flags_e flags;	/* Element's presentation flags */
 	int optional;	/* Following optional members, including current */
 	int memb_offset;		/* Offset of the element */
 	ber_tlv_tag_t tag;		/* Outmost (most immediate) tag */
diff --git a/tests/19-param-OK.asn1.-P b/tests/19-param-OK.asn1.-P
index bed6a5f..83be07d 100644
--- a/tests/19-param-OK.asn1.-P
+++ b/tests/19-param-OK.asn1.-P
@@ -117,6 +117,9 @@
 	asn1_DEF_toBeSigned_tags,
 	sizeof(asn1_DEF_toBeSigned_tags)
 		/sizeof(asn1_DEF_toBeSigned_tags[0]), /* 1 */
+	asn1_DEF_toBeSigned_tags,	/* Same as above */
+	sizeof(asn1_DEF_toBeSigned_tags)
+		/sizeof(asn1_DEF_toBeSigned_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_toBeSigned,
 	3,	/* Elements count */
@@ -173,6 +176,9 @@
 	asn1_DEF_Certificate_tags,
 	sizeof(asn1_DEF_Certificate_tags)
 		/sizeof(asn1_DEF_Certificate_tags[0]), /* 1 */
+	asn1_DEF_Certificate_tags,	/* Same as above */
+	sizeof(asn1_DEF_Certificate_tags)
+		/sizeof(asn1_DEF_Certificate_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_Certificate,
 	3,	/* Elements count */
@@ -229,6 +235,9 @@
 	asn1_DEF_Name_tags,
 	sizeof(asn1_DEF_Name_tags)
 		/sizeof(asn1_DEF_Name_tags[0]), /* 1 */
+	asn1_DEF_Name_tags,	/* Same as above */
+	sizeof(asn1_DEF_Name_tags)
+		/sizeof(asn1_DEF_Name_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_Name,
 	1,	/* Single element */
@@ -340,6 +349,9 @@
 	asn1_DEF_RelativeDistinguishedName_tags,
 	sizeof(asn1_DEF_RelativeDistinguishedName_tags)
 		/sizeof(asn1_DEF_RelativeDistinguishedName_tags[0]), /* 1 */
+	asn1_DEF_RelativeDistinguishedName_tags,	/* Same as above */
+	sizeof(asn1_DEF_RelativeDistinguishedName_tags)
+		/sizeof(asn1_DEF_RelativeDistinguishedName_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_RelativeDistinguishedName,
 	1,	/* Single element */
diff --git a/tests/25-misc-OK.asn1 b/tests/25-misc-OK.asn1
index 3a7eb91..43487de 100644
--- a/tests/25-misc-OK.asn1
+++ b/tests/25-misc-OK.asn1
@@ -20,9 +20,9 @@
 				a(1), b(2)
 				},
 		e	OCTET STRING,
-		f 	OCTET STRING,
+		f [5]	VisibleString,
 		g	BIT STRING,
-		h	BIT STRING,
+		h [7]	BIT STRING,
 		...
 	}
 
diff --git a/tests/31-set-of-OK.asn1.-P b/tests/31-set-of-OK.asn1.-P
index e28455a..7728121 100644
--- a/tests/31-set-of-OK.asn1.-P
+++ b/tests/31-set-of-OK.asn1.-P
@@ -48,6 +48,9 @@
 	asn1_DEF_Forest_tags,
 	sizeof(asn1_DEF_Forest_tags)
 		/sizeof(asn1_DEF_Forest_tags[0]), /* 1 */
+	asn1_DEF_Forest_tags,	/* Same as above */
+	sizeof(asn1_DEF_Forest_tags)
+		/sizeof(asn1_DEF_Forest_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_Forest,
 	1,	/* Single element */
@@ -119,6 +122,9 @@
 	asn1_DEF_Tree_tags,
 	sizeof(asn1_DEF_Tree_tags)
 		/sizeof(asn1_DEF_Tree_tags[0]), /* 1 */
+	asn1_DEF_Tree_tags,	/* Same as above */
+	sizeof(asn1_DEF_Tree_tags)
+		/sizeof(asn1_DEF_Tree_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_Tree,
 	2,	/* Elements count */
@@ -193,7 +199,8 @@
 		},
 };
 static ber_tlv_tag_t asn1_DEF_trees_tags[] = {
-	(ASN_TAG_CLASS_CONTEXT | (0 << 2))
+	(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
 };
 static asn1_SET_OF_specifics_t asn1_DEF_trees_specs = {
 	sizeof(struct trees),
@@ -210,7 +217,10 @@
 	0,	/* Use generic outmost tag fetcher */
 	asn1_DEF_trees_tags,
 	sizeof(asn1_DEF_trees_tags)
-		/sizeof(asn1_DEF_trees_tags[0]), /* 1 */
+		/sizeof(asn1_DEF_trees_tags[0]) - 1, /* 1 */
+	asn1_DEF_trees_tags,	/* Same as above */
+	sizeof(asn1_DEF_trees_tags)
+		/sizeof(asn1_DEF_trees_tags[0]), /* 2 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_trees,
 	1,	/* Single element */
@@ -252,6 +262,9 @@
 	asn1_DEF_anything_member_tags,
 	sizeof(asn1_DEF_anything_member_tags)
 		/sizeof(asn1_DEF_anything_member_tags[0]), /* 1 */
+	asn1_DEF_anything_member_tags,	/* Same as above */
+	sizeof(asn1_DEF_anything_member_tags)
+		/sizeof(asn1_DEF_anything_member_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_anything_member,
 	1,	/* Elements count */
@@ -268,7 +281,8 @@
 		},
 };
 static ber_tlv_tag_t asn1_DEF_anything_tags[] = {
-	(ASN_TAG_CLASS_CONTEXT | (1 << 2))
+	(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
 };
 static asn1_SET_OF_specifics_t asn1_DEF_anything_specs = {
 	sizeof(struct anything),
@@ -285,7 +299,10 @@
 	0,	/* Use generic outmost tag fetcher */
 	asn1_DEF_anything_tags,
 	sizeof(asn1_DEF_anything_tags)
-		/sizeof(asn1_DEF_anything_tags[0]), /* 1 */
+		/sizeof(asn1_DEF_anything_tags[0]) - 1, /* 1 */
+	asn1_DEF_anything_tags,	/* Same as above */
+	sizeof(asn1_DEF_anything_tags)
+		/sizeof(asn1_DEF_anything_tags[0]), /* 2 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_anything,
 	1,	/* Single element */
@@ -338,6 +355,9 @@
 	asn1_DEF_Stuff_tags,
 	sizeof(asn1_DEF_Stuff_tags)
 		/sizeof(asn1_DEF_Stuff_tags[0]), /* 1 */
+	asn1_DEF_Stuff_tags,	/* Same as above */
+	sizeof(asn1_DEF_Stuff_tags)
+		/sizeof(asn1_DEF_Stuff_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_Stuff,
 	2,	/* Elements count */
diff --git a/tests/39-sequence-of-OK.asn1.-P b/tests/39-sequence-of-OK.asn1.-P
index a1f622b..81ac16d 100644
--- a/tests/39-sequence-of-OK.asn1.-P
+++ b/tests/39-sequence-of-OK.asn1.-P
@@ -57,6 +57,9 @@
 	asn1_DEF_collection_tags,
 	sizeof(asn1_DEF_collection_tags)
 		/sizeof(asn1_DEF_collection_tags[0]), /* 1 */
+	asn1_DEF_collection_tags,	/* Same as above */
+	sizeof(asn1_DEF_collection_tags)
+		/sizeof(asn1_DEF_collection_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_collection,
 	1,	/* Single element */
@@ -105,6 +108,9 @@
 	asn1_DEF_T_tags,
 	sizeof(asn1_DEF_T_tags)
 		/sizeof(asn1_DEF_T_tags[0]), /* 1 */
+	asn1_DEF_T_tags,	/* Same as above */
+	sizeof(asn1_DEF_T_tags)
+		/sizeof(asn1_DEF_T_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_T,
 	2,	/* Elements count */
@@ -177,6 +183,9 @@
 	asn1_DEF_T2_tags,
 	sizeof(asn1_DEF_T2_tags)
 		/sizeof(asn1_DEF_T2_tags[0]), /* 1 */
+	asn1_DEF_T2_tags,	/* Same as above */
+	sizeof(asn1_DEF_T2_tags)
+		/sizeof(asn1_DEF_T2_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_T2,
 	2,	/* Elements count */
diff --git a/tests/42-real-life-OK.asn1.-PR b/tests/42-real-life-OK.asn1.-PR
index 385dcb9..262bacc 100644
--- a/tests/42-real-life-OK.asn1.-PR
+++ b/tests/42-real-life-OK.asn1.-PR
@@ -93,6 +93,9 @@
 	asn1_DEF_varsets_tags,
 	sizeof(asn1_DEF_varsets_tags)
 		/sizeof(asn1_DEF_varsets_tags[0]), /* 1 */
+	asn1_DEF_varsets_tags,	/* Same as above */
+	sizeof(asn1_DEF_varsets_tags)
+		/sizeof(asn1_DEF_varsets_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_varsets,
 	1,	/* Single element */
@@ -141,6 +144,9 @@
 	asn1_DEF_LogLine_tags,
 	sizeof(asn1_DEF_LogLine_tags)
 		/sizeof(asn1_DEF_LogLine_tags[0]), /* 1 */
+	asn1_DEF_LogLine_tags,	/* Same as above */
+	sizeof(asn1_DEF_LogLine_tags)
+		/sizeof(asn1_DEF_LogLine_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_LogLine,
 	2,	/* Elements count */
@@ -233,6 +239,9 @@
 	asn1_DEF_vparts_tags,
 	sizeof(asn1_DEF_vparts_tags)
 		/sizeof(asn1_DEF_vparts_tags[0]), /* 1 */
+	asn1_DEF_vparts_tags,	/* Same as above */
+	sizeof(asn1_DEF_vparts_tags)
+		/sizeof(asn1_DEF_vparts_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_vparts,
 	1,	/* Single element */
@@ -281,6 +290,9 @@
 	asn1_DEF_VariablePartSet_tags,
 	sizeof(asn1_DEF_VariablePartSet_tags)
 		/sizeof(asn1_DEF_VariablePartSet_tags[0]), /* 1 */
+	asn1_DEF_VariablePartSet_tags,	/* Same as above */
+	sizeof(asn1_DEF_VariablePartSet_tags)
+		/sizeof(asn1_DEF_VariablePartSet_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_VariablePartSet,
 	2,	/* Elements count */
@@ -401,6 +413,9 @@
 	asn1_DEF_vset_tags,
 	sizeof(asn1_DEF_vset_tags)
 		/sizeof(asn1_DEF_vset_tags[0]), /* 1 */
+	asn1_DEF_vset_tags,	/* Same as above */
+	sizeof(asn1_DEF_vset_tags)
+		/sizeof(asn1_DEF_vset_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_vset,
 	1,	/* Single element */
@@ -450,6 +465,9 @@
 	asn1_DEF_vrange_tags,
 	sizeof(asn1_DEF_vrange_tags)
 		/sizeof(asn1_DEF_vrange_tags[0]), /* 1 */
+	asn1_DEF_vrange_tags,	/* Same as above */
+	sizeof(asn1_DEF_vrange_tags)
+		/sizeof(asn1_DEF_vrange_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_vrange,
 	2,	/* Elements count */
@@ -493,8 +511,10 @@
 	CHOICE_print,
 	CHOICE_free,
 	CHOICE_outmost_tag,
-	0,	/* No explicit tags (pointer) */
-	0,	/* No explicit tags (count) */
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_VariablePart,
 	2,	/* Elements count */
@@ -583,6 +603,9 @@
 	asn1_DEF_email_tags,
 	sizeof(asn1_DEF_email_tags)
 		/sizeof(asn1_DEF_email_tags[0]), /* 1 */
+	asn1_DEF_email_tags,	/* Same as above */
+	sizeof(asn1_DEF_email_tags)
+		/sizeof(asn1_DEF_email_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_email,
 	1,	/* Single element */
@@ -632,6 +655,9 @@
 	asn1_DEF_notify_tags,
 	sizeof(asn1_DEF_notify_tags)
 		/sizeof(asn1_DEF_notify_tags[0]), /* 1 */
+	asn1_DEF_notify_tags,	/* Same as above */
+	sizeof(asn1_DEF_notify_tags)
+		/sizeof(asn1_DEF_notify_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_notify,
 	2,	/* Elements count */
@@ -680,6 +706,9 @@
 	asn1_DEF_ActionItem_tags,
 	sizeof(asn1_DEF_ActionItem_tags)
 		/sizeof(asn1_DEF_ActionItem_tags[0]), /* 1 */
+	asn1_DEF_ActionItem_tags,	/* Same as above */
+	sizeof(asn1_DEF_ActionItem_tags)
+		/sizeof(asn1_DEF_ActionItem_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_ActionItem,
 	2,	/* Elements count */
diff --git a/tests/43-recursion-OK.asn1.-P b/tests/43-recursion-OK.asn1.-P
index 18c02d7..1f93524 100644
--- a/tests/43-recursion-OK.asn1.-P
+++ b/tests/43-recursion-OK.asn1.-P
@@ -66,6 +66,9 @@
 	asn1_DEF_t_member1_tags,
 	sizeof(asn1_DEF_t_member1_tags)
 		/sizeof(asn1_DEF_t_member1_tags[0]), /* 1 */
+	asn1_DEF_t_member1_tags,	/* Same as above */
+	sizeof(asn1_DEF_t_member1_tags)
+		/sizeof(asn1_DEF_t_member1_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_t_member1,
 	1,	/* Single element */
@@ -100,6 +103,9 @@
 	asn1_DEF_t_member2_tags,
 	sizeof(asn1_DEF_t_member2_tags)
 		/sizeof(asn1_DEF_t_member2_tags[0]), /* 1 */
+	asn1_DEF_t_member2_tags,	/* Same as above */
+	sizeof(asn1_DEF_t_member2_tags)
+		/sizeof(asn1_DEF_t_member2_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_t_member2,
 	1,	/* Single element */
@@ -164,6 +170,9 @@
 	asn1_DEF_Test_structure_1_tags,
 	sizeof(asn1_DEF_Test_structure_1_tags)
 		/sizeof(asn1_DEF_Test_structure_1_tags[0]), /* 1 */
+	asn1_DEF_Test_structure_1_tags,	/* Same as above */
+	sizeof(asn1_DEF_Test_structure_1_tags)
+		/sizeof(asn1_DEF_Test_structure_1_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_Test_structure_1,
 	4,	/* Elements count */
@@ -223,7 +232,8 @@
 		},
 };
 static ber_tlv_tag_t asn1_DEF_or_tags[] = {
-	(ASN_TAG_CLASS_CONTEXT | (2 << 2))
+	(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
 };
 static asn1_SET_OF_specifics_t asn1_DEF_or_specs = {
 	sizeof(struct or),
@@ -240,7 +250,10 @@
 	0,	/* Use generic outmost tag fetcher */
 	asn1_DEF_or_tags,
 	sizeof(asn1_DEF_or_tags)
-		/sizeof(asn1_DEF_or_tags[0]), /* 1 */
+		/sizeof(asn1_DEF_or_tags[0]) - 1, /* 1 */
+	asn1_DEF_or_tags,	/* Same as above */
+	sizeof(asn1_DEF_or_tags)
+		/sizeof(asn1_DEF_or_tags[0]), /* 2 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_or,
 	1,	/* Single element */
@@ -300,8 +313,10 @@
 	CHOICE_print,
 	CHOICE_free,
 	CHOICE_outmost_tag,
-	0,	/* No explicit tags (pointer) */
-	0,	/* No explicit tags (count) */
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_Choice_1,
 	4,	/* Elements count */
diff --git a/tests/44-choice-in-sequence-OK.asn1.-P b/tests/44-choice-in-sequence-OK.asn1.-P
index 107cdb8..5ac269d 100644
--- a/tests/44-choice-in-sequence-OK.asn1.-P
+++ b/tests/44-choice-in-sequence-OK.asn1.-P
@@ -106,8 +106,10 @@
 	CHOICE_print,
 	CHOICE_free,
 	CHOICE_outmost_tag,
-	0,	/* No explicit tags (pointer) */
-	0,	/* No explicit tags (count) */
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_e,
 	2,	/* Elements count */
@@ -152,8 +154,10 @@
 	CHOICE_print,
 	CHOICE_free,
 	CHOICE_outmost_tag,
-	0,	/* No explicit tags (pointer) */
-	0,	/* No explicit tags (count) */
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_h,
 	2,	/* Elements count */
@@ -215,8 +219,10 @@
 	CHOICE_print,
 	CHOICE_free,
 	CHOICE_outmost_tag,
-	0,	/* No explicit tags (pointer) */
-	0,	/* No explicit tags (count) */
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_b,
 	4,	/* Elements count */
@@ -240,7 +246,8 @@
 		},
 };
 static ber_tlv_tag_t asn1_DEF_T_tags[] = {
-	(ASN_TAG_CLASS_PRIVATE | (1 << 2))
+	(ASN_TAG_CLASS_PRIVATE | (1 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
 };
 static asn1_TYPE_tag2member_t asn1_DEF_T_tag2el[] = {
     { (ASN_TAG_CLASS_PRIVATE | (2 << 2)), 0, 0, 0 }, /* a at 15 */
@@ -268,7 +275,10 @@
 	0,	/* Use generic outmost tag fetcher */
 	asn1_DEF_T_tags,
 	sizeof(asn1_DEF_T_tags)
-		/sizeof(asn1_DEF_T_tags[0]), /* 1 */
+		/sizeof(asn1_DEF_T_tags[0]) - 1, /* 1 */
+	asn1_DEF_T_tags,	/* Same as above */
+	sizeof(asn1_DEF_T_tags)
+		/sizeof(asn1_DEF_T_tags[0]), /* 2 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_T,
 	2,	/* Elements count */
diff --git a/tests/46-redefine-OK.asn1.-PR b/tests/46-redefine-OK.asn1.-PR
index ea256a8..9104df8 100644
--- a/tests/46-redefine-OK.asn1.-PR
+++ b/tests/46-redefine-OK.asn1.-PR
@@ -91,6 +91,9 @@
 	asn1_DEF_PrimitiveType_tags,
 	sizeof(asn1_DEF_PrimitiveType_tags)
 		/sizeof(asn1_DEF_PrimitiveType_tags[0]), /* 1 */
+	asn1_DEF_PrimitiveType_tags,	/* Same as above */
+	sizeof(asn1_DEF_PrimitiveType_tags)
+		/sizeof(asn1_DEF_PrimitiveType_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -152,6 +155,9 @@
 	asn1_DEF_ConstructedType_tags,
 	sizeof(asn1_DEF_ConstructedType_tags)
 		/sizeof(asn1_DEF_ConstructedType_tags[0]), /* 1 */
+	asn1_DEF_ConstructedType_tags,	/* Same as above */
+	sizeof(asn1_DEF_ConstructedType_tags)
+		/sizeof(asn1_DEF_ConstructedType_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_ConstructedType,
 	1,	/* Elements count */
@@ -238,7 +244,8 @@
 /*** <<< STAT-DEFS [T] >>> ***/
 
 static ber_tlv_tag_t asn1_DEF_T_tags[] = {
-	(ASN_TAG_CLASS_CONTEXT | (3 << 2))
+	(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
 };
 asn1_TYPE_descriptor_t asn1_DEF_T = {
 	"T",
@@ -250,7 +257,10 @@
 	0,	/* Use generic outmost tag fetcher */
 	asn1_DEF_T_tags,
 	sizeof(asn1_DEF_T_tags)
-		/sizeof(asn1_DEF_T_tags[0]), /* 1 */
+		/sizeof(asn1_DEF_T_tags[0]) - 1, /* 1 */
+	asn1_DEF_T_tags,	/* Same as above */
+	sizeof(asn1_DEF_T_tags)
+		/sizeof(asn1_DEF_T_tags[0]), /* 2 */
 	-0,	/* Unknown yet */
 	0, 0,	/* Defined elsewhere */
 	0	/* No specifics */
diff --git a/tests/47-set-ext-OK.asn1.-P b/tests/47-set-ext-OK.asn1.-P
index 5a3e2c1..51b77ac 100644
--- a/tests/47-set-ext-OK.asn1.-P
+++ b/tests/47-set-ext-OK.asn1.-P
@@ -73,6 +73,9 @@
 	asn1_DEF_T1_tags,
 	sizeof(asn1_DEF_T1_tags)
 		/sizeof(asn1_DEF_T1_tags[0]), /* 1 */
+	asn1_DEF_T1_tags,	/* Same as above */
+	sizeof(asn1_DEF_T1_tags)
+		/sizeof(asn1_DEF_T1_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_T1,
 	1,	/* Elements count */
@@ -154,6 +157,9 @@
 	asn1_DEF_T2_tags,
 	sizeof(asn1_DEF_T2_tags)
 		/sizeof(asn1_DEF_T2_tags[0]), /* 1 */
+	asn1_DEF_T2_tags,	/* Same as above */
+	sizeof(asn1_DEF_T2_tags)
+		/sizeof(asn1_DEF_T2_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_T2,
 	1,	/* Elements count */
@@ -223,8 +229,10 @@
 	CHOICE_print,
 	CHOICE_free,
 	CHOICE_outmost_tag,
-	0,	/* No explicit tags (pointer) */
-	0,	/* No explicit tags (count) */
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_T3,
 	1,	/* Elements count */
@@ -294,8 +302,10 @@
 	CHOICE_print,
 	CHOICE_free,
 	CHOICE_outmost_tag,
-	0,	/* No explicit tags (pointer) */
-	0,	/* No explicit tags (count) */
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_T4,
 	1,	/* Elements count */
diff --git a/tests/50-constraint-OK.asn1.-P b/tests/50-constraint-OK.asn1.-P
index 4459f53..545ddba 100644
--- a/tests/50-constraint-OK.asn1.-P
+++ b/tests/50-constraint-OK.asn1.-P
@@ -91,6 +91,9 @@
 	asn1_DEF_Int1_tags,
 	sizeof(asn1_DEF_Int1_tags)
 		/sizeof(asn1_DEF_Int1_tags[0]), /* 1 */
+	asn1_DEF_Int1_tags,	/* Same as above */
+	sizeof(asn1_DEF_Int1_tags)
+		/sizeof(asn1_DEF_Int1_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -207,6 +210,9 @@
 	asn1_DEF_Int2_tags,
 	sizeof(asn1_DEF_Int2_tags)
 		/sizeof(asn1_DEF_Int2_tags[0]), /* 1 */
+	asn1_DEF_Int2_tags,	/* Same as above */
+	sizeof(asn1_DEF_Int2_tags)
+		/sizeof(asn1_DEF_Int2_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -327,6 +333,9 @@
 	asn1_DEF_Int3_tags,
 	sizeof(asn1_DEF_Int3_tags)
 		/sizeof(asn1_DEF_Int3_tags[0]), /* 1 */
+	asn1_DEF_Int3_tags,	/* Same as above */
+	sizeof(asn1_DEF_Int3_tags)
+		/sizeof(asn1_DEF_Int3_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -447,6 +456,9 @@
 	asn1_DEF_Int4_tags,
 	sizeof(asn1_DEF_Int4_tags)
 		/sizeof(asn1_DEF_Int4_tags[0]), /* 1 */
+	asn1_DEF_Int4_tags,	/* Same as above */
+	sizeof(asn1_DEF_Int4_tags)
+		/sizeof(asn1_DEF_Int4_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -567,6 +579,9 @@
 	asn1_DEF_Int5_tags,
 	sizeof(asn1_DEF_Int5_tags)
 		/sizeof(asn1_DEF_Int5_tags[0]), /* 1 */
+	asn1_DEF_Int5_tags,	/* Same as above */
+	sizeof(asn1_DEF_Int5_tags)
+		/sizeof(asn1_DEF_Int5_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -687,6 +702,9 @@
 	asn1_DEF_ExtensibleExtensions_tags,
 	sizeof(asn1_DEF_ExtensibleExtensions_tags)
 		/sizeof(asn1_DEF_ExtensibleExtensions_tags[0]), /* 1 */
+	asn1_DEF_ExtensibleExtensions_tags,	/* Same as above */
+	sizeof(asn1_DEF_ExtensibleExtensions_tags)
+		/sizeof(asn1_DEF_ExtensibleExtensions_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -785,6 +803,9 @@
 	asn1_DEF_Str1_tags,
 	sizeof(asn1_DEF_Str1_tags)
 		/sizeof(asn1_DEF_Str1_tags[0]), /* 1 */
+	asn1_DEF_Str1_tags,	/* Same as above */
+	sizeof(asn1_DEF_Str1_tags)
+		/sizeof(asn1_DEF_Str1_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -917,6 +938,9 @@
 	asn1_DEF_Str2_tags,
 	sizeof(asn1_DEF_Str2_tags)
 		/sizeof(asn1_DEF_Str2_tags[0]), /* 1 */
+	asn1_DEF_Str2_tags,	/* Same as above */
+	sizeof(asn1_DEF_Str2_tags)
+		/sizeof(asn1_DEF_Str2_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -1060,6 +1084,9 @@
 	asn1_DEF_Str3_tags,
 	sizeof(asn1_DEF_Str3_tags)
 		/sizeof(asn1_DEF_Str3_tags[0]), /* 1 */
+	asn1_DEF_Str3_tags,	/* Same as above */
+	sizeof(asn1_DEF_Str3_tags)
+		/sizeof(asn1_DEF_Str3_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -1189,6 +1216,9 @@
 	asn1_DEF_Str4_tags,
 	sizeof(asn1_DEF_Str4_tags)
 		/sizeof(asn1_DEF_Str4_tags[0]), /* 1 */
+	asn1_DEF_Str4_tags,	/* Same as above */
+	sizeof(asn1_DEF_Str4_tags)
+		/sizeof(asn1_DEF_Str4_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -1318,6 +1348,9 @@
 	asn1_DEF_PER_Visible_tags,
 	sizeof(asn1_DEF_PER_Visible_tags)
 		/sizeof(asn1_DEF_PER_Visible_tags[0]), /* 1 */
+	asn1_DEF_PER_Visible_tags,	/* Same as above */
+	sizeof(asn1_DEF_PER_Visible_tags)
+		/sizeof(asn1_DEF_PER_Visible_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -1447,6 +1480,9 @@
 	asn1_DEF_PER_Visible_2_tags,
 	sizeof(asn1_DEF_PER_Visible_2_tags)
 		/sizeof(asn1_DEF_PER_Visible_2_tags[0]), /* 1 */
+	asn1_DEF_PER_Visible_2_tags,	/* Same as above */
+	sizeof(asn1_DEF_PER_Visible_2_tags)
+		/sizeof(asn1_DEF_PER_Visible_2_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -1576,6 +1612,9 @@
 	asn1_DEF_Not_PER_Visible_1_tags,
 	sizeof(asn1_DEF_Not_PER_Visible_1_tags)
 		/sizeof(asn1_DEF_Not_PER_Visible_1_tags[0]), /* 1 */
+	asn1_DEF_Not_PER_Visible_1_tags,	/* Same as above */
+	sizeof(asn1_DEF_Not_PER_Visible_1_tags)
+		/sizeof(asn1_DEF_Not_PER_Visible_1_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -1705,6 +1744,9 @@
 	asn1_DEF_Not_PER_Visible_2_tags,
 	sizeof(asn1_DEF_Not_PER_Visible_2_tags)
 		/sizeof(asn1_DEF_Not_PER_Visible_2_tags[0]), /* 1 */
+	asn1_DEF_Not_PER_Visible_2_tags,	/* Same as above */
+	sizeof(asn1_DEF_Not_PER_Visible_2_tags)
+		/sizeof(asn1_DEF_Not_PER_Visible_2_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -1834,6 +1876,9 @@
 	asn1_DEF_Not_PER_Visible_3_tags,
 	sizeof(asn1_DEF_Not_PER_Visible_3_tags)
 		/sizeof(asn1_DEF_Not_PER_Visible_3_tags[0]), /* 1 */
+	asn1_DEF_Not_PER_Visible_3_tags,	/* Same as above */
+	sizeof(asn1_DEF_Not_PER_Visible_3_tags)
+		/sizeof(asn1_DEF_Not_PER_Visible_3_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -1966,6 +2011,9 @@
 	asn1_DEF_SIZE_but_not_FROM_tags,
 	sizeof(asn1_DEF_SIZE_but_not_FROM_tags)
 		/sizeof(asn1_DEF_SIZE_but_not_FROM_tags[0]), /* 1 */
+	asn1_DEF_SIZE_but_not_FROM_tags,	/* Same as above */
+	sizeof(asn1_DEF_SIZE_but_not_FROM_tags)
+		/sizeof(asn1_DEF_SIZE_but_not_FROM_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -2098,6 +2146,9 @@
 	asn1_DEF_SIZE_and_FROM_tags,
 	sizeof(asn1_DEF_SIZE_and_FROM_tags)
 		/sizeof(asn1_DEF_SIZE_and_FROM_tags[0]), /* 1 */
+	asn1_DEF_SIZE_and_FROM_tags,	/* Same as above */
+	sizeof(asn1_DEF_SIZE_and_FROM_tags)
+		/sizeof(asn1_DEF_SIZE_and_FROM_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -2227,6 +2278,9 @@
 	asn1_DEF_Neither_SIZE_nor_FROM_tags,
 	sizeof(asn1_DEF_Neither_SIZE_nor_FROM_tags)
 		/sizeof(asn1_DEF_Neither_SIZE_nor_FROM_tags[0]), /* 1 */
+	asn1_DEF_Neither_SIZE_nor_FROM_tags,	/* Same as above */
+	sizeof(asn1_DEF_Neither_SIZE_nor_FROM_tags)
+		/sizeof(asn1_DEF_Neither_SIZE_nor_FROM_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -2373,6 +2427,9 @@
 	asn1_DEF_Utf8_3_tags,
 	sizeof(asn1_DEF_Utf8_3_tags)
 		/sizeof(asn1_DEF_Utf8_3_tags[0]), /* 1 */
+	asn1_DEF_Utf8_3_tags,	/* Same as above */
+	sizeof(asn1_DEF_Utf8_3_tags)
+		/sizeof(asn1_DEF_Utf8_3_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -2489,6 +2546,9 @@
 	asn1_DEF_Utf8_2_tags,
 	sizeof(asn1_DEF_Utf8_2_tags)
 		/sizeof(asn1_DEF_Utf8_2_tags[0]), /* 1 */
+	asn1_DEF_Utf8_2_tags,	/* Same as above */
+	sizeof(asn1_DEF_Utf8_2_tags)
+		/sizeof(asn1_DEF_Utf8_2_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -2587,6 +2647,9 @@
 	asn1_DEF_Utf8_1_tags,
 	sizeof(asn1_DEF_Utf8_1_tags)
 		/sizeof(asn1_DEF_Utf8_1_tags[0]), /* 1 */
+	asn1_DEF_Utf8_1_tags,	/* Same as above */
+	sizeof(asn1_DEF_Utf8_1_tags)
+		/sizeof(asn1_DEF_Utf8_1_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
diff --git a/tests/60-any-OK.asn1.-P b/tests/60-any-OK.asn1.-P
index 86d47f4..62fd9b3 100644
--- a/tests/60-any-OK.asn1.-P
+++ b/tests/60-any-OK.asn1.-P
@@ -63,6 +63,9 @@
 	asn1_DEF_T1_tags,
 	sizeof(asn1_DEF_T1_tags)
 		/sizeof(asn1_DEF_T1_tags[0]), /* 1 */
+	asn1_DEF_T1_tags,	/* Same as above */
+	sizeof(asn1_DEF_T1_tags)
+		/sizeof(asn1_DEF_T1_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_T1,
 	2,	/* Elements count */
@@ -135,6 +138,9 @@
 	asn1_DEF_T2_tags,
 	sizeof(asn1_DEF_T2_tags)
 		/sizeof(asn1_DEF_T2_tags[0]), /* 1 */
+	asn1_DEF_T2_tags,	/* Same as above */
+	sizeof(asn1_DEF_T2_tags)
+		/sizeof(asn1_DEF_T2_tags[0]), /* 1 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_T2,
 	2,	/* Elements count */
diff --git a/tests/65-multi-tag-OK.asn1.-P b/tests/65-multi-tag-OK.asn1.-P
index fec7c9c..01681c2 100644
--- a/tests/65-multi-tag-OK.asn1.-P
+++ b/tests/65-multi-tag-OK.asn1.-P
@@ -83,6 +83,14 @@
 	(ASN_TAG_CLASS_CONTEXT | (4 << 2)),
 	(ASN_TAG_CLASS_CONTEXT | (6 << 2))
 };
+static ber_tlv_tag_t asn1_DEF_T1_all_tags[] = {
+	(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (4 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (5 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (6 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
+};
 asn1_TYPE_descriptor_t asn1_DEF_T1 = {
 	"T1",
 	T1_constraint,
@@ -94,6 +102,9 @@
 	asn1_DEF_T1_tags,
 	sizeof(asn1_DEF_T1_tags)
 		/sizeof(asn1_DEF_T1_tags[0]), /* 4 */
+	asn1_DEF_T1_all_tags,
+	sizeof(asn1_DEF_T1_all_tags)
+		/sizeof(asn1_DEF_T1_all_tags[0]), /* 6 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -183,6 +194,13 @@
 	(ASN_TAG_CLASS_CONTEXT | (4 << 2)),
 	(ASN_TAG_CLASS_CONTEXT | (6 << 2))
 };
+static ber_tlv_tag_t asn1_DEF_T2_all_tags[] = {
+	(ASN_TAG_CLASS_CONTEXT | (3 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (4 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (5 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (6 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
+};
 asn1_TYPE_descriptor_t asn1_DEF_T2 = {
 	"T2",
 	T2_constraint,
@@ -194,6 +212,9 @@
 	asn1_DEF_T2_tags,
 	sizeof(asn1_DEF_T2_tags)
 		/sizeof(asn1_DEF_T2_tags[0]), /* 3 */
+	asn1_DEF_T2_all_tags,
+	sizeof(asn1_DEF_T2_all_tags)
+		/sizeof(asn1_DEF_T2_all_tags[0]), /* 5 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -282,6 +303,12 @@
 	(ASN_TAG_CLASS_CONTEXT | (4 << 2)),
 	(ASN_TAG_CLASS_CONTEXT | (6 << 2))
 };
+static ber_tlv_tag_t asn1_DEF_T3_all_tags[] = {
+	(ASN_TAG_CLASS_CONTEXT | (4 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (5 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (6 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
+};
 asn1_TYPE_descriptor_t asn1_DEF_T3 = {
 	"T3",
 	T3_constraint,
@@ -293,6 +320,9 @@
 	asn1_DEF_T3_tags,
 	sizeof(asn1_DEF_T3_tags)
 		/sizeof(asn1_DEF_T3_tags[0]), /* 2 */
+	asn1_DEF_T3_all_tags,
+	sizeof(asn1_DEF_T3_all_tags)
+		/sizeof(asn1_DEF_T3_all_tags[0]), /* 4 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -379,7 +409,8 @@
 
 static ber_tlv_tag_t asn1_DEF_T4_tags[] = {
 	(ASN_TAG_CLASS_CONTEXT | (5 << 2)),
-	(ASN_TAG_CLASS_CONTEXT | (6 << 2))
+	(ASN_TAG_CLASS_CONTEXT | (6 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
 };
 asn1_TYPE_descriptor_t asn1_DEF_T4 = {
 	"T4",
@@ -391,7 +422,10 @@
 	0,	/* Use generic outmost tag fetcher */
 	asn1_DEF_T4_tags,
 	sizeof(asn1_DEF_T4_tags)
-		/sizeof(asn1_DEF_T4_tags[0]), /* 2 */
+		/sizeof(asn1_DEF_T4_tags[0]) - 1, /* 2 */
+	asn1_DEF_T4_tags,	/* Same as above */
+	sizeof(asn1_DEF_T4_tags)
+		/sizeof(asn1_DEF_T4_tags[0]), /* 3 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -477,7 +511,8 @@
 /*** <<< STAT-DEFS [T5] >>> ***/
 
 static ber_tlv_tag_t asn1_DEF_T5_tags[] = {
-	(ASN_TAG_CLASS_CONTEXT | (6 << 2))
+	(ASN_TAG_CLASS_CONTEXT | (6 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (2 << 2))
 };
 asn1_TYPE_descriptor_t asn1_DEF_T5 = {
 	"T5",
@@ -489,7 +524,10 @@
 	0,	/* Use generic outmost tag fetcher */
 	asn1_DEF_T5_tags,
 	sizeof(asn1_DEF_T5_tags)
-		/sizeof(asn1_DEF_T5_tags[0]), /* 1 */
+		/sizeof(asn1_DEF_T5_tags[0]) - 1, /* 1 */
+	asn1_DEF_T5_tags,	/* Same as above */
+	sizeof(asn1_DEF_T5_tags)
+		/sizeof(asn1_DEF_T5_tags[0]), /* 2 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -588,6 +626,9 @@
 	asn1_DEF_T6_tags,
 	sizeof(asn1_DEF_T6_tags)
 		/sizeof(asn1_DEF_T6_tags[0]), /* 1 */
+	asn1_DEF_T6_tags,	/* Same as above */
+	sizeof(asn1_DEF_T6_tags)
+		/sizeof(asn1_DEF_T6_tags[0]), /* 1 */
 	-0,	/* Unknown yet */
 	0, 0,	/* No members */
 	0	/* No specifics */
@@ -673,7 +714,9 @@
 /*** <<< STAT-DEFS [T] >>> ***/
 
 static ber_tlv_tag_t asn1_DEF_T_tags[] = {
-	(ASN_TAG_CLASS_CONTEXT | (0 << 2))
+	(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (123 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
 };
 asn1_TYPE_descriptor_t asn1_DEF_T = {
 	"T",
@@ -685,7 +728,10 @@
 	0,	/* Use generic outmost tag fetcher */
 	asn1_DEF_T_tags,
 	sizeof(asn1_DEF_T_tags)
-		/sizeof(asn1_DEF_T_tags[0]), /* 1 */
+		/sizeof(asn1_DEF_T_tags[0]) - 2, /* 1 */
+	asn1_DEF_T_tags,	/* Same as above */
+	sizeof(asn1_DEF_T_tags)
+		/sizeof(asn1_DEF_T_tags[0]), /* 3 */
 	-0,	/* Unknown yet */
 	0, 0,	/* Defined elsewhere */
 	0	/* No specifics */
@@ -740,7 +786,8 @@
 		},
 };
 static ber_tlv_tag_t asn1_DEF_Ts_tags[] = {
-	(ASN_TAG_CLASS_CONTEXT | (123 << 2))
+	(ASN_TAG_CLASS_CONTEXT | (123 << 2)),
+	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
 };
 static asn1_TYPE_tag2member_t asn1_DEF_Ts_tag2el[] = {
     { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* m1 at 24 */
@@ -765,7 +812,10 @@
 	0,	/* Use generic outmost tag fetcher */
 	asn1_DEF_Ts_tags,
 	sizeof(asn1_DEF_Ts_tags)
-		/sizeof(asn1_DEF_Ts_tags[0]), /* 1 */
+		/sizeof(asn1_DEF_Ts_tags[0]) - 1, /* 1 */
+	asn1_DEF_Ts_tags,	/* Same as above */
+	sizeof(asn1_DEF_Ts_tags)
+		/sizeof(asn1_DEF_Ts_tags[0]), /* 2 */
 	1,	/* Whether CONSTRUCTED */
 	asn1_MBR_Ts,
 	3,	/* Elements count */