added stack control to PER

diff --git a/skeletons/asn-decoder-template.c b/skeletons/asn-decoder-template.c
index c50d8b9..b428064 100644
--- a/skeletons/asn-decoder-template.c
+++ b/skeletons/asn-decoder-template.c
@@ -19,6 +19,7 @@
 #include <errno.h>	/* for errno */
 
 #include <asn_application.h>
+#include <asn_internal.h>	/* for _ASN_DEFAULT_STACK_MAX */
 
 extern asn_TYPE_descriptor_t asn_DEF;	/* ASN.1 type to be decoded */
 #ifdef	ASN_PDU_COLLECTION		/* Generated by asn1c: -pdu=... */
@@ -51,11 +52,17 @@
 	OUT_NULL	/* -onull: No pretty-printing */
 } oform;	/* -o<format> */
 
-#define	DEBUG(fmt, args...)	do {		\
-	if(!opt_debug) break;			\
-	fprintf(stderr, fmt, ##args);		\
-	fprintf(stderr, "\n");			\
-} while(0)
+/* Debug output function */
+static inline void
+DEBUG(const char *fmt, ...) {
+	va_list ap;
+	if(!opt_debug) return;
+	fprintf(stderr, "AD: ");
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+}
 
 int
 main(int ac, char **av) {
@@ -131,9 +138,9 @@
 		break;
 	case 's':
 		opt_stack = atoi(optarg);
-		if(opt_stack <= 0) {
+		if(opt_stack < 0) {
 			fprintf(stderr,
-				"-s %s: Value greater than 0 expected\n",
+				"-s %s: Non-negative value expected\n",
 				optarg);
 			exit(EX_UNAVAILABLE);
 		}
@@ -164,8 +171,8 @@
 		"  -c           Check ASN.1 constraints after decoding\n"
 		"  -d           Enable debugging (-dd is even better)\n"
 		"  -n <num>     Process files <num> times\n"
-		"  -s <size>    Set the stack usage limit\n"
-		, (long)suggested_bufsize);
+		"  -s <size>    Set the stack usage limit (default is %d)\n"
+		, (long)suggested_bufsize, _ASN_DEFAULT_STACK_MAX);
 		exit(EX_USAGE);
 	}
 
@@ -250,11 +257,12 @@
 	return (fwrite(buffer, 1, size, fp) == size) ? 0 : -1;
 }
 
-static char *buffer;
-static size_t buf_offset;	/* Offset from the start */
+static char  *buffer;
 static size_t buf_len;		/* Length of meaningful contents */
-static size_t buf_size;	/* Allocated memory */
-static off_t buf_shifted;	/* Number of bytes ever shifted */
+static size_t buf_size;		/* Allocated memory */
+static size_t buf_offset;	/* Offset from the start */
+static off_t  buf_shifted;	/* Number of bytes ever shifted */
+static int    buf_nreallocs;	/* Number of reallocations */
 
 #define	bufptr	(buffer + buf_offset)
 #define	bufend	(buffer + buf_offset + buf_len)
@@ -262,13 +270,13 @@
 /*
  * Ensure that the buffer contains at least this amount of free space.
  */
-static void buf_extend(size_t bySize) {
+static void buf_extend(const void *data2add, size_t bySize) {
 
 	DEBUG("buf_extend(%ld) { o=%ld l=%ld s=%ld }",
 		(long)bySize, (long)buf_offset, (long)buf_len, (long)buf_size);
 
 	if(buf_size >= (buf_offset + buf_len + bySize)) {
-		return;	/* Nothing to do */
+		/* Nothing to do */
 	} else if(bySize <= buf_offset) {
 		DEBUG("\tContents shifted by %ld", (long)buf_offset);
 
@@ -278,17 +286,22 @@
 		buf_offset = 0;
 	} else {
 		size_t newsize = (buf_size << 2) + bySize;
-		void *p = realloc(buffer, newsize);
-		if(p) {
-			buffer = (char *)p;
-			buf_size = newsize;
-
-			DEBUG("\tBuffer reallocated to %ld", (long)newsize);
-		} else {
+		void *p = malloc(newsize);
+		if(!p) {
 			perror("realloc()");
 			exit(EX_OSERR);
 		}
+		memcpy(p, buffer, buf_len);
+		free(buffer);
+		buffer = (char *)p;
+		buf_size = newsize;
+		buf_offset = 0;
+		DEBUG("\tBuffer reallocated to %ld, %d time",
+			(long)newsize, ++buf_nreallocs);
 	}
+
+	memcpy(buffer + buf_offset + buf_len, data2add, bySize);
+	buf_len += bySize;
 }
 
 static void *data_decode_from_file(asn_TYPE_descriptor_t *pduType, const char *fname, ssize_t suggested_bufsize) {
@@ -310,7 +323,7 @@
 		DEBUG("Processing file %s", fname);
 		fp = fopen(fname, "r");
 	} else {
-		DEBUG("Processing standard input");
+		DEBUG("Processing %s", "standard input");
 		fname = "stdin";
 		fp = stdin;
 	}
@@ -330,8 +343,10 @@
 		fbuf_size = suggested_bufsize;
 	}
 
+	buf_nreallocs = 0;
 	buf_shifted = 0;
 	buf_offset = 0;
+	buf_size = 0;
 	buf_len = 0;
 
 	/* Pretend immediate EOF */
@@ -339,19 +354,15 @@
 	rval.consumed = 0;
 
 	while((rd = fread(fbuf, 1, fbuf_size, fp)) || !feof(fp)) {
-		asn_per_data_t pd;
 		char  *i_bptr;
 		size_t i_size;
 
 		/*
 		 * Copy the data over, or use the original buffer.
 		 */
-		if(buf_len) {
+		if(buf_size) {
 			/* Append the new data into the intermediate buffer */
-			buf_extend(rd);
-			memcpy(bufend, fbuf, rd);
-			buf_len += rd;
-
+			buf_extend(fbuf, rd);
 			i_bptr = bufptr;
 			i_size = buf_len;
 		} else {
@@ -369,36 +380,35 @@
 				(void **)&structure, i_bptr, i_size);
 			break;
 		case INP_PER:
-			pd.buffer = (uint8_t *)i_bptr;
-			pd.nboff  = 0;
-			pd.nbits  = i_size * 8;
-			rval = pduType->uper_decoder(opt_codec_ctx, pduType, 0,
-				(void **)&structure, &pd);
+			rval = uper_decode(opt_codec_ctx, pduType,
+				(void **)&structure, i_bptr, i_size);
 			break;
 		}
-		DEBUG("decode(%ld) consumed %ld, code %d",
-			(long)buf_len, (long)rval.consumed, rval.code);
+		DEBUG("decode(%ld) consumed %ld (%ld), code %d",
+			(long)buf_len, (long)rval.consumed, (long)i_size,
+			rval.code);
 
-		if(buf_len == 0) {
+		if(buf_size == 0) {
 			/*
 			 * Switch the remainder into the intermediate buffer.
 			 */
 			if(rval.code != RC_FAIL && rval.consumed < rd) {
-				buf_extend(rd - rval.consumed);
-				memcpy(bufend,
-					fbuf + rval.consumed,
-					rd - rval.consumed);
-				buf_len = rd - rval.consumed;
+				buf_extend(fbuf + rval.consumed,
+					     rd - rval.consumed);
+				rval.consumed = 0;
 			}
 		}
 
 		switch(rval.code) {
 		case RC_OK:
-			DEBUG("RC_OK, finishing up");
+			DEBUG("RC_OK, finishing up with %ld",
+				(long)rval.consumed);
 			if(fp != stdin) fclose(fp);
 			return structure;
 		case RC_WMORE:
-			DEBUG("RC_WMORE, continuing...");
+			DEBUG("RC_WMORE, continuing %ld with %ld..%ld..%ld",
+				(long)rval.consumed, (long)buf_offset,
+				(long)buf_len, (long)buf_size);
 			/*
 			 * Adjust position inside the source buffer.
 			 */