context is now optional

diff --git a/skeletons/BOOLEAN.c b/skeletons/BOOLEAN.c
index 9609a19..c7a1cac 100644
--- a/skeletons/BOOLEAN.c
+++ b/skeletons/BOOLEAN.c
@@ -39,7 +39,6 @@
 		int tag_mode) {
 	BOOLEAN_t *st = (BOOLEAN_t *)*bool_value;
 	ber_dec_rval_t rval;
-	ber_dec_ctx_t ctx = { 0, 0, 0, 0 };
 	ber_tlv_len_t length;
 	ber_tlv_len_t lidx;
 
@@ -58,8 +57,7 @@
 	/*
 	 * Check tags.
 	 */
-	rval = ber_check_tags(td, &ctx,
-		buf_ptr, size, tag_mode, &length, 0);
+	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, &length, 0);
 	if(rval.code != RC_OK)
 		return rval;
 
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index 75782a6..73b5959 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -40,7 +40,6 @@
 	void **int_structure, void *buf_ptr, size_t size, int tag_mode) {
 	INTEGER_t *st = (INTEGER_t *)*int_structure;
 	ber_dec_rval_t rval;
-	ber_dec_ctx_t ctx = { 0, 0, 0, 0 };
 	ber_tlv_len_t length;
 
 	/*
@@ -61,8 +60,7 @@
 	/*
 	 * Check tags.
 	 */
-	rval = ber_check_tags(td, &ctx,
-		buf_ptr, size, tag_mode, &length, 0);
+	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, &length, 0);
 	if(rval.code != RC_OK)
 		return rval;
 
diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c
index b0872a2..aac5f86 100644
--- a/skeletons/NativeInteger.c
+++ b/skeletons/NativeInteger.c
@@ -47,7 +47,6 @@
 	void **int_ptr, void *buf_ptr, size_t size, int tag_mode) {
 	int *Int = (int *)*int_ptr;
 	ber_dec_rval_t rval;
-	ber_dec_ctx_t ctx = { 0, 0, 0, 0 };
 	ber_tlv_len_t length;
 
 	/*
@@ -68,8 +67,7 @@
 	/*
 	 * Check tags.
 	 */
-	rval = ber_check_tags(td, &ctx,
-		buf_ptr, size, tag_mode, &length, 0);
+	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, &length, 0);
 	if(rval.code != RC_OK)
 		return rval;
 
diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c
index 1566a7f..1151087 100644
--- a/skeletons/NativeReal.c
+++ b/skeletons/NativeReal.c
@@ -48,7 +48,6 @@
 	void **dbl_ptr, void *buf_ptr, size_t size, int tag_mode) {
 	double *Dbl = (double *)*dbl_ptr;
 	ber_dec_rval_t rval;
-	ber_dec_ctx_t ctx = { 0, 0, 0, 0 };
 	ber_tlv_len_t length;
 
 	/*
@@ -69,8 +68,7 @@
 	/*
 	 * Check tags.
 	 */
-	rval = ber_check_tags(td, &ctx,
-		buf_ptr, size, tag_mode, &length, 0);
+	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, &length, 0);
 	if(rval.code != RC_OK)
 		return rval;
 
diff --git a/skeletons/ber_decoder.c b/skeletons/ber_decoder.c
index 1632bb0..3672b68 100644
--- a/skeletons/ber_decoder.c
+++ b/skeletons/ber_decoder.c
@@ -3,22 +3,25 @@
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #include <asn_internal.h>
-#include <constr_TYPE.h>
 #include <assert.h>
 
 #undef	ADVANCE
-#define	ADVANCE(num_bytes)	do {			\
-		size_t num = num_bytes;			\
-		ptr = ((char *)ptr) + num;		\
-		size -= num;				\
-		consumed_myself += num;			\
+#define	ADVANCE(num_bytes)	do {					\
+		size_t num = num_bytes;					\
+		ptr = ((char *)ptr) + num;				\
+		size -= num;						\
+		consumed_myself += num;					\
 	} while(0)
 #undef	RETURN
-#define	RETURN(_code)	do {				\
-		ber_dec_rval_t rval;			\
-		rval.code = _code;			\
-		rval.consumed = consumed_myself;	\
-		return rval;				\
+#define	RETURN(_code)	do {						\
+		ber_dec_rval_t rval;					\
+		rval.code = _code;					\
+		if(opt_ctx) opt_ctx->step = step; /* Save context */	\
+		if(_code == RC_OK || opt_ctx)				\
+			rval.consumed = consumed_myself;		\
+		else							\
+			rval.consumed = 0;	/* Context-free */	\
+		return rval;						\
 	} while(0)
 
 /*
@@ -42,7 +45,7 @@
  * Check the set of <TL<TL<TL...>>> tags matches the definition.
  */
 ber_dec_rval_t
-ber_check_tags(asn1_TYPE_descriptor_t *td, ber_dec_ctx_t *ctx,
+ber_check_tags(asn1_TYPE_descriptor_t *td, ber_dec_ctx_t *opt_ctx,
 		void *ptr, size_t size, int tag_mode,
 		ber_tlv_len_t *last_length, int *opt_tlv_form) {
 	ssize_t consumed_myself = 0;
@@ -53,6 +56,7 @@
 	ber_tlv_len_t limit_len = -1;
 	int expect_00_terminators = 0;
 	int tlv_constr = -1;	/* If CHOICE, opt_tlv_form is not given */
+	int step = opt_ctx ? opt_ctx->step : 0;	/* Where we left previously */
 	int tagno;
 
 	/*
@@ -77,11 +81,11 @@
 	 * it appropriately.
 	 */
 
-	tagno = ctx->step	/* Continuing where left previously */
+	tagno = step	/* Continuing where left previously */
 		+ (tag_mode==1?-1:0)
 		;
 	ASN_DEBUG("ber_check_tags(%s, size=%ld, tm=%d, step=%d, tagno=%d)",
-		td->name, (long)size, tag_mode, ctx->step, tagno);
+		td->name, (long)size, tag_mode, step, tagno);
 	//assert(td->tags_count >= 1); ?May not be the case for CHOICE or ANY.
 
 	if(tag_mode == 0 && tagno == td->tags_count) {
@@ -102,23 +106,25 @@
 		case -1: RETURN(RC_FAIL);
 		case 0: RETURN(RC_WMORE);
 		}
+		ASN_DEBUG("Advancing %ld in ANY case",
+			(long)(tag_len + len_len));
 		ADVANCE(tag_len + len_len);
 	} else {
 		assert(tagno < td->tags_count);	/* At least one loop */
 	}
-	for((void)tagno; tagno < td->tags_count; tagno++, ctx->step++) {
+	for((void)tagno; tagno < td->tags_count; tagno++, step++) {
 
 		/*
 		 * Fetch and process T from TLV.
 		 */
 		tag_len = ber_fetch_tag(ptr, size, &tlv_tag);
 			ASN_DEBUG("Fetching tag from {%p,%ld} %02X..%02X: "
-				"len %ld, tag %s",
+				"len %ld, step %d, tag %s",
 				ptr, (long)size,
 				size?*(uint8_t *)ptr:0,
 				((size_t)tag_len<size&&tag_len>0)
 					?*((uint8_t *)ptr + tag_len):0,
-				(long)tag_len,
+				(long)tag_len, step,
 				ber_tlv_tag_string(tlv_tag));
 		switch(tag_len) {
 		case -1: RETURN(RC_FAIL);
@@ -131,7 +137,7 @@
 		 * If {I}, don't check anything.
 		 * If {I,B,C}, check B and C unless we're at I.
 		 */
-		if(tag_mode != 0 && ctx->step == 0) {
+		if(tag_mode != 0 && step == 0) {
 			/*
 			 * We don't expect tag to match here.
 			 * It's just because we don't know how the tag
@@ -158,11 +164,15 @@
 		 */
 		if(tagno < (td->tags_count - 1)) {
 			if(tlv_constr == 0) {
+				ASN_DEBUG("tlv_constr = %d, expfail",
+					tlv_constr);
 				RETURN(RC_FAIL);
 			}
 		} else {
 			if(td->last_tag_form != tlv_constr
 			&& td->last_tag_form != -1) {
+				ASN_DEBUG("last_tag_form %d != %d",
+					td->last_tag_form, tlv_constr);
 				RETURN(RC_FAIL);
 			}
 		}
@@ -172,6 +182,7 @@
 		 */
 		len_len = ber_fetch_length(tlv_constr,
 			(char *)ptr + tag_len, size - tag_len, &tlv_len);
+		ASN_DEBUG("Fetchinig len = %ld", (long)len_len);
 		switch(len_len) {
 		case -1: RETURN(RC_FAIL);
 		case 0: RETURN(RC_WMORE);
@@ -227,7 +238,7 @@
 		if((ssize_t)size > limit_len) {
 			/*
 			 * Make sure that we won't consume more bytes
-			 * from the large buffer than the inferred limit.
+			 * from the parent frame than the inferred limit.
 			 */
 			size = limit_len;
 		}