more XER decoding


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@633 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index d1b0874..a9c591d 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -1103,26 +1103,34 @@
 		(void *struct_ptr, void *chunk_buf, size_t chunk_size,
 			int have_more)
 ) {
+	OCTET_STRING_t *st = *sptr;
 	asn_OCTET_STRING_specifics_t *specs = td->specifics
 				? (asn_OCTET_STRING_specifics_t *)td->specifics
 				: &asn_DEF_OCTET_STRING_specs;
 	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
 	asn_struct_ctx_t *ctx;		/* Per-structure parser context */
+	asn_dec_rval_t rval;		/* Return value from the decoder */
+	int st_allocated;
 
 	/*
 	 * Create the string if does not exist.
 	 */
-	if(!*sptr) {
-		OCTET_STRING_t *st;
+	if(!st) {
 		st = (OCTET_STRING_t *)CALLOC(1, specs->struct_size);
-		if(st) st->buf = (uint8_t *)CALLOC(1, 1);
 		*sptr = (void *)st;
-		if(!st || !st->buf) {
-			asn_dec_rval_t rval;
-			if(*sptr) FREEMEM(*sptr);
-			rval.code = RC_FAIL;
-			rval.consumed = 0;
-			return rval;
+		if(!st) goto sta_failed;
+		st_allocated = 1;
+	} else  st_allocated = 0;
+	if(!st->buf) {
+		/* This is separate from above section */
+		st->buf = (uint8_t *)CALLOC(1, 1);
+		if(!st->buf) {
+			if(st_allocated) {
+				*sptr = 0;
+				goto stb_failed;
+			} else {
+				goto sta_failed;
+			}
 		}
 	}
 
@@ -1131,6 +1139,13 @@
 
 	return xer_decode_general(opt_codec_ctx, ctx, *sptr, xml_tag,
 		buf_ptr, size, opt_unexpected_tag_decoder, body_receiver);
+
+stb_failed:
+	FREEMEM(st);
+sta_failed:
+	rval.code = RC_FAIL;
+	rval.consumed = 0;
+	return rval;
 }
 
 /*
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index 40e99e5..0222abf 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -1,5 +1,6 @@
 /*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #include <asn_internal.h>
@@ -539,7 +540,6 @@
 	}
 }
 
-#undef	ADVANCE	/* Just in case */
 #undef	XER_ADVANCE
 #define	XER_ADVANCE(num_bytes)	do {			\
 		size_t num = num_bytes;			\
@@ -548,6 +548,9 @@
 		consumed_myself += num;			\
 	} while(0)
 
+/*
+ * Decode the XER (XML) data.
+ */
 asn_dec_rval_t
 CHOICE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
 	void **struct_ptr, const char *opt_mname,
@@ -564,7 +567,7 @@
 	void *st = *struct_ptr;	/* Target structure. */
 	asn_struct_ctx_t *ctx;	/* Decoder context */
 
-	asn_dec_rval_t rval;
+	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 */
@@ -590,9 +593,7 @@
 	 * Phase 2: Processing inner type.
 	 * Phase 3: Only waiting for closing tag
 	 */
-
-	if(ctx->phase > 3) RETURN(RC_FAIL);
-	for(xer_state = ctx->left, edx = ctx->step;;) {
+	for(xer_state = ctx->left, 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 */
@@ -617,12 +618,19 @@
 				memb_ptr2 = &memb_ptr;
 			}
 
+			/* Start/Continue decoding the inner member */
 			tmprval = elm->type->xer_decoder(opt_codec_ctx,
 					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);
 			if(tmprval.code != RC_OK)
 				RETURN(tmprval.code);
+			assert(_fetch_present_idx(st,
+				specs->pres_offset, specs->pres_size) == 0);
+			/* 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 */
@@ -648,25 +656,22 @@
 			}
 		}
 
-		tcv = xer_check_tag(buf_ptr, size, xml_tag);
+		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
+		printf("XER/CHOICE tcv=%d ph=%d\n", tcv, ctx->phase);
 		switch(tcv) {
 		case XCT_BOTH:
-			if(ctx->phase == 3)
-				break;
+			break;	/* No CHOICE? */
 		case XCT_CLOSING:
-			if(ctx->phase == 0)
+			if(ctx->phase != 3)
 				break;
 			XER_ADVANCE(ch_size);
-			ctx->phase = 4;
+			ctx->phase = 4;	/* Phase out */
 			RETURN(RC_OK);
 		case XCT_OPENING:
 			if(ctx->phase == 0) {
 				XER_ADVANCE(ch_size);
 				ctx->phase = 1;	/* Processing body phase */
 				continue;
-			} else if(ctx->phase == 3) {
-				/* But we're waiting for closing! */
-				break;
 			}
 			/* Fall through */
 		case XCT_UNEXPECTED:
@@ -675,11 +680,11 @@
 				break;	/* Really unexpected */
 
 			/*
-			 * Search which member corresponds to this tag.
+			 * Search which inner member corresponds to this tag.
 			 */
 			for(edx = 0; edx < td->elements_count; edx++) {
 				elm = &td->elements[edx];
-				tcv = xer_check_tag(buf_ptr, size, elm->name);
+				tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
 				switch(tcv) {
 				case XCT_BOTH:
 				case XCT_OPENING:
@@ -704,7 +709,7 @@
 			break;
 		}
 
-		ASN_DEBUG("Unexpected XML tag in SEQUENCE");
+		ASN_DEBUG("Unexpected XML tag in CHOICE");
 		break;
 	}
 
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index bac4244..01fc8a9 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -1,5 +1,6 @@
 /*-
- * Copyright (c) 2003, 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2003, 2004, 2005 Lev Walkin <vlm@lionet.info>.
+ * All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #include <asn_internal.h>
@@ -588,7 +589,7 @@
 	return erval;
 }
 
-#undef	ADVANCE	/* Just in case */
+
 #undef	XER_ADVANCE
 #define	XER_ADVANCE(num_bytes)	do {			\
 		size_t num = num_bytes;			\
@@ -597,6 +598,9 @@
 		consumed_myself += num;			\
 	} while(0)
 
+/*
+ * Decode the XER (XML) data.
+ */
 asn_dec_rval_t
 SEQUENCE_decode_xer(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
 	void **struct_ptr, const char *opt_mname,
@@ -604,17 +608,18 @@
 	/*
 	 * Bring closer parts of structure description.
 	 */
-	asn_SEQUENCE_specifics_t *specs = (asn_SEQUENCE_specifics_t *)td->specifics;
+	asn_SEQUENCE_specifics_t *specs
+		= (asn_SEQUENCE_specifics_t *)td->specifics;
 	asn_TYPE_member_t *elements = td->elements;
 	const char *xml_tag = opt_mname ? opt_mname : td->xml_tag;
 
 	/*
-	 * Parts of the structure being constructed.
+	 * ... and parts of the structure being constructed.
 	 */
 	void *st = *struct_ptr;	/* Target structure. */
 	asn_struct_ctx_t *ctx;	/* Decoder context */
 
-	asn_dec_rval_t rval;
+	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 */
@@ -639,16 +644,14 @@
 	 * Phase 1: Processing body and reacting on closing tag.
 	 * Phase 2: Processing inner type.
 	 */
-
-	if(ctx->phase > 2) RETURN(RC_FAIL);
-	for(xer_state = ctx->left, edx = ctx->step;;) {
+	for(xer_state = ctx->left, edx = ctx->step; 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 */
 		asn_TYPE_member_t *elm;
 
 		/*
-		 * Go inside the member.
+		 * Go inside the inner member of a sequence.
 		 */
 		if(ctx->phase == 2) {
 			asn_dec_rval_t tmprval;
@@ -666,15 +669,18 @@
 				memb_ptr2 = &memb_ptr;
 			}
 
+			/* Invoke the inner type decoder, m.b. multiple times */
 			tmprval = elm->type->xer_decoder(opt_codec_ctx,
 					elm->type, memb_ptr2, elm->name,
 					buf_ptr, size);
 			XER_ADVANCE(tmprval.consumed);
 			if(tmprval.code != RC_OK)
 				RETURN(tmprval.code);
-			ctx->phase = 1;
+			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);
 			/* Fall through */
 		}
 
@@ -698,11 +704,11 @@
 			}
 		}
 
-		tcv = xer_check_tag(buf_ptr, size, xml_tag);
+		tcv = xer_check_tag(buf_ptr, ch_size, xml_tag);
+		ASN_DEBUG("XER/SEQUENCE: tcv = %d, ph=%d", tcv, ctx->phase);
 		switch(tcv) {
 		case XCT_CLOSING:
 			if(ctx->phase == 0) break;
-			XER_ADVANCE(ch_size);
 			ctx->phase = 0;
 			/* Fall through */
 		case XCT_BOTH:
@@ -720,7 +726,7 @@
 				) {
 					XER_ADVANCE(ch_size);
 					ctx->phase = 3;	/* Phase out */
-					continue;
+					RETURN(RC_OK);
 				} else {
 					ASN_DEBUG("Premature end of XER SEQUENCE");
 					RETURN(RC_FAIL);
@@ -738,7 +744,9 @@
 			int edx_end;
 			int n;
 
-			if(!ctx->phase
+			ASN_DEBUG("XER/SEQUENCE: tcv=%d, ph=%d",
+				tcv, ctx->phase);
+			if(ctx->phase != 1
 			|| edx >= td->elements_count)
 				break;	/* Really unexpected */
 
@@ -748,7 +756,7 @@
 			edx_end = edx + elements[edx].optional + 1;
 			for(n = edx; n < edx_end; n++) {
 				elm = &td->elements[n];
-				tcv = xer_check_tag(buf_ptr, size, elm->name);
+				tcv = xer_check_tag(buf_ptr,ch_size,elm->name);
 				switch(tcv) {
 				case XCT_BOTH:
 				case XCT_OPENING:
@@ -778,7 +786,7 @@
 		break;
 	}
 
-	ctx->phase = 3;	/* Phase out, just in case */
+	ctx->phase = 3;	/* "Phase out" on hard failure */
 	RETURN(RC_FAIL);
 }
 
diff --git a/skeletons/xer_decoder.c b/skeletons/xer_decoder.c
index db27a49..79a6bcc 100644
--- a/skeletons/xer_decoder.c
+++ b/skeletons/xer_decoder.c
@@ -55,9 +55,10 @@
 		pxer_chunk_type_e *ch_type) {
 	struct xer__cb_arg arg;
 	ssize_t ret;
+	int new_stateContext = *stateContext;
 
 	arg.callback_not_invoked = 1;
-	ret = pxml_parse(stateContext, buffer, size, xer__token_cb, &arg);
+	ret = pxml_parse(&new_stateContext, buffer, size, xer__token_cb, &arg);
 	if(ret < 0) return -1;
 	if(arg.callback_not_invoked) {
 		assert(ret == 0);	/* No data was consumed */
@@ -84,6 +85,7 @@
 		break;
 	}
 
+	*stateContext = new_stateContext;	/* Update the context */
 	return arg.chunk_size;
 }
 
@@ -98,6 +100,8 @@
 	xer_check_tag_e ct = XCT_OPENING;
 
 	if(size < 2 || buf[0] != LANGLE || buf[size-1] != RANGLE) {
+		if(size >= 2)
+		ASN_DEBUG("Broken XML tag: \"%c...%c\"", buf[0], buf[size - 1]);
 		return XCT_BROKEN;
 	}