introduce generic encoder
diff --git a/skeletons/converter-sample.c b/skeletons/converter-sample.c
index 8ec45f2..bbf276c 100644
--- a/skeletons/converter-sample.c
+++ b/skeletons/converter-sample.c
@@ -22,20 +22,31 @@
 #include <asn_internal.h>    /* for ASN__DEFAULT_STACK_MAX */
 
 /* Convert "Type" defined by -DPDU into "asn_DEF_Type" */
+
+#ifndef NO_ASN_PDU
+#ifndef PDU
+#error Define -DPDU to compile this sample converter.
+#endif
+#ifdef    ASN_PDU_COLLECTION        /* Generated by asn1c: -pdu=... */
+extern asn_TYPE_descriptor_t *asn_pdu_collection[];
+#endif
 #define    ASN_DEF_PDU(t)    asn_DEF_ ## t
 #define    DEF_PDU_Type(t)    ASN_DEF_PDU(t)
 #define    PDU_Type    DEF_PDU_Type(PDU)
 
 extern asn_TYPE_descriptor_t PDU_Type;    /* ASN.1 type to be decoded */
-#ifdef    ASN_PDU_COLLECTION        /* Generated by asn1c: -pdu=... */
-extern asn_TYPE_descriptor_t *asn_pdu_collection[];
-#endif
+#define PDU_Type_Ptr (&PDU_Type)
+#else   /* NO_ASN_PDU */
+#define PDU_Type_Ptr    NULL
+#endif  /* NO_ASN_PDU */
 
 /*
  * Open file and parse its contens.
  */
-static void *data_decode_from_file(asn_TYPE_descriptor_t *asnTypeOfPDU,
-    FILE *file, const char *name, ssize_t suggested_bufsize, int first_pdu);
+static void *data_decode_from_file(enum asn_transfer_syntax,
+                                   asn_TYPE_descriptor_t *asnTypeOfPDU,
+                                   FILE *file, const char *name,
+                                   ssize_t suggested_bufsize, int first_pdu);
 static int write_out(const void *buffer, size_t size, void *key);
 static FILE *argument_to_file(char *av[], int idx);
 static char *argument_to_name(char *av[], int idx);
@@ -46,24 +57,6 @@
 static int opt_nopad;    /* -per-nopad (PER input is not padded) */
 static int opt_onepdu;    /* -1 (decode single PDU) */
 
-/* Input data format selector */
-static enum input_format {
-    INP_BER,    /* -iber: BER input */
-    INP_XER,    /* -ixer: XER input */
-    INP_OER,    /* -ioer: OER input */
-    INP_PER        /* -iper: Unaligned PER input */
-} iform;    /* -i<format> */
-
-/* Output data format selector */
-static enum output_format {
-    OUT_XER,    /* -oxer: XER (XML) output */
-    OUT_DER,    /* -oder: DER (BER) output */
-    OUT_OER,    /* -ooer: Canonical OER output */
-    OUT_PER,    /* -oper: Unaligned PER output */
-    OUT_TEXT,    /* -otext: semi-structured text */
-    OUT_NULL    /* -onull: No pretty-printing */
-} oform;    /* -o<format> */
-
 #ifdef    JUNKTEST        /* Enable -J <probability> */
 #define    JUNKOPT    "J:"
 static double opt_jprob;    /* Junk bit probability */
@@ -85,20 +78,60 @@
     fprintf(stderr, "\n");
 }
 
+static const char *
+ats_simple_name(enum asn_transfer_syntax syntax) {
+    switch(syntax) {
+    case ATS_INVALID:
+        return "/dev/null";
+    case ATS_NONSTANDARD_PLAINTEXT:
+        return "plaintext";
+    case ATS_BER:
+        return "BER";
+    case ATS_DER:
+        return "DER";
+    case ATS_CER:
+        return "CER";
+    case ATS_BASIC_OER:
+    case ATS_CANONICAL_OER:
+        return "OER";
+    case ATS_BASIC_XER:
+    case ATS_CANONICAL_XER:
+        return "XER";
+    case ATS_UNALIGNED_BASIC_PER:
+    case ATS_UNALIGNED_CANONICAL_PER:
+        return "PER";
+    default:
+        return "<?>";
+    }
+}
+
 int
 main(int ac, char *av[]) {
     FILE *binary_out;
-    static asn_TYPE_descriptor_t *pduType = &PDU_Type;
+    static asn_TYPE_descriptor_t *pduType = PDU_Type_Ptr;
     ssize_t suggested_bufsize = 8192;  /* close or equal to stdio buffer */
     int number_of_iterations = 1;
     int num;
     int ch;
+    enum asn_transfer_syntax isyntax = ATS_INVALID;
+    enum asn_transfer_syntax osyntax = ATS_INVALID;
+
+#ifndef  PDU
+    if(!pduType) {
+        fprintf(stderr, "No -DPDU defined during compilation.\n");
+#ifdef  NO_ASN_PDU
+        exit(0);
+#else
+        exit(EX_SOFTWARE);
+#endif
+    }
+#endif
 
     /* Figure out if specialty decoder needs to be default */
     if(pduType->op->oer_decoder)
-        iform = INP_OER;
+        isyntax = ATS_BASIC_OER;
     else if(pduType->op->uper_decoder)
-        iform = INP_PER;
+        isyntax = ATS_UNALIGNED_BASIC_PER;
 
     /*
      * Pocess the command-line argments.
@@ -106,24 +139,24 @@
     while((ch = getopt(ac, av, "i:o:1b:cdn:p:hs:" JUNKOPT)) != -1)
     switch(ch) {
     case 'i':
-        if(optarg[0] == 'b') { iform = INP_BER; break; }
-        if(optarg[0] == 'x') { iform = INP_XER; break; }
+        if(optarg[0] == 'b') { isyntax = ATS_BER; break; }
+        if(optarg[0] == 'x') { isyntax = ATS_BASIC_XER; break; }
         if(pduType->op->oer_decoder
-        && optarg[0] == 'o') { iform = INP_OER; break; }
+        && optarg[0] == 'o') { isyntax = ATS_BASIC_OER; break; }
         if(pduType->op->uper_decoder
-        && optarg[0] == 'p') { iform = INP_PER; break; }
+        && optarg[0] == 'p') { isyntax = ATS_UNALIGNED_BASIC_PER; break; }
         fprintf(stderr, "-i<format>: '%s': improper format selector\n",
             optarg);
         exit(EX_UNAVAILABLE);
     case 'o':
-        if(optarg[0] == 'd') { oform = OUT_DER; break; }
+        if(optarg[0] == 'd') { osyntax = ATS_DER; break; }
         if(pduType->op->oer_encoder
-        && optarg[0] == 'o') { oform = OUT_OER; break; }
+        && optarg[0] == 'o') { osyntax = ATS_CANONICAL_OER; break; }
         if(pduType->op->uper_encoder
-        && optarg[0] == 'p') { oform = OUT_PER; break; }
-        if(optarg[0] == 'x') { oform = OUT_XER; break; }
-        if(optarg[0] == 't') { oform = OUT_TEXT; break; }
-        if(optarg[0] == 'n') { oform = OUT_NULL; break; }
+        && optarg[0] == 'p') { osyntax = ATS_UNALIGNED_CANONICAL_PER; break; }
+        if(optarg[0] == 'x') { osyntax = ATS_BASIC_XER; break; }
+        if(optarg[0] == 't') { osyntax = ATS_NONSTANDARD_PLAINTEXT; break; }
+        if(optarg[0] == 'n') { osyntax = ATS_INVALID; break; }
         fprintf(stderr, "-o<format>: '%s': improper format selector\n",
             optarg);
         exit(EX_UNAVAILABLE);
@@ -219,14 +252,14 @@
         if(pduType->op->oer_decoder)
         fprintf(stderr,
         "  -ioer        Input is in OER (Octet Encoding Rules)%s\n",
-            iform == INP_OER ? " (DEFAULT)" : "");
+            isyntax == ATS_BASIC_OER ? " (DEFAULT)" : "");
         if(pduType->op->uper_decoder)
         fprintf(stderr,
         "  -iper        Input is in Unaligned PER (Packed Encoding Rules)%s\n",
-            iform == INP_PER ? " (DEFAULT)" : "");
+            isyntax == ATS_UNALIGNED_BASIC_PER ? " (DEFAULT)" : "");
         fprintf(stderr,
         "  -iber        Input is in BER (Basic Encoding Rules)%s\n",
-            iform == INP_BER ? " (DEFAULT)" : "");
+            isyntax == ATS_BER ? " (DEFAULT)" : "");
         fprintf(stderr,
         "  -ixer        Input is in XER (XML Encoding Rules)\n");
         if(pduType->op->oer_encoder)
@@ -273,7 +306,7 @@
     }
 
     if(isatty(1)) {
-        const int is_text_output = oform == OUT_TEXT || oform == OUT_XER;
+        const int is_text_output = osyntax == ATS_NONSTANDARD_PLAINTEXT || osyntax == ATS_CANONICAL_XER || osyntax == ATS_BASIC_XER;
         if(is_text_output) {
             binary_out = stdout;
         } else {
@@ -301,11 +334,11 @@
         char *name = argument_to_name(av, ac_i);
         int first_pdu;
 
-        for(first_pdu = 1; first_pdu || !opt_onepdu; first_pdu = 0) {
+        for(first_pdu = 1; file && (first_pdu || !opt_onepdu); first_pdu = 0) {
             /*
              * Decode the encoded structure from file.
              */
-            structure = data_decode_from_file(pduType, file, name,
+            structure = data_decode_from_file(isyntax, pduType, file, name,
                                               suggested_bufsize, first_pdu);
             if(!structure) {
                 if(errno) {
@@ -330,59 +363,24 @@
                 }
             }
 
-            switch(oform) {
-            case OUT_NULL:
+            if(osyntax == ATS_INVALID) {
 #ifdef JUNKTEST
-                if(opt_jprob == 0.0)
-#endif
+                if(opt_jprob == 0.0) {
                     fprintf(stderr, "%s: decoded successfully\n", name);
-                break;
-            case OUT_TEXT: /* -otext */
-                asn_fprint(stdout, pduType, structure);
-                break;
-            case OUT_XER: /* -oxer */
-                if(xer_fprint(stdout, pduType, structure)) {
-                    fprintf(stderr, "%s: Cannot convert %s into XML\n", name,
-                            pduType->name);
-                    exit(EX_UNAVAILABLE);
                 }
-                break;
-            case OUT_DER:
-                erv = der_encode(pduType, structure, write_out, binary_out);
-                if(erv.encoded < 0) {
-                    fprintf(stderr, "%s: Cannot convert %s into DER\n", name,
-                            pduType->name);
-                    exit(EX_UNAVAILABLE);
-                }
-                DEBUG("Encoded in %ld bytes of DER", (long)erv.encoded);
-                break;
-            case OUT_OER:
-#ifdef  ASN_DISABLE_OER_SUPPORT
-                erv.encoded = -1;
 #else
-                erv = oer_encode(pduType, structure, write_out, binary_out);
+                fprintf(stderr, "%s: decoded successfully\n", name);
 #endif
-                if(erv.encoded < 0) {
-                    fprintf(stderr, "%s: Cannot convert %s into OER\n", name,
-                            pduType->name);
+            } else {
+                erv = asn_encode(NULL, osyntax, pduType, structure, write_out, binary_out);
+
+                if(erv.encoded == -1) {
+                    fprintf(stderr, "%s: Cannot convert %s into %s\n", name,
+                            pduType->name, ats_simple_name(osyntax));
                     exit(EX_UNAVAILABLE);
                 }
-                DEBUG("Encoded in %ld bytes of OER", (long)erv.encoded);
-                break;
-            case OUT_PER:
-#ifdef  ASN_DISABLE_PER_SUPPORT
-                erv.encoded = -1;
-#else
-                erv = uper_encode(pduType, structure, write_out, binary_out);
-#endif
-                if(erv.encoded < 0) {
-                    fprintf(stderr,
-                            "%s: Cannot convert %s into Unaligned PER\n", name,
-                            pduType->name);
-                    exit(EX_UNAVAILABLE);
-                }
-                DEBUG("Encoded in %ld bits of UPER", (long)erv.encoded);
-                break;
+                DEBUG("Encoded in %zd bytes of %s", erv.encoded,
+                      ats_simple_name(osyntax));
             }
 
             ASN_STRUCT_FREE(*pduType, structure);
@@ -610,7 +608,7 @@
 }
 
 static void *
-data_decode_from_file(asn_TYPE_descriptor_t *pduType, FILE *file, const char *name, ssize_t suggested_bufsize, int on_first_pdu) {
+data_decode_from_file(enum asn_transfer_syntax isyntax, asn_TYPE_descriptor_t *pduType, FILE *file, const char *name, ssize_t suggested_bufsize, int on_first_pdu) {
     static uint8_t *fbuf;
     static ssize_t fbuf_size;
     static asn_codec_ctx_t s_codec_ctx;
@@ -688,12 +686,12 @@
         junk_bytes_with_probability(i_bptr, i_size, opt_jprob);
 #endif
 
-        switch(iform) {
-        case INP_BER:
+        switch(isyntax) {
+        case ATS_BER:
             rval = ber_decode(opt_codec_ctx, pduType,
                 (void **)&structure, i_bptr, i_size);
             break;
-        case INP_OER:
+        case ATS_BASIC_OER:
 #ifdef ASN_DISABLE_OER_SUPPORT
             rval.code = RC_FAIL;
             rval.consumed = 0;
@@ -702,11 +700,11 @@
                 (void **)&structure, i_bptr, i_size);
 #endif
             break;
-        case INP_XER:
+        case ATS_BASIC_XER:
             rval = xer_decode(opt_codec_ctx, pduType,
                 (void **)&structure, i_bptr, i_size);
             break;
-        case INP_PER:
+        case ATS_UNALIGNED_BASIC_PER:
 #ifdef ASN_DISABLE_PER_SUPPORT
             rval.code = RC_FAIL;
             rval.consumed = 0;
@@ -740,6 +738,9 @@
                 break;
             }
             break;
+        default:
+            rval.consumed = 0;
+            /* Fall through */
         }
         DEBUG("decode(%ld) consumed %ld+%db (%ld), code %d",
             (long)DynamicBuffer.length,
@@ -804,7 +805,7 @@
      */
     if(on_first_pdu
     || DynamicBuffer.length
-    || new_offset - old_offset > ((iform == INP_XER)?sizeof("\r\n")-1:0)
+    || new_offset - old_offset > ((isyntax == ATS_BASIC_XER)?sizeof("\r\n")-1:0)
     ) {
 
 #ifdef    JUNKTEST