padding change

git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@1329 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/examples/sample.makefile.regen b/examples/sample.makefile.regen
index b1f4a64..5e18947 100755
--- a/examples/sample.makefile.regen
+++ b/examples/sample.makefile.regen
@@ -75,12 +75,12 @@
 	echo '	for b in 1 17 33 980 8192; do \'
 	echo '	echo "Recoding $$f into XER and back ($$b)..."; \'
 	echo '	./${TARGET} -b $$b -iber -oxer $$f > ./.tmp.1.$$$$ || exit 2; \'
-	echo '	./${TARGET} -b $$b -ixer -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \'
-	echo '	diff ./.tmp.1.$$$$ ./.tmp.2.$$$$ || exit 2; \'
+	echo '	./${TARGET} -b $$b -ixer -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 3; \'
+	echo '	diff ./.tmp.1.$$$$ ./.tmp.2.$$$$ || exit 4; \'
 	echo '	rm -f ./.tmp.[12].$$$$; \'
 	echo '	echo "Test junking $$f (please wait)..."; \'
-	echo '	./${TARGET} -J0.0001 -n 1000 -b $$b -iber -onull $$f || exit 2; \'
-	echo '	./${TARGET} -J0.001 -n 1000 -b $$b -iber -onull $$f || exit 2; \'
+	echo '	./${TARGET} -J0.0001 -n 1000 -b $$b -iber -onull $$f || exit 5; \'
+	echo '	./${TARGET} -J0.001 -n 1000 -b $$b -iber -onull $$f || exit 6; \'
 	echo '	done; done; fi'
 	echo
 	echo 'check-xer:'
@@ -89,41 +89,41 @@
 	echo '	for b in 1 17 33 980 8192; do \'
 	echo '	echo "Recoding $$f into DER and back ($$b)..."; \'
 	echo '	./${TARGET} -b $$b -ixer -oder $$f > ./.tmp.1.$$$$ || exit 2; \'
-	echo '	./${TARGET} -b $$b -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \'
-	echo '	diff $$f ./.tmp.2.$$$$ || exit 2; \'
+	echo '	./${TARGET} -b $$b -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 3; \'
+	echo '	diff $$f ./.tmp.2.$$$$ || exit 4; \'
 	echo '	rm -f ./.tmp.[12].$$$$; \'
 	echo '	echo "Test junking $$f (please wait)..."; \'
-	echo '	./${TARGET} -J0.0001 -n 1000 -b $$b -ixer -onull $$f || exit 2; \'
-	echo '	./${TARGET} -J0.001 -n 1000 -b $$b -ixer -onull $$f || exit 2; \'
+	echo '	./${TARGET} -J0.0001 -n 1000 -b $$b -ixer -onull $$f || exit 5; \'
+	echo '	./${TARGET} -J0.001 -n 1000 -b $$b -ixer -onull $$f || exit 6; \'
 	echo '	done; done; fi'
 	echo
 	echo 'check-per:'
-	echo "	@if test -f sample-${ASN1PDU}-1.per ; then \\"
-	echo "	for f in sample-${ASN1PDU}-[1-9].per; do \\"
+	echo "	@if test -f sample-${ASN1PDU}-1-nopad.per ; then \\"
+	echo "	for f in sample-${ASN1PDU}-[1-9]-nopad.per; do \\"
 	echo '	for b in 1 17 33 980 8192; do \'
-	echo '	echo "Recoding $$f into DER into XER and back ($$b)..."; \'
-	echo '	./${TARGET} -b $$b -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \'
-	echo '	./${TARGET} -b $$b -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \'
-	echo '	./${TARGET} -b $$b -ixer -oder ./.tmp.2.$$$$ > ./.tmp.3.$$$$ || exit 2; \'
-	echo '	diff ./.tmp.1.$$$$ ./.tmp.3.$$$$ || exit 2; \'
+	echo '	echo "Recoding non-padded $$f into DER into XER and back ($$b)..."; \'
+	echo '	./${TARGET} -b $$b -per-nopad -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \'
+	echo '	./${TARGET} -b $$b -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 3; \'
+	echo '	./${TARGET} -b $$b -ixer -oder ./.tmp.2.$$$$ > ./.tmp.3.$$$$ || exit 4; \'
+	echo '	diff ./.tmp.1.$$$$ ./.tmp.3.$$$$ || exit 5; \'
 	echo '	rm -f ./.tmp.[123].$$$$; \'
 	echo '	echo "Test junking $$f (please wait)..."; \'
-	echo '	./${TARGET} -J0.0001 -n 1000 -b $$b -iper -onull $$f || exit 2; \'
-	echo '	./${TARGET} -J0.001 -n 1000 -b $$b -iper -onull $$f || exit 2; \'
+	echo '	./${TARGET} -J0.0001 -n 1000 -b $$b -per-nopad -iper -onull $$f || exit 6; \'
+	echo '	./${TARGET} -J0.001 -n 1000 -b $$b -per-nopad -iper -onull $$f || exit 7; \'
 	echo '	done; done; fi'
-	echo "	@if test -f sample-${ASN1PDU}-1-padded.per ; then \\"
-	echo "	for f in sample-*-[1-9]-padded.per; do \\"
+	echo "	@if test -f sample-${ASN1PDU}-1.per ; then \\"
+	echo "	for f in sample-*-[1-9].per; do \\"
 	echo '	pdu=`echo $$f | sed -E -e "s/sample-([A-Za-z-]+)-[0-9].*/\1/"`; \'
 	echo '	for b in 1 17 33 980 8192; do \'
-	echo '	echo "Recoding byte-padded $$f into DER into XER and back ($$b)..."; \'
-	echo '	./${TARGET} -b $$b -per-padded -p $$pdu -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \'
-	echo '	./${TARGET} -b $$b -p $$pdu -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \'
-	echo '	./${TARGET} -b $$b -p $$pdu -ixer -oper ./.tmp.2.$$$$ > ./.tmp.1.$$$$ || exit 2; \'
-	echo '	diff $$f ./.tmp.1.$$$$ || exit 2; \'
+	echo '	echo "Recoding $$f into DER into XER and back ($$b)..."; \'
+	echo '	./${TARGET} -b $$b -p $$pdu -iper -oder $$f > ./.tmp.1.$$$$ || exit 3; \'
+	echo '	./${TARGET} -b $$b -p $$pdu -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 4; \'
+	echo '	./${TARGET} -b $$b -p $$pdu -ixer -oper ./.tmp.2.$$$$ > ./.tmp.1.$$$$ || exit 5; \'
+	echo '	diff $$f ./.tmp.1.$$$$ || exit 6; \'
 	echo '	rm -f ./.tmp.[12].$$$$; \'
 	echo '	echo "Test junking $$f (please wait)..."; \'
-	echo '	./${TARGET} -J0.0001 -n 1000 -b $$b -per-padded -iper -onull $$f || exit 2; \'
-	echo '	./${TARGET} -J0.001 -n 1000 -b $$b -per-padded -iper -onull $$f || exit 2; \'
+	echo '	./${TARGET} -J0.0001 -n 1000 -b $$b -iper -onull $$f || exit 7; \'
+	echo '	./${TARGET} -J0.001 -n 1000 -b $$b -iper -onull $$f || exit 8; \'
 	echo '	done; done; fi'
 	echo
 	echo "distclean: clean"
diff --git a/examples/sample.source.RRC/Makefile b/examples/sample.source.RRC/Makefile
index 22c5436..5ecd357 100644
--- a/examples/sample.source.RRC/Makefile
+++ b/examples/sample.source.RRC/Makefile
@@ -4787,12 +4787,12 @@
 	for b in 1 17 33 980 8192; do \
 	echo "Recoding $$f into XER and back ($$b)..."; \
 	./${TARGET} -b $$b -iber -oxer $$f > ./.tmp.1.$$$$ || exit 2; \
-	./${TARGET} -b $$b -ixer -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
-	diff ./.tmp.1.$$$$ ./.tmp.2.$$$$ || exit 2; \
+	./${TARGET} -b $$b -ixer -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 3; \
+	diff ./.tmp.1.$$$$ ./.tmp.2.$$$$ || exit 4; \
 	rm -f ./.tmp.[12].$$$$; \
 	echo "Test junking $$f (please wait)..."; \
-	./${TARGET} -J0.0001 -n 1000 -b $$b -iber -onull $$f || exit 2; \
-	./${TARGET} -J0.001 -n 1000 -b $$b -iber -onull $$f || exit 2; \
+	./${TARGET} -J0.0001 -n 1000 -b $$b -iber -onull $$f || exit 5; \
+	./${TARGET} -J0.001 -n 1000 -b $$b -iber -onull $$f || exit 6; \
 	done; done; fi
 
 check-xer:
@@ -4801,41 +4801,41 @@
 	for b in 1 17 33 980 8192; do \
 	echo "Recoding $$f into DER and back ($$b)..."; \
 	./${TARGET} -b $$b -ixer -oder $$f > ./.tmp.1.$$$$ || exit 2; \
-	./${TARGET} -b $$b -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
-	diff $$f ./.tmp.2.$$$$ || exit 2; \
+	./${TARGET} -b $$b -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 3; \
+	diff $$f ./.tmp.2.$$$$ || exit 4; \
 	rm -f ./.tmp.[12].$$$$; \
 	echo "Test junking $$f (please wait)..."; \
-	./${TARGET} -J0.0001 -n 1000 -b $$b -ixer -onull $$f || exit 2; \
-	./${TARGET} -J0.001 -n 1000 -b $$b -ixer -onull $$f || exit 2; \
+	./${TARGET} -J0.0001 -n 1000 -b $$b -ixer -onull $$f || exit 5; \
+	./${TARGET} -J0.001 -n 1000 -b $$b -ixer -onull $$f || exit 6; \
 	done; done; fi
 
 check-per:
-	@if test -f sample-DL-DCCH-Message-1.per ; then \
-	for f in sample-DL-DCCH-Message-[1-9].per; do \
+	@if test -f sample-DL-DCCH-Message-1-nopad.per ; then \
+	for f in sample-DL-DCCH-Message-[1-9]-nopad.per; do \
 	for b in 1 17 33 980 8192; do \
-	echo "Recoding $$f into DER into XER and back ($$b)..."; \
-	./${TARGET} -b $$b -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \
-	./${TARGET} -b $$b -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
-	./${TARGET} -b $$b -ixer -oder ./.tmp.2.$$$$ > ./.tmp.3.$$$$ || exit 2; \
-	diff ./.tmp.1.$$$$ ./.tmp.3.$$$$ || exit 2; \
+	echo "Recoding non-padded $$f into DER into XER and back ($$b)..."; \
+	./${TARGET} -b $$b -per-nopad -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \
+	./${TARGET} -b $$b -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 3; \
+	./${TARGET} -b $$b -ixer -oder ./.tmp.2.$$$$ > ./.tmp.3.$$$$ || exit 4; \
+	diff ./.tmp.1.$$$$ ./.tmp.3.$$$$ || exit 5; \
 	rm -f ./.tmp.[123].$$$$; \
 	echo "Test junking $$f (please wait)..."; \
-	./${TARGET} -J0.0001 -n 1000 -b $$b -iper -onull $$f || exit 2; \
-	./${TARGET} -J0.001 -n 1000 -b $$b -iper -onull $$f || exit 2; \
+	./${TARGET} -J0.0001 -n 1000 -b $$b -per-nopad -iper -onull $$f || exit 6; \
+	./${TARGET} -J0.001 -n 1000 -b $$b -per-nopad -iper -onull $$f || exit 7; \
 	done; done; fi
-	@if test -f sample-DL-DCCH-Message-1-nopad.per ; then \
-	for f in sample-*-[1-9]-nopad.per; do \
+	@if test -f sample-DL-DCCH-Message-1.per ; then \
+	for f in sample-*-[1-9].per; do \
 	pdu=`echo $$f | sed -E -e "s/sample-([A-Za-z-]+)-[0-9].*/\1/"`; \
 	for b in 1 17 33 980 8192; do \
-	echo "Recoding unpadded $$f into DER into XER and back ($$b)..."; \
-	./${TARGET} -b $$b -per-nopad -p $$pdu -iper -oder $$f > ./.tmp.1.$$$$ || exit 2; \
-	./${TARGET} -b $$b -p $$pdu -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 2; \
-	./${TARGET} -b $$b -p $$pdu -ixer -oper ./.tmp.2.$$$$ > ./.tmp.1.$$$$ || exit 2; \
-	diff $$f ./.tmp.1.$$$$ || exit 2; \
+	echo "Recoding $$f into DER into XER and back ($$b)..."; \
+	./${TARGET} -b $$b -p $$pdu -iper -oder $$f > ./.tmp.1.$$$$ || exit 3; \
+	./${TARGET} -b $$b -p $$pdu -iber -oxer ./.tmp.1.$$$$ > ./.tmp.2.$$$$ || exit 4; \
+	./${TARGET} -b $$b -p $$pdu -ixer -oper ./.tmp.2.$$$$ > ./.tmp.1.$$$$ || exit 5; \
+	diff $$f ./.tmp.1.$$$$ || exit 6; \
 	rm -f ./.tmp.[12].$$$$; \
 	echo "Test junking $$f (please wait)..."; \
-	./${TARGET} -J0.0001 -n 1000 -b $$b -per-nopad -iper -onull $$f || exit 2; \
-	./${TARGET} -J0.001 -n 1000 -b $$b -per-nopad -iper -onull $$f || exit 2; \
+	./${TARGET} -J0.0001 -n 1000 -b $$b -iper -onull $$f || exit 7; \
+	./${TARGET} -J0.001 -n 1000 -b $$b -iper -onull $$f || exit 8; \
 	done; done; fi
 
 distclean: clean
diff --git a/skeletons/converter-sample.c b/skeletons/converter-sample.c
index 1e541c9..4f5b8ed 100644
--- a/skeletons/converter-sample.c
+++ b/skeletons/converter-sample.c
@@ -15,7 +15,6 @@
 #include <unistd.h>	/* for getopt(3) */
 #include <string.h>	/* for strerror(3) */
 #include <sysexits.h>	/* for EX_* exit codes */
-#include <assert.h>	/* for assert(3) */
 #include <errno.h>	/* for errno */
 
 #include <asn_application.h>
@@ -43,7 +42,7 @@
        int opt_debug;	/* -d (or -dd) */
 static int opt_check;	/* -c (constraints checking) */
 static int opt_stack;	/* -s (maximum stack size) */
-static int opt_ippad;	/* -per-padded (PER input is byte-padded) */
+static int opt_nopad;	/* -per-nopad (PER input is not padded) */
 static int opt_onepdu;	/* -1 (decode single PDU) */
 
 /* Input data format selector */
@@ -146,8 +145,8 @@
 		}
 		break;
 	case 'p':
-		if(strcmp(optarg, "er-padded") == 0) {
-			opt_ippad = 1;
+		if(strcmp(optarg, "er-nopad") == 0) {
+			opt_nopad = 1;
 			break;
 		}
 #ifdef	ASN_PDU_COLLECTION
@@ -207,7 +206,7 @@
 		"  -onull       Verify (decode) input, but do not output\n");
 		if(pduType->uper_decoder)
 		fprintf(stderr,
-		"  -per-padded  Assume PER PDUs are byte-padded (-iper)\n");
+		"  -per-nopad   Assume PER PDUs are not padded (-iper)\n");
 #ifdef	ASN_PDU_COLLECTION
 		fprintf(stderr,
 		"  -p <PDU>     Specify PDU type to decode\n"
@@ -631,23 +630,24 @@
 				(void **)&structure, i_bptr, i_size);
 			break;
 		case INP_PER:
+			if(opt_nopad)
 			rval = uper_decode(opt_codec_ctx, pduType,
 				(void **)&structure, i_bptr, i_size, 0,
 				DynamicBuffer.unbits);
-			/* PER requires returns number of bits, but a catch! */
+			else
+			rval = uper_decode_complete(opt_codec_ctx, pduType,
+				(void **)&structure, i_bptr, i_size);
 			switch(rval.code) {
 			case RC_OK:
-				/* Check if input is byte-padded at the end */
-				if(opt_ippad && (rval.consumed % 8)) {
-					rval.consumed /= 8;
-					rval.consumed++;
-					ecbits = 0;
-					break;
-				}
 				/* Fall through */
 			case RC_FAIL:
-				ecbits = rval.consumed % 8;	/* Extra bits */
-				rval.consumed /= 8; /* Convert into bytes! */
+				if(opt_nopad) {
+					/* uper_decode() returns bits! */
+					/* Extra bits */
+					ecbits = rval.consumed % 8;
+					/* Convert into bytes! */
+					rval.consumed /= 8;
+				}
 				break;
 			case RC_WMORE:
 				/* PER does not support restartability */
diff --git a/skeletons/per_decoder.c b/skeletons/per_decoder.c
index de9dc55..2b3d2e2 100644
--- a/skeletons/per_decoder.c
+++ b/skeletons/per_decoder.c
@@ -2,6 +2,40 @@
 #include <asn_internal.h>
 #include <per_decoder.h>
 
+/*
+ * Decode a "Production of a complete encoding", X.691#10.1.
+ * The complete encoding contains at least one byte, and is an integral
+ * multiple of 8 bytes.
+ */
+asn_dec_rval_t
+uper_decode_complete(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size) {
+	asn_dec_rval_t rval;
+
+	rval = uper_decode(opt_codec_ctx, td, sptr, buffer, size, 0, 0);
+	if(rval.consumed) {
+		/*
+		 * We've always given 8-aligned data,
+		 * so convert bits to integral bytes.
+		 */
+		rval.consumed += 7;
+		rval.consumed >>= 3;
+	} else if(rval.code == RC_OK) {
+		if(size) {
+			if(((uint8_t *)buffer)[0] == 0) {
+				rval.consumed = 1;	/* 1 byte */
+			} else {
+				ASN_DEBUG("Expecting single zeroed byte");
+				rval.code = RC_FAIL;
+			}
+		} else {
+			/* Must contain at least 8 bits. */
+			rval.code = RC_WMORE;
+		}
+	}
+
+	return rval;
+}
+
 asn_dec_rval_t
 uper_decode(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td, void **sptr, const void *buffer, size_t size, int skip_bits, int unused_bits) {
 	asn_codec_ctx_t s_codec_ctx;
diff --git a/skeletons/per_decoder.h b/skeletons/per_decoder.h
index 26aaf59..8397a54 100644
--- a/skeletons/per_decoder.h
+++ b/skeletons/per_decoder.h
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2005, 2007 Lev Walkin <vlm@lionet.info>. All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #ifndef	_PER_DECODER_H_
@@ -15,7 +15,19 @@
 struct asn_TYPE_descriptor_s;	/* Forward declaration */
 
 /*
+ * Unaligned PER decoder of a "complete encoding" as per X.691#10.1.
+ * On success, this call always returns (.consumed >= 1), as per X.691#10.1.3.
+ */
+asn_dec_rval_t uper_decode_complete(struct asn_codec_ctx_s *opt_codec_ctx,
+	struct asn_TYPE_descriptor_s *type_descriptor,	/* Type to decode */
+	void **struct_ptr,	/* Pointer to a target structure's pointer */
+	const void *buffer,	/* Data to be decoded */
+	size_t size		/* Size of data buffer */
+	);
+
+/*
  * Unaligned PER decoder of any ASN.1 type. May be invoked by the application.
+ * WARNING: This call returns the number of BITS read from the stream. Beware.
  */
 asn_dec_rval_t uper_decode(struct asn_codec_ctx_s *opt_codec_ctx,
 	struct asn_TYPE_descriptor_s *type_descriptor,	/* Type to decode */