unber/enber work: -1 switch fixed; also made more verbose


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@965 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/ChangeLog b/ChangeLog
index 417a4f8..dfd71fe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,9 @@
 	* Conditional INTEGER/ENUMERATED representation: long vs. INTEGER_t
 	  type is chosen based on PER visible constraints (Test cases 90, 91).
 	* Union structures for CHOICE type are not anonymous anymore.
+	* Made unber(1) program more verbose: effective structure length is
+	  now displayed as L="<n>" at the closing tag. (Test check-xxber.sh).
+	* Fixed unber(1)'s -1 switch for indefinite encoding length.
 
 0.9.17:	2005-Aug-07
 
diff --git a/asn1c/Makefile.am b/asn1c/Makefile.am
index 5e3f5cb..2005f73 100644
--- a/asn1c/Makefile.am
+++ b/asn1c/Makefile.am
@@ -22,7 +22,7 @@
 
 dist_man1_MANS = asn1c.1 unber.1 enber.1
 
-check_SCRIPTS = check-parsing.sh
-TESTS = check-parsing.sh
-EXTRA_DIST = check-parsing.sh
-CLEANFILES = .check-parsing.*.tmp
+check_SCRIPTS = check-xxber.sh check-parsing.sh
+TESTS = $(check_SCRIPTS)
+EXTRA_DIST = $(check_SCRIPTS)
+CLEANFILES = .check-xxber.*.tmp .check-parsing.*.tmp
diff --git a/asn1c/Makefile.in b/asn1c/Makefile.in
index 6e9f061..e6aab3a 100644
--- a/asn1c/Makefile.in
+++ b/asn1c/Makefile.in
@@ -220,10 +220,10 @@
 
 noinst_HEADERS = sys-common.h
 dist_man1_MANS = asn1c.1 unber.1 enber.1
-check_SCRIPTS = check-parsing.sh
-TESTS = check-parsing.sh
-EXTRA_DIST = check-parsing.sh
-CLEANFILES = .check-parsing.*.tmp
+check_SCRIPTS = check-xxber.sh check-parsing.sh
+TESTS = $(check_SCRIPTS)
+EXTRA_DIST = $(check_SCRIPTS)
+CLEANFILES = .check-xxber.*.tmp .check-parsing.*.tmp
 all: all-recursive
 
 .SUFFIXES:
diff --git a/asn1c/check-parsing.sh b/asn1c/check-parsing.sh
index 37765cd..02b146e 100755
--- a/asn1c/check-parsing.sh
+++ b/asn1c/check-parsing.sh
@@ -2,6 +2,7 @@
 
 tmpfile=".check-parsing.$$.tmp"
 
+# Test diff(1) capabilities
 diff -a . . 2>/dev/null && diffArgs="-a"		# Assume text files
 diff -u . . 2>/dev/null && diffArgs="$diffArgs -u"	# Unified diff output
 
diff --git a/asn1c/check-xxber.sh b/asn1c/check-xxber.sh
new file mode 100755
index 0000000..ad36391
--- /dev/null
+++ b/asn1c/check-xxber.sh
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+ORIG="./.check-xxber.orig.$$.tmp"
+TEST="./.check-xxber.test.$$.tmp"
+
+# Test diff(1) capabilities
+diff -a . . 2>/dev/null && diffArgs="-a"		# Assume text files
+diff -u . . 2>/dev/null && diffArgs="$diffArgs -u"	# Unified diff output
+
+cat<<EOM > $ORIG
+<I O="0" T="[UNIVERSAL 16]" TL="2" V="Indefinite" A="SEQUENCE">
+<P O="2" T="[UNIVERSAL 19]" TL="2" V="2" A="PrintableString">&#x55;&#x53;</P>
+<C O="6" T="[UNIVERSAL 16]" TL="2" V="6" A="SEQUENCE">
+<P O="8" T="[UNIVERSAL 2]" TL="2" V="4" A="INTEGER">&#x31;&#xa6;&#x20;&#x47;</P>
+</C O="14" T="[UNIVERSAL 16]" A="SEQUENCE" L="8">
+EOM
+
+./enber < $ORIG - | ./unber -p -i 0 - > $TEST 2>&1
+diff $diffArgs $ORIG $TEST >/dev/null 2>&1
+diffExitCode=$?
+
+if [ $diffExitCode == "0" ]; then
+	echo "FAILED: $0: expected failure, got success"
+	exit 42;
+fi
+
+# Append necessary terminator
+echo '</I O="14" T="[UNIVERSAL 0]" TL="2" L="16">' >> $ORIG
+
+# Try trancoding again
+./enber < $ORIG - | ./unber -p -i 0 - > $TEST 2>&1
+
+diff $diffArgs $ORIG $TEST
+diffExitCode=$?
+
+rm -f $ORIG $TEST
+
+exit $diffExitCode
diff --git a/asn1c/enber.1 b/asn1c/enber.1
index 365bc46..b5e13e3 100644
--- a/asn1c/enber.1
+++ b/asn1c/enber.1
@@ -37,12 +37,12 @@
 .P
 The following example demostrates the use of comments:
 .Vb
-\&	<C T="[1]" TL="2" V="2">
-\&		<I T="[1]" TL="2" V="Indefinite">
-\&		\fB--\fR </I>
+\&	<C O="0" T="[1]" TL="2" V="2">
+\&		<I O="2" T="[1]" TL="2" V="Indefinite">
+\&		\fB--\fR </I O="4" T="[UNIVERSAL 0]" L="4">
 \&		\fB#\fR Do not terminate:
 \&		\fB#\fR the absence of end-of-content octets is intentional!
-\&	</C>
+\&	</C O="6" T="[1]" L="6">
 .Ve
 .SH SEE ALSO
 .TP
diff --git a/asn1c/unber.1 b/asn1c/unber.1
index b67c87b..7b718b9 100644
--- a/asn1c/unber.1
+++ b/asn1c/unber.1
@@ -70,10 +70,10 @@
 .Vb
 \&<I O="0" T="[UNIVERSAL 16]" TL="2" V="Indefinite" A="SEQUENCE">
 \&  <P O="2" T="[UNIVERSAL 19]" TL="2" V="2" A="PrintableString">US</P>
-\&  <C O="6" T="[UNIVERSAL 16]" TL="2" V="11" A="SEQUENCE">
+\&  <C O="6" T="[UNIVERSAL 16]" TL="2" V="6" A="SEQUENCE">
 \&    <P O="8" T="[UNIVERSAL 2]" TL="2" V="4" A="INTEGER" F>832970823</P>
-\&  </C T="[UNIVERSAL 16]" A="SEQUENCE">
-\&</I O="14" T="[UNIVERSAL 16]" A="SEQUENCE">
+\&  </C O="14" T="[UNIVERSAL 16]" A="SEQUENCE" L="8">
+\&</I O="14" T="[UNIVERSAL 0]" TL="2" L="16">
 .Ve
 .SH EXAMPLES
 Decode the given Tag/Length sequence given in hexadecimal form:
diff --git a/asn1c/unber.c b/asn1c/unber.c
index 28087d4..03de104 100644
--- a/asn1c/unber.c
+++ b/asn1c/unber.c
@@ -147,8 +147,8 @@
 	PD_FINISHED	= 0,
 	PD_EOF		= 1,
 } pd_code_e;
-static pd_code_e process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level, ssize_t limit, ssize_t *frame_size, int expect_eoc);
-static void print_TL(int fin, asn1c_integer_t offset, int level, int constr, ssize_t tlen, ber_tlv_tag_t, ber_tlv_len_t);
+static pd_code_e process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level, ssize_t limit, ber_tlv_len_t *frame_size, ber_tlv_len_t effective_size, int expect_eoc);
+static void print_TL(int fin, asn1c_integer_t offset, int level, int constr, ssize_t tlen, ber_tlv_tag_t, ber_tlv_len_t, ber_tlv_len_t effective_frame_size);
 static int print_V(const char *fname, FILE *fp, ber_tlv_tag_t, ber_tlv_len_t);
 
 /*
@@ -158,8 +158,8 @@
 process(const char *fname) {
 	FILE *fp;
 	pd_code_e pdc;
-	asn1c_integer_t offset = 0;	/* Stream decoding position */
-	ssize_t frame_size = 0;		/* Single frame size */
+	asn1c_integer_t offset = 0;		/* Stream decoding position */
+	ber_tlv_len_t frame_size = 0;		/* Single frame size */
 
 	if(strcmp(fname, "-")) {
 		fp = fopen(fname, "r");
@@ -175,7 +175,8 @@
 	 * Fetch out BER-encoded data until EOF or error.
 	 */
 	do {
-		pdc = process_deeper(fname, fp, &offset, 0, -1, &frame_size, 0);
+		pdc = process_deeper(fname, fp, &offset,
+				     0, -1, &frame_size, 0, 0);
 	} while(pdc == PD_FINISHED && !single_type_decoding);
 
 	if(fp != stdin)
@@ -189,12 +190,14 @@
 /*
  * Process the TLV recursively.
  */
-static pd_code_e process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level, ssize_t limit, ssize_t *frame_size, int expect_eoc) {
+static pd_code_e
+process_deeper(const char *fname, FILE *fp, asn1c_integer_t *offset, int level, ssize_t limit, ber_tlv_len_t *frame_size, ber_tlv_len_t effective_size, int expect_eoc) {
 	unsigned char tagbuf[32];
 	ssize_t tblen = 0;
 	pd_code_e pdc = PD_FINISHED;
 	ber_tlv_tag_t tlv_tag;
 	ber_tlv_len_t tlv_len;
+	ber_tlv_len_t local_esize = effective_size;
 	ssize_t t_len;
 	ssize_t l_len;
 
@@ -217,7 +220,7 @@
 		/* Get the next byte from the input stream */
 		ch = fgetc(fp);
 		if(ch == -1) {
-			if(tblen || limit > 0) {
+			if(limit > 0 || expect_eoc) {
 				fprintf(stderr,
 					"%s: Unexpected end of file (TL)"
 					" at %" PRIdASN "\n",
@@ -267,7 +270,8 @@
 		assert((t_len + l_len) == tblen);
 
 		if(!expect_eoc || tagbuf[0] || tagbuf[1])
-			print_TL(0, *offset, level, constr, tblen, tlv_tag, tlv_len);
+			print_TL(0, *offset, level, constr, tblen,
+				 tlv_tag, tlv_len, effective_size);
 
 		if(limit != -1) {
 			/* If limit is set, account for the TL sequence */
@@ -285,15 +289,17 @@
 
 		*offset += t_len + l_len;
 		*frame_size += t_len + l_len;
+		effective_size += t_len + l_len;
+		local_esize += t_len + l_len;
 
 		if(expect_eoc && tagbuf[0] == '\0' && tagbuf[1] == '\0') {
 			/* End of content octets */
-			print_TL(1, *offset, level - 1, 1, 2, 0, -1);
+			print_TL(1, *offset - 2, level - 1, 1, 2, 0, -1, effective_size);
 			return PD_FINISHED;
 		}
 
 		if(constr) {
-			ssize_t dec = 0;
+			ber_tlv_len_t dec = 0;
 			/*
 			 * This is a constructed type. Process recursively.
 			 */
@@ -303,15 +309,19 @@
 			}
 			pdc = process_deeper(fname, fp, offset, level + 1,
 				tlv_len == -1 ? limit : tlv_len,
-				&dec, tlv_len == -1);
+				&dec, t_len + l_len, tlv_len == -1);
 			if(pdc == PD_FAILED) return pdc;
 			if(limit != -1) {
 				assert(limit >= dec);
 				limit -= dec;
 			}
 			*frame_size += dec;
+			effective_size += dec;
+			local_esize += dec;
 			if(tlv_len == -1) {
 				tblen = 0;
+				if(pdc == PD_FINISHED && limit < 0)
+					return pdc;
 				continue;
 			}
 		} else {
@@ -325,9 +335,13 @@
 			}
 			*offset += tlv_len;
 			*frame_size += tlv_len;
+			effective_size += tlv_len;
+			local_esize += tlv_len;
 		}
 
-		print_TL(1, *offset, level, constr, tblen, tlv_tag, tlv_len);
+		print_TL(1, *offset, level, constr, tblen,
+			 tlv_tag, tlv_len, local_esize);
+		local_esize = 0;
 
 		tblen = 0;
 	} while(1);
@@ -336,7 +350,7 @@
 }
 
 static void
-print_TL(int fin, asn1c_integer_t offset, int level, int constr, ssize_t tlen, ber_tlv_tag_t tlv_tag, ber_tlv_len_t tlv_len) {
+print_TL(int fin, asn1c_integer_t offset, int level, int constr, ssize_t tlen, ber_tlv_tag_t tlv_tag, ber_tlv_len_t tlv_len, ber_tlv_len_t effective_size) {
 
 	if(fin && !constr) {
 		printf("</P>\n");
@@ -348,9 +362,8 @@
 
 	printf(constr ? ((tlv_len == -1) ? "I" : "C") : "P");
 
-	/* In case of <P>, <C>, <I>, </I> print out the offset */
-	if(fin == 0 || tlv_len == -1)
-		printf(" O=\"%" PRIdASN "\"", offset);
+	/* Print out the offset of this boundary, even if closing tag */
+	printf(" O=\"%" PRIdASN "\"", offset);
 
 	printf(" T=\"");
 	ber_tlv_tag_fwrite(tlv_tag, stdout);
@@ -372,7 +385,11 @@
 		if(str) printf(" A=\"%s\"", str);
 	}
 
-	if(fin) printf(">\n");
+	if(fin) {
+		if(constr)
+			printf(" L=\"%ld\"", (long)effective_size);
+		printf(">\n");
+	}
 }
 
 /*