extensions support

diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index b136065..175ef24 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -569,7 +569,6 @@
 
 	asn_dec_rval_t rval;		/* Return value of a decoder */
 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
-	int xer_state;			/* XER low level parsing context */
 	int edx;			/* Element index */
 
 	/*
@@ -593,7 +592,7 @@
 	 * Phase 2: Processing inner type.
 	 * Phase 3: Only waiting for closing tag
 	 */
-	for(xer_state = ctx->left, edx = ctx->step; ctx->phase <= 3;) {
+	for(edx = ctx->step; ctx->phase <= 3;) {
 		pxer_chunk_type_e ch_type;	/* XER chunk type */
 		ssize_t ch_size;		/* Chunk size */
 		xer_check_tag_e tcv;		/* Tag check value */
@@ -623,7 +622,7 @@
 					elm->type, memb_ptr2, elm->name,
 					buf_ptr, size);
 			XER_ADVANCE(tmprval.consumed);
-			ASN_DEBUG("XER/CHOICE: itdf: code=%d, xs=%d", tmprval.code, xer_state);
+			ASN_DEBUG("XER/CHOICE: itdf: code=%d", tmprval.code);
 			if(tmprval.code != RC_OK)
 				RETURN(tmprval.code);
 			assert(_fetch_present_idx(st,
@@ -631,7 +630,6 @@
 			/* Record what we've got */
 			_set_present_idx(st,
 				specs->pres_offset, specs->pres_size, edx + 1);
-			ctx->left = xer_state = 0;	/* New, clean state */
 			ctx->phase = 3;
 			/* Fall through */
 		}
@@ -639,12 +637,10 @@
 		/*
 		 * Get the next part of the XML stream.
 		 */
-		ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+		ch_size = xer_next_token(buf_ptr, size, &ch_type);
 		switch(ch_size) {
 		case -1: RETURN(RC_FAIL);
-		case 0:
-			ctx->left = xer_state;
-			RETURN(RC_WMORE);
+		case 0:  RETURN(RC_WMORE);
 		default:
 			switch(ch_type) {
 			case PXER_COMMENT:	/* Got XML comment */
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 1430946..31f0c42 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -621,7 +621,6 @@
 
 	asn_dec_rval_t rval;		/* Return value from a decoder */
 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
-	int xer_state;			/* XER low level parsing context */
 	int edx;			/* Element index */
 	int edx_end;
 
@@ -644,8 +643,10 @@
 	 * Phase 0: Check that the opening tag matches our expectations.
 	 * Phase 1: Processing body and reacting on closing tag.
 	 * Phase 2: Processing inner type.
+	 * Phase 3: Skipping unknown extensions.
+	 * Phase 4: PHASED OUT
 	 */
-	for(xer_state = ctx->left, edx = ctx->step; ctx->phase <= 2;) {
+	for(edx = ctx->step; ctx->phase <= 3;) {
 		pxer_chunk_type_e ch_type;	/* XER chunk type */
 		ssize_t ch_size;		/* Chunk size */
 		xer_check_tag_e tcv;		/* Tag check value */
@@ -679,7 +680,6 @@
 			if(tmprval.code != RC_OK)
 				RETURN(tmprval.code);
 			ctx->phase = 1;	/* Back to body processing */
-			ctx->left = xer_state = 0;	/* New, clean state */
 			ctx->step = ++edx;
 			ASN_DEBUG("XER/SEQUENCE phase => %d, step => %d",
 				ctx->phase, ctx->step);
@@ -689,12 +689,10 @@
 		/*
 		 * Get the next part of the XML stream.
 		 */
-		ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+		ch_size = xer_next_token(buf_ptr, size, &ch_type);
 		switch(ch_size) {
 		case -1: RETURN(RC_FAIL);
-		case 0:
-			ctx->left = xer_state;
-			RETURN(RC_WMORE);
+		case 0:  RETURN(RC_WMORE);
 		default:
 			switch(ch_type) {
 			case PXER_COMMENT:	/* Got XML comment */
@@ -708,6 +706,26 @@
 
 		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
 		ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d", tcv, ctx->phase);
+
+		/* Skip the extensions section */
+		if(ctx->phase == 3) {
+			switch(xer_skip_unknown(tcv, &ctx->left)) {
+			case -1:
+				ctx->phase = 4;
+				RETURN(RC_FAIL);
+			case 0:
+				XER_ADVANCE(ch_size);
+				continue;
+			case 1:
+				XER_ADVANCE(ch_size);
+				ctx->phase = 1;
+				continue;
+			case 2:
+				ctx->phase = 1;
+				break;
+			}
+		}
+
 		switch(tcv) {
 		case XCT_CLOSING:
 			if(ctx->phase == 0) break;
@@ -727,7 +745,7 @@
 						> td->elements_count)
 				) {
 					XER_ADVANCE(ch_size);
-					ctx->phase = 3;	/* Phase out */
+					ctx->phase = 4;	/* Phase out */
 					RETURN(RC_OK);
 				} else {
 					ASN_DEBUG("Premature end of XER SEQUENCE");
@@ -784,11 +802,20 @@
 			/* It is expected extension */
 			if(IN_EXTENSION_GROUP(specs,
 				edx + elements[edx].optional)) {
-				ASN_DEBUG("Got anticipated extension at %d, "
-					"but NOT IMPLEMENTED YET", edx);
+				ASN_DEBUG("Got anticipated extension at %d", edx);
 				/*
-				 * TODO: implement skipping of extensions
+				 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
+				 * By using a mask. Only record a pure
+				 * <opening> tags.
 				 */
+				if(tcv & XCT_CLOSING) {
+					/* Found </extension> without body */
+				} else {
+					ctx->left = 1;
+					ctx->phase = 3;	/* Skip ...'s */
+				}
+				XER_ADVANCE(ch_size);
+				continue;
 			}
 
 			/* Fall through */
@@ -800,7 +827,7 @@
 		break;
 	}
 
-	ctx->phase = 3;	/* "Phase out" on hard failure */
+	ctx->phase = 4;	/* "Phase out" on hard failure */
 	RETURN(RC_FAIL);
 }
 
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index 120acb2..c5bb201 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -600,7 +600,6 @@
 
 	asn_dec_rval_t rval;		/* Return value from a decoder */
 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
-	int xer_state;			/* XER low level parsing context */
 	int edx;			/* Element index */
 
 	/*
@@ -621,8 +620,10 @@
 	 * Phase 0: Check that the opening tag matches our expectations.
 	 * Phase 1: Processing body and reacting on closing tag.
 	 * Phase 2: Processing inner type.
+	 * Phase 3: Skipping unknown extensions.
+	 * Phase 4: PHASED OUT
 	 */
-	for(xer_state = ctx->left, edx = ctx->step; ctx->phase <= 2;) {
+	for(edx = ctx->step; ctx->phase <= 3;) {
 		pxer_chunk_type_e ch_type;	/* XER chunk type */
 		ssize_t ch_size;		/* Chunk size */
 		xer_check_tag_e tcv;		/* Tag check value */
@@ -662,7 +663,6 @@
 			if(tmprval.code != RC_OK)
 				RETURN(tmprval.code);
 			ctx->phase = 1;	/* Back to body processing */
-			ctx->left = xer_state = 0;	/* New, clean state */
 			ASN_SET_MKPRESENT((char *)st + specs->pres_offset, edx);
 			ASN_DEBUG("XER/SET phase => %d", ctx->phase);
 			/* Fall through */
@@ -671,12 +671,10 @@
 		/*
 		 * Get the next part of the XML stream.
 		 */
-		ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+		ch_size = xer_next_token(buf_ptr, size, &ch_type);
 		switch(ch_size) {
 		case -1: RETURN(RC_FAIL);
-		case 0:
-			ctx->left = xer_state;
-			RETURN(RC_WMORE);
+		case 0:  RETURN(RC_WMORE);
 		default:
 			switch(ch_type) {
 			case PXER_COMMENT:	/* Got XML comment */
@@ -690,6 +688,26 @@
 
 		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
 		ASN_DEBUG("XER/SET: tcv = %d, ph=%d", tcv, ctx->phase);
+
+		/* Skip the extensions section */
+		if(ctx->phase == 3) {
+			switch(xer_skip_unknown(tcv, &ctx->left)) {
+			case -1:
+				ctx->phase = 4;
+				RETURN(RC_FAIL);
+			case 0:
+				XER_ADVANCE(ch_size);
+				continue;
+			case 1:
+				XER_ADVANCE(ch_size);
+				ctx->phase = 1;
+				continue;
+			case 2:
+				ctx->phase = 1;
+				break;
+			}
+		}
+
 		switch(tcv) {
 		case XCT_CLOSING:
 			if(ctx->phase == 0) break;
@@ -699,7 +717,7 @@
 			if(ctx->phase == 0) {
 				if(_SET_is_populated(td, st)) {
 					XER_ADVANCE(ch_size);
-					ctx->phase = 3;	/* Phase out */
+					ctx->phase = 4;	/* Phase out */
 					RETURN(RC_OK);
 				} else {
 					ASN_DEBUG("Premature end of XER SET");
@@ -725,9 +743,8 @@
 			 * Search which member corresponds to this tag.
 			 */
 			for(edx = 0; edx < td->elements_count; edx++) {
-				elm = &elements[edx];
-				tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
-				switch(tcv) {
+				switch(xer_check_tag(buf_ptr, ch_size,
+					elements[edx].name)) {
 				case XCT_BOTH:
 				case XCT_OPENING:
 					/*
@@ -750,11 +767,20 @@
 
 			/* It is expected extension */
 			if(specs->extensible) {
-				ASN_DEBUG("Got anticipated extension, "
-					"but NOT IMPLEMENTED YET");
+				ASN_DEBUG("Got anticipated extension");
 				/*
-				 * TODO: implement skipping of extensions
+				 * Check for (XCT_BOTH or XCT_UNKNOWN_BO)
+				 * By using a mask. Only record a pure
+				 * <opening> tags.
 				 */
+				if(tcv & XCT_CLOSING) {
+					/* Found </extension> without body */
+				} else {
+					ctx->left = 1;
+					ctx->phase = 3;	/* Skip ...'s */
+				}
+				XER_ADVANCE(ch_size);
+				continue;
 			}
 
 			/* Fall through */
@@ -766,7 +792,7 @@
 		break;
 	}
 
-	ctx->phase = 3;	/* "Phase out" on hard failure */
+	ctx->phase = 4;	/* "Phase out" on hard failure */
 	RETURN(RC_FAIL);
 }
 
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c
index eed604e..7df1e5c 100644
--- a/skeletons/constr_SET_OF.c
+++ b/skeletons/constr_SET_OF.c
@@ -482,7 +482,6 @@
 
 	asn_dec_rval_t rval;		/* Return value from a decoder */
 	ssize_t consumed_myself = 0;	/* Consumed bytes from ptr */
-	int xer_state;			/* XER low level parsing context */
 
 	/*
 	 * Create the target structure if it is not present already.
@@ -503,7 +502,7 @@
 	 * Phase 1: Processing body and reacting on closing tag.
 	 * Phase 2: Processing inner type.
 	 */
-	for(xer_state = ctx->left; ctx->phase <= 2;) {
+	for(; ctx->phase <= 2;) {
 		pxer_chunk_type_e ch_type;	/* XER chunk type */
 		ssize_t ch_size;		/* Chunk size */
 		xer_check_tag_e tcv;		/* Tag check value */
@@ -530,7 +529,6 @@
 				RETURN(tmprval.code);
 			}
 			ctx->phase = 1;	/* Back to body processing */
-			ctx->left = xer_state = 0;	/* New, clean state */
 			ASN_DEBUG("XER/SET OF phase => %d", ctx->phase);
 			/* Fall through */
 		}
@@ -538,12 +536,10 @@
 		/*
 		 * Get the next part of the XML stream.
 		 */
-		ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+		ch_size = xer_next_token(buf_ptr, size, &ch_type);
 		switch(ch_size) {
 		case -1: RETURN(RC_FAIL);
-		case 0:
-			ctx->left = xer_state;
-			RETURN(RC_WMORE);
+		case 0:  RETURN(RC_WMORE);
 		default:
 			switch(ch_type) {
 			case PXER_COMMENT:	/* Got XML comment */
diff --git a/skeletons/xer_decoder.c b/skeletons/xer_decoder.c
index e81d7de..ed1fff4 100644
--- a/skeletons/xer_decoder.c
+++ b/skeletons/xer_decoder.c
@@ -51,14 +51,13 @@
  * Fetch the next token from the XER/XML stream.
  */
 ssize_t
-xer_next_token(int *stateContext, void *buffer, size_t size,
-		pxer_chunk_type_e *ch_type) {
+xer_next_token(void *buffer, size_t size, pxer_chunk_type_e *ch_type) {
 	struct xer__cb_arg arg;
+	int stateContext = 0;
 	ssize_t ret;
-	int new_stateContext = *stateContext;
 
 	arg.callback_not_invoked = 1;
-	ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg);
+	ret = pxml_parse(&stateContext, buffer, size, xer__token_cb, &arg);
 	if(ret < 0) return -1;
 	if(arg.callback_not_invoked) {
 		assert(ret == 0);	/* No data was consumed */
@@ -66,6 +65,7 @@
 	} else {
 		assert(arg.chunk_size);
 		assert(arg.chunk_buf == buffer);
+		assert(stateContext == 0);
 	}
 
 	/*
@@ -85,7 +85,6 @@
 		break;
 	}
 
-	*stateContext = new_stateContext;	/* Update the context */
 	return arg.chunk_size;
 }
 
@@ -169,10 +168,8 @@
 			(struct_key, chunk_buf, chunk_size,	\
 				(size_t)chunk_size < size);	\
 		if(converted_size == -1) RETURN(RC_FAIL);	\
-		if(converted_size == 0 && size == chunk_size) {	\
-			ctx->step = xer_state;			\
+		if(converted_size == 0 && size == chunk_size)	\
 			RETURN(RC_WMORE);			\
-		}						\
 		chunk_size = converted_size;			\
 	} while(0)
 #define	XER_GOT_EMPTY()	do {					\
@@ -198,7 +195,6 @@
 
 	asn_dec_rval_t rval;
 	ssize_t consumed_myself = 0;
-	int xer_state;			/* XER low level parsing context */
 
 	(void)opt_codec_ctx;
 
@@ -208,7 +204,7 @@
 	 * Phase 1: Processing body and reacting on closing tag.
 	 */
 	if(ctx->phase > 1) RETURN(RC_FAIL);
-	for(xer_state = ctx->step;;) {
+	for(;;) {
 		pxer_chunk_type_e ch_type;	/* XER chunk type */
 		ssize_t ch_size;		/* Chunk size */
 		xer_check_tag_e tcv;		/* Tag check value */
@@ -216,11 +212,10 @@
 		/*
 		 * Get the next part of the XML stream.
 		 */
-		ch_size = xer_next_token(&xer_state, buf_ptr, size, &ch_type);
+		ch_size = xer_next_token(buf_ptr, size, &ch_type);
 		switch(ch_size) {
 		case -1: RETURN(RC_FAIL);
 		case 0:
-			ctx->step = xer_state;
 			RETURN(RC_WMORE);
 		default:
 			switch(ch_type) {
@@ -320,3 +315,29 @@
 	return 1;       /* All whitespace */
 }
 
+/*
+ * This is a vastly simplified, non-validating XML tree skipper.
+ */
+int
+xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth) {
+	assert(*depth > 0);
+	switch(tcv) {
+	case XCT_BOTH:
+	case XCT_UNKNOWN_BO:
+		/* These negate each other. */
+		return 0;
+	case XCT_OPENING:
+	case XCT_UNKNOWN_OP:
+		++(*depth);
+		return 0;
+	case XCT_CLOSING:
+	case XCT_UNKNOWN_CL:
+		if(--(*depth) == 0)
+			return (tcv == XCT_CLOSING) ? 2 : 1;
+		return 0;
+	default:
+		return -1;
+	}
+}
+
+
diff --git a/skeletons/xer_decoder.h b/skeletons/xer_decoder.h
index c3df005..c0e23b9 100644
--- a/skeletons/xer_decoder.h
+++ b/skeletons/xer_decoder.h
@@ -63,8 +63,7 @@
 	PXER_TEXT,	/* Plain text between XER tags */
 	PXER_COMMENT,	/* A comment, may be part of */
   } pxer_chunk_type_e;
-ssize_t xer_next_token(int *stateContext, void *buffer, size_t size,
-	pxer_chunk_type_e *_ch_type);
+ssize_t xer_next_token(void *buffer, size_t size, pxer_chunk_type_e *_ch_type);
 
 /*
  * This function checks the buffer against the tag name is expected to occur.
@@ -90,4 +89,9 @@
  */
 int xer_is_whitespace(void *chunk_buf, size_t chunk_size);
 
+/*
+ * Skip the series of anticipated extensions.
+ */
+int xer_skip_unknown(xer_check_tag_e tcv, ber_tlv_len_t *depth);
+
 #endif	/* _XER_DECODER_H_ */