upgrade: PER related changes


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@1011 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/asn-decoder-template.c b/skeletons/asn-decoder-template.c
index 348c373..c50d8b9 100644
--- a/skeletons/asn-decoder-template.c
+++ b/skeletons/asn-decoder-template.c
@@ -21,7 +21,9 @@
 #include <asn_application.h>
 
 extern asn_TYPE_descriptor_t asn_DEF;	/* ASN.1 type to be decoded */
-static asn_TYPE_descriptor_t *pduType = &asn_DEF;
+#ifdef	ASN_PDU_COLLECTION		/* Generated by asn1c: -pdu=... */
+extern asn_TYPE_descriptor_t *asn_pdu_collection[];
+#endif
 
 /*
  * Open file and parse its contens.
@@ -37,7 +39,8 @@
 /* Input data format selector */
 static enum input_format {
 	INP_BER,	/* -iber: BER input */
-	INP_XER		/* -ixer: XER input */
+	INP_XER,	/* -ixer: XER input */
+	INP_PER		/* -iper: Unaligned PER input */
 } iform;	/* -i<format> */
 
 /* Output data format selector */
@@ -56,19 +59,26 @@
 
 int
 main(int ac, char **av) {
+	static asn_TYPE_descriptor_t *pduType = &asn_DEF;
 	ssize_t suggested_bufsize = 8192;  /* close or equal to stdio buffer */
 	int number_of_iterations = 1;
 	int num;
 	int ch;
 
+	/* Figure out if Unaligned PER needs to be default */
+	if(pduType->uper_decoder)
+		iform = INP_PER;
+
 	/*
 	 * Pocess the command-line argments.
 	 */
-	while((ch = getopt(ac, av, "i:o:b:cdn:hs:")) != -1)
+	while((ch = getopt(ac, av, "i:o:b:cdn:p:hs:")) != -1)
 	switch(ch) {
 	case 'i':
 		if(optarg[0] == 'b') { iform = INP_BER; break; }
 		if(optarg[0] == 'x') { iform = INP_XER; break; }
+		if(pduType->uper_decoder
+		&& optarg[0] == 'p') { iform = INP_PER; break; }
 		fprintf(stderr, "-i<format>: '%s': improper format selector",
 			optarg);
 		exit(EX_UNAVAILABLE);
@@ -80,6 +90,21 @@
 		fprintf(stderr, "-o<format>: '%s': improper format selector",
 			optarg);
 		exit(EX_UNAVAILABLE);
+	case 'p':
+#ifdef	ASN_PDU_COLLECTION
+		{
+			asn_TYPE_descriptor_t **pdu = asn_pdu_collection;
+			if(optarg[0] < 'A' || optarg[0] > 'Z') {
+				fprintf(stderr, "Available PDU types:\n");
+				for(; *pdu; pdu++) printf("%s\n", (*pdu)->name);
+				exit(0);
+			}
+			while(*pdu && strcmp((*pdu)->name, optarg)) pdu++;
+			if(*pdu) { pduType = *pdu; break; }
+		}
+#endif	/* ASN_PDU_COLLECTION */
+		fprintf(stderr, "-p %s: Unrecognized PDU\n", optarg);
+		exit(EX_UNAVAILABLE);
 	case 'b':
 		suggested_bufsize = atoi(optarg);
 		if(suggested_bufsize < 1
@@ -115,21 +140,32 @@
 		break;
 	case 'h':
 	default:
+		fprintf(stderr, "Usage: %s [options] <data.ber> ...\n", av[0]);
+		fprintf(stderr, "Where options are:\n");
+		if(pduType->uper_decoder)
 		fprintf(stderr,
-		"Usage: %s [options] <data.ber> ...\n"
-		"Where options are:\n"
-		"  -iber   (I)  Input is in BER (Basic Encoding Rules)\n"
+		"  -iper   (I)  Input is in Unaligned PER (Packed Encoding Rules)\n");
+		fprintf(stderr,
+		"  -iber   %s  Input is in BER (Basic Encoding Rules)\n",
+			iform == INP_PER ? "   " : "(I)");
+		fprintf(stderr,
 		"  -ixer        Input is in XER (XML Encoding Rules)\n"
 		"  -oder        Output in DER (Distinguished Encoding Rules)\n"
 		"  -oxer   (O)  Output in XER (XML Encoding Rules)\n"
 		"  -otext       Output in plain semi-structured text (dump)\n"
-		"  -onull       Verify (decode) input, but do not output\n"
+		"  -onull       Verify (decode) input, but do not output\n");
+#ifdef	ASN_PDU_COLLECTION
+		fprintf(stderr,
+		"  -p <PDU>     Specify PDU type to decode\n"
+		"  -p list      List available PDUs\n");
+#endif	/* ASN_PDU_COLLECTION */
+		fprintf(stderr,
 		"  -b <size>    Set the i/o buffer size (default is %ld)\n"
 		"  -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"
-		, av[0], (long)suggested_bufsize);
+		, (long)suggested_bufsize);
 		exit(EX_USAGE);
 	}
 
@@ -210,7 +246,8 @@
 
 /* Dump the buffer */
 static int write_out(const void *buffer, size_t size, void *key) {
-	return (fwrite(buffer, 1, size, key) == size) ? 0 : -1;
+	FILE *fp = (FILE *)key;
+	return (fwrite(buffer, 1, size, fp) == size) ? 0 : -1;
 }
 
 static char *buffer;
@@ -302,6 +339,7 @@
 	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;
 
@@ -330,6 +368,13 @@
 			rval = xer_decode(opt_codec_ctx, pduType,
 				(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);
+			break;
 		}
 		DEBUG("decode(%ld) consumed %ld, code %d",
 			(long)buf_len, (long)rval.consumed, rval.code);