clean-up; removed unnecessary field from type descriptor


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@400 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/ANY.c b/skeletons/ANY.c
index ed529c5..1825da1 100644
--- a/skeletons/ANY.c
+++ b/skeletons/ANY.c
@@ -18,9 +18,8 @@
 	ANY_encode_xer,
 	0, /* Use generic outmost tag fetcher */
 	0, 0, 0, 0,
-	-1,	/* Both ways are fine (primitive and constructed) */
 	0, 0,	/* No members */
-	(void *)1	/* Special indicator that this is an ANY type */
+	(void *)2	/* Special indicator that this is an ANY type */
 };
 
 
@@ -139,7 +138,7 @@
 		size_t nsize = (arg->size ? arg->size << 2 : 16) + size;
 		void *p = REALLOC(arg->buffer, nsize);
 		if(!p) return -1;
-		(void *)arg->buffer = p;
+		arg->buffer = (uint8_t *)p;
 		arg->size = nsize;
 	}
 
diff --git a/skeletons/BIT_STRING.c b/skeletons/BIT_STRING.c
index 274dec9..e0e2507 100644
--- a/skeletons/BIT_STRING.c
+++ b/skeletons/BIT_STRING.c
@@ -4,6 +4,7 @@
  */
 #include <asn_internal.h>
 #include <BIT_STRING.h>
+#include <asn_internal.h>
 
 /*
  * BIT STRING basic type description.
@@ -27,9 +28,8 @@
 	asn1_DEF_BIT_STRING_tags,	/* Same as above */
 	sizeof(asn1_DEF_BIT_STRING_tags)
 	  / sizeof(asn1_DEF_BIT_STRING_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
-	(void *)-1	/* Special indicator that this is a BIT STRING */
+	(void *)1	/* Special indicator that this is a BIT STRING */
 };
 
 /*
@@ -144,9 +144,10 @@
 
 	(void)td;	/* Unused argument */
 
-	if(!st || !st->buf) return cb("<absent>", 8, app_key);
+	if(!st || !st->buf)
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
-	ilevel += 4;
+	ilevel++;
 	buf = st->buf;
 	end = buf + st->size;
 
@@ -156,12 +157,9 @@
 	for(buf++; buf < end; buf++) {
 		if(((buf - st->buf) - 1) % 16 == 0 && (st->size > 17)
 				&& buf != st->buf+1) {
-			int i;
-			/* Indentation */
-			if(cb("\n", 1, app_key)) return -1;
-			for(i = 0; i < ilevel; i++) cb(" ", 1, app_key);
+			_i_INDENT(1);
 			/* Dump the string */
-			if(cb(scratch, p - scratch, app_key)) return -1;
+			if(cb(scratch, p - scratch, app_key) < 0) return -1;
 			p = scratch;
 		}
 		*p++ = h2c[*buf >> 4];
@@ -173,13 +171,11 @@
 		p--;	/* Eat the tailing space */
 
 		if((st->size > 17)) {
-			int i;
-			if(cb("\n", 1, app_key)) return -1;
-			for(i = 0; i < ilevel; i++) cb(" ", 1, app_key);
+			_i_INDENT(1);
 		}
 
 		/* Dump the incomplete 16-bytes row */
-		if(cb(scratch, p - scratch, app_key))
+		if(cb(scratch, p - scratch, app_key) < 0)
 			return -1;
 	}
 
diff --git a/skeletons/BMPString.c b/skeletons/BMPString.c
index bdbd40d..2a11299 100644
--- a/skeletons/BMPString.c
+++ b/skeletons/BMPString.c
@@ -28,7 +28,6 @@
 	asn1_DEF_BMPString_tags,
 	sizeof(asn1_DEF_BMPString_tags)
 	  / sizeof(asn1_DEF_BMPString_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -101,7 +100,8 @@
 	(void)td;	/* Unused argument */
 	(void)ilevel;	/* Unused argument */
 
-	if(!st || !st->buf) return cb("<absent>", 8, app_key);
+	if(!st || !st->buf)
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	if(BMPString__dump(st, cb, app_key) < 0)
 		return -1;
diff --git a/skeletons/BOOLEAN.c b/skeletons/BOOLEAN.c
index c7a1cac..ef6926a 100644
--- a/skeletons/BOOLEAN.c
+++ b/skeletons/BOOLEAN.c
@@ -25,7 +25,6 @@
 	sizeof(asn1_DEF_BOOLEAN_tags) / sizeof(asn1_DEF_BOOLEAN_tags[0]),
 	asn1_DEF_BOOLEAN_tags,	/* Same as above */
 	sizeof(asn1_DEF_BOOLEAN_tags) / sizeof(asn1_DEF_BOOLEAN_tags[0]),
-	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -43,7 +42,7 @@
 	ber_tlv_len_t lidx;
 
 	if(st == NULL) {
-		(void *)st = *bool_value = CALLOC(1, sizeof(*st));
+		st = (BOOLEAN_t *)(*bool_value = CALLOC(1, sizeof(*st)));
 		if(st == NULL) {
 			rval.code = RC_FAIL;
 			rval.consumed = 0;
@@ -57,7 +56,7 @@
 	/*
 	 * Check tags.
 	 */
-	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, &length, 0);
+	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, 0, &length, 0);
 	if(rval.code != RC_OK)
 		return rval;
 
@@ -101,7 +100,7 @@
 	asn_enc_rval_t erval;
 	BOOLEAN_t *st = (BOOLEAN_t *)sptr;
 
-	erval.encoded = der_write_tags(td, 1, tag_mode, tag, cb, app_key);
+	erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key);
 	if(erval.encoded == -1) {
 		erval.failed_type = td;
 		erval.structure_ptr = sptr;
@@ -110,11 +109,10 @@
 
 	if(cb) {
 		uint8_t bool_value;
-		ssize_t ret;
 
-		bool_value = *st?0xff:0; /* 0xff mandated by DER */
-		ret = cb(&bool_value, 1, app_key);
-		if(ret == -1) {
+		bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */
+
+		if(cb(&bool_value, 1, app_key) < 0) {
 			erval.encoded = -1;
 			erval.failed_type = td;
 			erval.structure_ptr = sptr;
@@ -154,18 +152,26 @@
 BOOLEAN_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 	asn_app_consume_bytes_f *cb, void *app_key) {
 	const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
+	const char *buf;
+	size_t buflen;
 
 	(void)td;	/* Unused argument */
 	(void)ilevel;	/* Unused argument */
 
 	if(st) {
-		if(*st)
-			return cb("TRUE", 4, app_key);
-		else
-			return cb("FALSE", 5, app_key);
+		if(*st) {
+			buf = "TRUE";
+			buflen = 4;
+		} else {
+			buf = "FALSE";
+			buflen = 5;
+		}
 	} else {
-		return cb("<absent>", 8, app_key);
+		buf = "<absent>";
+		buflen = 8;
 	}
+
+	return (cb(buf, buflen, app_key) < 0) ? -1 : 0;
 }
 
 void
diff --git a/skeletons/ENUMERATED.c b/skeletons/ENUMERATED.c
index 158119d..821a467 100644
--- a/skeletons/ENUMERATED.c
+++ b/skeletons/ENUMERATED.c
@@ -4,6 +4,7 @@
  */
 #include <asn_internal.h>
 #include <ENUMERATED.h>
+#include <ber_codec_prim.h>
 
 /*
  * ENUMERATED basic type description.
@@ -13,10 +14,10 @@
 };
 asn1_TYPE_descriptor_t asn1_DEF_ENUMERATED = {
 	"ENUMERATED",
-	INTEGER_free,			/* Implemented in terms of INTEGER */
+	ASN__PRIMITIVE_TYPE_free,
 	INTEGER_print,			/* Implemented in terms of INTEGER */
 	asn_generic_no_constraint,
-	INTEGER_decode_ber,		/* Implemented in terms of INTEGER */
+	ber_decode_primitive,
 	INTEGER_encode_der,		/* Implemented in terms of INTEGER */
 	0,				/* Not implemented yet */
 	INTEGER_encode_xer,		/* Implemented in terms of INTEGER */
@@ -25,7 +26,6 @@
 	sizeof(asn1_DEF_ENUMERATED_tags) / sizeof(asn1_DEF_ENUMERATED_tags[0]),
 	asn1_DEF_ENUMERATED_tags,	/* Same as above */
 	sizeof(asn1_DEF_ENUMERATED_tags) / sizeof(asn1_DEF_ENUMERATED_tags[0]),
-	0,	/* Primitive */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/GeneralString.c b/skeletons/GeneralString.c
index c9d8248..02c1c7e 100644
--- a/skeletons/GeneralString.c
+++ b/skeletons/GeneralString.c
@@ -28,7 +28,6 @@
 	asn1_DEF_GeneralString_tags,
 	sizeof(asn1_DEF_GeneralString_tags)
 	  / sizeof(asn1_DEF_GeneralString_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index 8f8fff2..161898f 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -110,7 +110,9 @@
  * GeneralizedTime basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_GeneralizedTime_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (24 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (24 << 2)),	/* [UNIVERSAL 24] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)),  /* [UNIVERSAL 26] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))    /* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_GeneralizedTime = {
 	"GeneralizedTime",
@@ -124,11 +126,10 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_GeneralizedTime_tags,
 	sizeof(asn1_DEF_GeneralizedTime_tags)
-	  / sizeof(asn1_DEF_GeneralizedTime_tags[0]),
-	asn1_DEF_GeneralizedTime_tags,	/* Same as above */
+	  / sizeof(asn1_DEF_GeneralizedTime_tags[0]) - 2,
+	asn1_DEF_GeneralizedTime_tags,
 	sizeof(asn1_DEF_GeneralizedTime_tags)
 	  / sizeof(asn1_DEF_GeneralizedTime_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -242,16 +243,16 @@
 
 		errno = EPERM;
 		if(asn_GT2time(st, &tm, 1) == -1 && errno != EPERM)
-			return cb("<bad-value>", 11, app_key);
+			return (cb("<bad-value>", 11, app_key) < 0) ? -1 : 0;
 
 		ret = snprintf(buf, sizeof(buf),
 			"%04d-%02d-%02d %02d:%02d%02d (GMT)",
 			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
 			tm.tm_hour, tm.tm_min, tm.tm_sec);
 		assert(ret > 0 && ret < (int)sizeof(buf));
-		return cb(buf, ret, app_key);
+		return (cb(buf, ret, app_key) < 0) ? -1 : 0;
 	} else {
-		return cb("<absent>", 8, app_key);
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 	}
 }
 
@@ -493,7 +494,7 @@
 	}
 
 	/* Pre-allocate a buffer of sufficient yet small length */
-	(void *)buf = MALLOC(buf_size);
+	buf = (char *)MALLOC(buf_size);
 	if(!buf) return 0;
 
 	gmtoff = GMTOFF(*tm);
@@ -536,7 +537,7 @@
 		if(opt_gt->buf)
 			FREEMEM(opt_gt->buf);
 	} else {
-		(void *)opt_gt = CALLOC(1, sizeof *opt_gt);
+		opt_gt = (GeneralizedTime_t *)CALLOC(1, sizeof *opt_gt);
 		if(!opt_gt) { free(buf); return 0; }
 	}
 
diff --git a/skeletons/GraphicString.c b/skeletons/GraphicString.c
index e8fa797..98a8d48 100644
--- a/skeletons/GraphicString.c
+++ b/skeletons/GraphicString.c
@@ -28,7 +28,6 @@
 	asn1_DEF_GraphicString_tags,
 	sizeof(asn1_DEF_GraphicString_tags)
 	  / sizeof(asn1_DEF_GraphicString_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/IA5String.c b/skeletons/IA5String.c
index a2c828d..e9d2a61 100644
--- a/skeletons/IA5String.c
+++ b/skeletons/IA5String.c
@@ -28,7 +28,6 @@
 	asn1_DEF_IA5String_tags,
 	sizeof(asn1_DEF_IA5String_tags)
 	  / sizeof(asn1_DEF_IA5String_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/INTEGER.c b/skeletons/INTEGER.c
index 73b5959..89be79e 100644
--- a/skeletons/INTEGER.c
+++ b/skeletons/INTEGER.c
@@ -4,6 +4,7 @@
  */
 #include <asn_internal.h>
 #include <INTEGER.h>
+#include <ber_codec_prim.h>	/* Encoder and decoder of a primitive */
 #include <assert.h>
 #include <errno.h>
 
@@ -15,10 +16,10 @@
 };
 asn1_TYPE_descriptor_t asn1_DEF_INTEGER = {
 	"INTEGER",
-	INTEGER_free,
+	ASN__PRIMITIVE_TYPE_free,
 	INTEGER_print,
 	asn_generic_no_constraint,
-	INTEGER_decode_ber,
+	ber_decode_primitive,
 	INTEGER_encode_der,
 	0,				/* Not implemented yet */
 	INTEGER_encode_xer,
@@ -27,89 +28,21 @@
 	sizeof(asn1_DEF_INTEGER_tags) / sizeof(asn1_DEF_INTEGER_tags[0]),
 	asn1_DEF_INTEGER_tags,	/* Same as above */
 	sizeof(asn1_DEF_INTEGER_tags) / sizeof(asn1_DEF_INTEGER_tags[0]),
-	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
 /*
- * Decode INTEGER type.
- */
-ber_dec_rval_t
-INTEGER_decode_ber(asn1_TYPE_descriptor_t *td,
-	void **int_structure, void *buf_ptr, size_t size, int tag_mode) {
-	INTEGER_t *st = (INTEGER_t *)*int_structure;
-	ber_dec_rval_t rval;
-	ber_tlv_len_t length;
-
-	/*
-	 * If the structure is not there, allocate it.
-	 */
-	if(st == NULL) {
-		(void *)st = *int_structure = CALLOC(1, sizeof(*st));
-		if(st == NULL) {
-			rval.code = RC_FAIL;
-			rval.consumed = 0;
-			return rval;
-		}
-	}
-
-	ASN_DEBUG("Decoding %s as INTEGER (tm=%d)",
-		td->name, tag_mode);
-
-	/*
-	 * Check tags.
-	 */
-	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, &length, 0);
-	if(rval.code != RC_OK)
-		return rval;
-
-	ASN_DEBUG("%s length is %d bytes", td->name, (int)length);
-
-	/*
-	 * Make sure we have this length.
-	 */
-	buf_ptr = ((char *)buf_ptr) + rval.consumed;
-	size -= rval.consumed;
-	if(length > (ber_tlv_len_t)size) {
-		rval.code = RC_WMORE;
-		rval.consumed = 0;
-		return rval;
-	}
-
-	st->buf = (uint8_t *)MALLOC(length);
-	if(st->buf) {
-		st->size = length;
-	} else {
-		rval.code = RC_FAIL;
-		rval.consumed = 0;
-		return rval;
-	}
-
-	memcpy(st->buf, buf_ptr, st->size);
-
-	rval.code = RC_OK;
-	rval.consumed += length;
-
-	ASN_DEBUG("Took %ld/%ld bytes to encode %s",
-		(long)rval.consumed,
-		(long)length, td->name);
-
-	return rval;
-}
-
-/*
  * Encode INTEGER type using DER.
  */
 asn_enc_rval_t
-INTEGER_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
+INTEGER_encode_der(asn1_TYPE_descriptor_t *td, void *sptr,
 	int tag_mode, ber_tlv_tag_t tag,
 	asn_app_consume_bytes_f *cb, void *app_key) {
-	asn_enc_rval_t erval;
-	INTEGER_t *st = (INTEGER_t *)ptr;
+	INTEGER_t *st = (INTEGER_t *)sptr;
 
 	ASN_DEBUG("%s %s as INTEGER (tm=%d)",
-		cb?"Encoding":"Estimating", sd->name, tag_mode);
+		cb?"Encoding":"Estimating", td->name, tag_mode);
 
 	/*
 	 * Canonicalize integer in the buffer.
@@ -155,32 +88,7 @@
 
 	} /* if(1) */
 
-	erval.encoded = der_write_tags(sd, st->size, tag_mode, tag,
-		cb, app_key);
-	ASN_DEBUG("INTEGER %s wrote tags %d", sd->name, (int)erval.encoded);
-	if(erval.encoded == -1) {
-		erval.failed_type = sd;
-		erval.structure_ptr = ptr;
-		return erval;
-	}
-
-	if(cb && st->buf) {
-		ssize_t ret;
-
-		ret = cb(st->buf, st->size, app_key);
-		if(ret == -1) {
-			erval.encoded = -1;
-			erval.failed_type = sd;
-			erval.structure_ptr = ptr;
-			return erval;
-		}
-	} else {
-		assert(st->buf || st->size == 0);
-	}
-
-	erval.encoded += st->size;
-
-	return erval;
+	return der_encode_primitive(td, sptr, tag_mode, tag, cb, app_key);
 }
 
 /*
@@ -254,13 +162,17 @@
 INTEGER_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 	asn_app_consume_bytes_f *cb, void *app_key) {
 	const INTEGER_t *st = (const INTEGER_t *)sptr;
+	ssize_t ret;
 
 	(void)td;
 	(void)ilevel;
 
-	if(!st && !st->buf) return cb("<absent>", 8, app_key);
+	if(!st && !st->buf)
+		ret = cb("<absent>", 8, app_key);
+	else
+		ret = INTEGER__dump(st, cb, app_key);
 
-	return (INTEGER__dump(st, cb, app_key) < 0) ? -1 : 0;
+	return (ret < 0) ? -1 : 0;
 }
 
 asn_enc_rval_t
@@ -282,25 +194,6 @@
 	return er;
 }
 
-void
-INTEGER_free(asn1_TYPE_descriptor_t *td, void *ptr, int contents_only) {
-	INTEGER_t *st = (INTEGER_t *)ptr;
-
-	if(!td || !st)
-		return;
-
-	ASN_DEBUG("Freeing %s as INTEGER (%d, %p, %p)",
-		td->name, contents_only, st, st->buf);
-
-	if(st->buf) {
-		FREEMEM(st->buf);
-	}
-
-	if(!contents_only) {
-		FREEMEM(st);
-	}
-}
-
 int
 asn1_INTEGER2long(const INTEGER_t *iptr, long *lptr) {
 	uint8_t *b, *end;
diff --git a/skeletons/INTEGER.h b/skeletons/INTEGER.h
index 89ab1af..b42321b 100644
--- a/skeletons/INTEGER.h
+++ b/skeletons/INTEGER.h
@@ -6,15 +6,12 @@
 #define	_INTEGER_H_
 
 #include <asn_application.h>
+#include <ber_codec_prim.h>
 
-typedef struct INTEGER {
-	uint8_t *buf;	/* Buffer with consecutive INTEGER bits (big-endian) */
-	int size;	/* Size of the buffer */
-} INTEGER_t;
+typedef ASN__PRIMITIVE_TYPE_t INTEGER_t;
 
 extern asn1_TYPE_descriptor_t asn1_DEF_INTEGER;
 
-asn_struct_free_f INTEGER_free;
 asn_struct_print_f INTEGER_print;
 ber_type_decoder_f INTEGER_decode_ber;
 der_type_encoder_f INTEGER_encode_der;
diff --git a/skeletons/ISO646String.c b/skeletons/ISO646String.c
index e5a4d44..dd94be2 100644
--- a/skeletons/ISO646String.c
+++ b/skeletons/ISO646String.c
@@ -28,7 +28,6 @@
 	asn1_DEF_ISO646String_tags,
 	sizeof(asn1_DEF_ISO646String_tags)
 	  / sizeof(asn1_DEF_ISO646String_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/NULL.c b/skeletons/NULL.c
index e15b9af..8276368 100644
--- a/skeletons/NULL.c
+++ b/skeletons/NULL.c
@@ -26,7 +26,6 @@
 	sizeof(asn1_DEF_NULL_tags) / sizeof(asn1_DEF_NULL_tags[0]),
 	asn1_DEF_NULL_tags,	/* Same as above */
 	sizeof(asn1_DEF_NULL_tags) / sizeof(asn1_DEF_NULL_tags[0]),
-	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -37,7 +36,7 @@
 	asn_app_consume_bytes_f *cb, void *app_key) {
 	asn_enc_rval_t erval;
 
-	erval.encoded = der_write_tags(td, 0, tag_mode, tag, cb, app_key);
+	erval.encoded = der_write_tags(td, 0, tag_mode, 0, tag, cb, app_key);
 	if(erval.encoded == -1) {
 		erval.failed_type = td;
 		erval.structure_ptr = ptr;
@@ -73,8 +72,8 @@
 	(void)ilevel;	/* Unused argument */
 
 	if(sptr) {
-		return cb("<present>", 9, app_key);
+		return (cb("<present>", 9, app_key) < 0) ? -1 : 0;
 	} else {
-		return cb("<absent>", 8, app_key);
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 	}
 }
diff --git a/skeletons/NativeEnumerated.c b/skeletons/NativeEnumerated.c
index ec4dd88..bbbc3fb 100644
--- a/skeletons/NativeEnumerated.c
+++ b/skeletons/NativeEnumerated.c
@@ -32,7 +32,6 @@
 	sizeof(asn1_DEF_NativeEnumerated_tags) / sizeof(asn1_DEF_NativeEnumerated_tags[0]),
 	asn1_DEF_NativeEnumerated_tags,	/* Same as above */
 	sizeof(asn1_DEF_NativeEnumerated_tags) / sizeof(asn1_DEF_NativeEnumerated_tags[0]),
-	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/NativeInteger.c b/skeletons/NativeInteger.c
index aac5f86..2310c07 100644
--- a/skeletons/NativeInteger.c
+++ b/skeletons/NativeInteger.c
@@ -34,7 +34,6 @@
 	sizeof(asn1_DEF_NativeInteger_tags) / sizeof(asn1_DEF_NativeInteger_tags[0]),
 	asn1_DEF_NativeInteger_tags,	/* Same as above */
 	sizeof(asn1_DEF_NativeInteger_tags) / sizeof(asn1_DEF_NativeInteger_tags[0]),
-	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -53,7 +52,7 @@
 	 * If the structure is not there, allocate it.
 	 */
 	if(Int == NULL) {
-		(void *)Int = *int_ptr = CALLOC(1, sizeof(*Int));
+		Int = (int *)(*int_ptr = CALLOC(1, sizeof(*Int)));
 		if(Int == NULL) {
 			rval.code = RC_FAIL;
 			rval.consumed = 0;
@@ -67,7 +66,7 @@
 	/*
 	 * Check tags.
 	 */
-	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, &length, 0);
+	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, 0, &length, 0);
 	if(rval.code != RC_OK)
 		return rval;
 
@@ -199,9 +198,9 @@
 	if(Int) {
 		ret = snprintf(scratch, sizeof(scratch), "%d", *Int);
 		assert(ret > 0 && ret < (int)sizeof(scratch));
-		return cb(scratch, ret, app_key);
+		return (cb(scratch, ret, app_key) < 0) ? -1 : 0;
 	} else {
-		return cb("<absent>", 8, app_key);
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 	}
 }
 
diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c
index 1151087..8fc9ca6 100644
--- a/skeletons/NativeReal.c
+++ b/skeletons/NativeReal.c
@@ -11,7 +11,6 @@
  */
 #include <asn_internal.h>
 #include <NativeReal.h>
-#include <INTEGER.h>
 #include <REAL.h>
 #include <assert.h>
 
@@ -35,7 +34,6 @@
 	sizeof(asn1_DEF_NativeReal_tags) / sizeof(asn1_DEF_NativeReal_tags[0]),
 	asn1_DEF_NativeReal_tags,	/* Same as above */
 	sizeof(asn1_DEF_NativeReal_tags) / sizeof(asn1_DEF_NativeReal_tags[0]),
-	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -68,7 +66,7 @@
 	/*
 	 * Check tags.
 	 */
-	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, &length, 0);
+	rval = ber_check_tags(td, 0, buf_ptr, size, tag_mode, 0, &length, 0);
 	if(rval.code != RC_OK)
 		return rval;
 
@@ -132,8 +130,8 @@
 		return erval;
 	}
 	
-	/* Encode fake REAL */
-	erval = INTEGER_encode_der(td, &tmp, tag_mode, tag, cb, app_key);
+	/* Encode a fake REAL */
+	erval = der_encode_primitive(td, &tmp, tag_mode, tag, cb, app_key);
 	if(erval.encoded == -1) {
 		assert(erval.structure_ptr == &tmp);
 		erval.structure_ptr = ptr;
@@ -148,13 +146,12 @@
 		asn_app_consume_bytes_f *cb, void *app_key) {
 	const double *Dbl = (const double *)sptr;
 	asn_enc_rval_t er;
-	double d;
 
 	(void)ilevel;
 
 	if(!Dbl) _ASN_ENCODE_FAILED;
 
-	er.encoded = REAL__dump(d, flags & XER_F_CANONICAL, cb, app_key);
+	er.encoded = REAL__dump(*Dbl, flags & XER_F_CANONICAL, cb, app_key);
 	if(er.encoded < 0) _ASN_ENCODE_FAILED;
 
 	return er;
@@ -171,7 +168,7 @@
 	(void)td;	/* Unused argument */
 	(void)ilevel;	/* Unused argument */
 
-	if(!Dbl) return cb("<absent>", 8, app_key);
+	if(!Dbl) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	return (REAL__dump(*Dbl, 0, cb, app_key) < 0) ? -1 : 0;
 }
diff --git a/skeletons/NumericString.c b/skeletons/NumericString.c
index b4a6df9..fa43558 100644
--- a/skeletons/NumericString.c
+++ b/skeletons/NumericString.c
@@ -28,7 +28,6 @@
 	asn1_DEF_NumericString_tags,
 	sizeof(asn1_DEF_NumericString_tags)
 	  / sizeof(asn1_DEF_NumericString_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index 43ced79..9e8f2e2 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -16,11 +16,11 @@
 };
 asn1_TYPE_descriptor_t asn1_DEF_OBJECT_IDENTIFIER = {
 	"OBJECT IDENTIFIER",
-	INTEGER_free,
+	ASN__PRIMITIVE_TYPE_free,
 	OBJECT_IDENTIFIER_print,
 	OBJECT_IDENTIFIER_constraint,
-	INTEGER_decode_ber,	/* Implemented in terms of INTEGER type */
-	OBJECT_IDENTIFIER_encode_der,
+	ber_decode_primitive,
+	der_encode_primitive,
 	0,				/* Not implemented yet */
 	OBJECT_IDENTIFIER_encode_xer,
 	0, /* Use generic outmost tag fetcher */
@@ -30,52 +30,11 @@
 	asn1_DEF_OBJECT_IDENTIFIER_tags,	/* Same as above */
 	sizeof(asn1_DEF_OBJECT_IDENTIFIER_tags)
 	    / sizeof(asn1_DEF_OBJECT_IDENTIFIER_tags[0]),
-	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
 
 
-/*
- * Encode OBJECT IDENTIFIER type using DER.
- */
-asn_enc_rval_t
-OBJECT_IDENTIFIER_encode_der(asn1_TYPE_descriptor_t *sd, void *ptr,
-	int tag_mode, ber_tlv_tag_t tag,
-	asn_app_consume_bytes_f *cb, void *app_key) {
-	asn_enc_rval_t erval;
-	OBJECT_IDENTIFIER_t *st = (OBJECT_IDENTIFIER_t *)ptr;
-
-	ASN_DEBUG("%s %s as OBJECT IDENTIFIER (tm=%d)",
-		cb?"Encoding":"Estimating", sd->name, tag_mode);
-
-	erval.encoded = der_write_tags(sd, st->size, tag_mode, tag,
-		cb, app_key);
-	ASN_DEBUG("OBJECT IDENTIFIER %s wrote tags %d",
-		sd->name, (int)erval.encoded);
-	if(erval.encoded == -1) {
-		erval.failed_type = sd;
-		erval.structure_ptr = ptr;
-		return erval;
-	}
-
-	if(cb && st->buf) {
-		int ret = cb(st->buf, st->size, app_key);
-		if(ret < 0) {
-			erval.encoded = -1;
-			erval.failed_type = sd;
-			erval.structure_ptr = ptr;
-			return erval;
-		}
-	} else {
-		assert(st->buf || st->size == 0);
-	}
-
-	erval.encoded += st->size;
-
-	return erval;
-}
-
 int
 OBJECT_IDENTIFIER_constraint(asn1_TYPE_descriptor_t *td, const void *sptr,
 		asn_app_consume_bytes_f *app_errlog, void *app_key) {
@@ -101,11 +60,12 @@
 
 
 int
-OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbuf, unsigned int rvsize) {
+OBJECT_IDENTIFIER_get_single_arc(uint8_t *arcbuf, unsigned int arclen, signed int add, void *rvbufp, unsigned int rvsize) {
 	unsigned LE __attribute__ ((unused)) = 1; /* Little endian (x86) */
 	uint8_t *arcend = arcbuf + arclen;	/* End of arc */
-	void *rvstart = rvbuf;	/* Original start of the value buffer */
 	unsigned int cache = 0;	/* No more than 14 significant bits */
+	unsigned char *rvbuf = (unsigned char *)rvbufp;
+	unsigned char *rvstart = rvbuf;	/* Original start of the value buffer */
 	int inc;	/* Return value growth direction */
 
 	rvsize *= CHAR_BIT;	/* bytes to bits */
@@ -155,15 +115,15 @@
 			errno = ERANGE;	/* Overflow */
 			return -1;
 		}
-		*(unsigned long *)rvbuf = accum + add;
+		*(unsigned long *)rvbuf = accum + add;	/* alignment OK! */
 		return 0;
 	}
 
 #ifndef	WORDS_BIGENDIAN
 	if(*(unsigned char *)&LE) {	/* Little endian (x86) */
 		/* "Convert" to big endian */
-		(unsigned char *)rvbuf += rvsize / CHAR_BIT - 1;
-		((unsigned char *)rvstart)--;
+		rvbuf += rvsize / CHAR_BIT - 1;
+		rvstart--;
 		inc = -1;	/* Descending */
 	} else
 #endif	/* !WORDS_BIGENDIAN */
@@ -175,8 +135,8 @@
 		/* Clear the high unused bits */
 		for(bits = rvsize - arclen;
 			bits > CHAR_BIT;
-				(unsigned char *)rvbuf += inc, bits -= CHAR_BIT)
-				*(unsigned char *)rvbuf = 0;
+				rvbuf += inc, bits -= CHAR_BIT)
+				*rvbuf = 0;
 
 		/* Fill the body of a value */
 		for(; arcbuf < arcend; arcbuf++) {
@@ -184,25 +144,24 @@
 			bits += 7;
 			if(bits >= CHAR_BIT) {
 				bits -= CHAR_BIT;
-				*(unsigned char *)rvbuf = (cache >> bits);
-				(unsigned char *)rvbuf += inc;
+				*rvbuf = (cache >> bits);
+				rvbuf += inc;
 			}
 		}
 		if(bits) {
-			*(unsigned char *)rvbuf = cache;
-			(unsigned char *)rvbuf += inc;
+			*rvbuf = cache;
+			rvbuf += inc;
 		}
 	}
 
 	if(add) {
-		for((unsigned char *)rvbuf -= inc; rvbuf != rvstart; (unsigned char *)rvbuf -= inc) {
-			int v = add + *(unsigned char *)rvbuf;
+		for(rvbuf -= inc; rvbuf != rvstart; rvbuf -= inc) {
+			int v = add + *rvbuf;
 			if(v & (-1 << CHAR_BIT)) {
-				*(unsigned char *)rvbuf
-					= (unsigned char)(v + (1 << CHAR_BIT));
+				*rvbuf = (unsigned char)(v + (1 << CHAR_BIT));
 				add = -1;
 			} else {
-				*(unsigned char *)rvbuf = v;
+				*rvbuf = v;
 				break;
 			}
 		}
@@ -331,16 +290,16 @@
 	(void)ilevel;	/* Unused argument */
 
 	if(!st || !st->buf)
-		return cb("<absent>", 8, app_key);
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	/* Dump preamble */
-	if(cb("{ ", 2, app_key))
+	if(cb("{ ", 2, app_key) < 0)
 		return -1;
 
 	if(OBJECT_IDENTIFIER__dump_body(st, cb, app_key) < 0)
 		return -1;
 
-	return cb(" }", 2, app_key);
+	return (cb(" }", 2, app_key) < 0) ? -1 : 0;
 }
 
 int
diff --git a/skeletons/OBJECT_IDENTIFIER.h b/skeletons/OBJECT_IDENTIFIER.h
index e232f70..3ccbc64 100644
--- a/skeletons/OBJECT_IDENTIFIER.h
+++ b/skeletons/OBJECT_IDENTIFIER.h
@@ -5,9 +5,10 @@
 #ifndef	_OBJECT_IDENTIFIER_H_
 #define	_OBJECT_IDENTIFIER_H_
 
-#include <INTEGER.h>
+#include <asn_application.h>
+#include <ber_codec_prim.h>
 
-typedef INTEGER_t OBJECT_IDENTIFIER_t; /* Implemented via INTEGER */
+typedef ASN__PRIMITIVE_TYPE_t OBJECT_IDENTIFIER_t;
 
 extern asn1_TYPE_descriptor_t asn1_DEF_OBJECT_IDENTIFIER;
 
diff --git a/skeletons/OCTET_STRING.c b/skeletons/OCTET_STRING.c
index df6f86e..6a72d1a 100644
--- a/skeletons/OCTET_STRING.c
+++ b/skeletons/OCTET_STRING.c
@@ -29,7 +29,6 @@
 	asn1_DEF_OCTET_STRING_tags,	/* Same as above */
 	sizeof(asn1_DEF_OCTET_STRING_tags)
 	  / sizeof(asn1_DEF_OCTET_STRING_tags[0]),
-	-1,	/* Both ways are fine (primitive and constructed) */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -161,10 +160,9 @@
 	int tlv_constr;
 	enum type_type_e {
 		_TT_GENERIC	= 0,	/* Just a random OCTET STRING */
-		_TT_BIT_STRING	= -1,	/* BIT STRING type, a special case */
-		_TT_ANY		= 1,	/* ANY type, a special case too */
-	} type_type
-		= (enum type_type_e)(int)td->specifics;	/* An ugly hack */
+		_TT_BIT_STRING	= 1,	/* BIT STRING type, a special case */
+		_TT_ANY		= 2,	/* ANY type, a special case too */
+	} type_type = (enum type_type_e)(int)td->specifics;
 
 	ASN_DEBUG("Decoding %s as %s (frame %ld)",
 		td->name,
@@ -189,7 +187,7 @@
 		 * Check tags.
 		 */
 		rval = ber_check_tags(td, ctx,
-			buf_ptr, size, tag_mode,
+			buf_ptr, size, tag_mode, -1,
 			&ctx->left, &tlv_constr);
 		if(rval.code != RC_OK) {
 			RETURN(rval.code);
@@ -234,8 +232,9 @@
 		ber_tlv_len_t tlv_len;
 		ber_tlv_tag_t expected_tag;
 		ssize_t tl, ll;
-		ssize_t Left = ((!sel||sel->left==-1||sel->left >= size)
-					?size:sel->left);
+				/* This one works even if (sel->left == -1) */
+		ssize_t Left = ((!sel||(size_t)sel->left >= size)
+					?size:(size_t)sel->left);
 
 
 		ASN_DEBUG("fetch tag(size=%d,L=%d), %sstack, left=%d, want0=%d",
@@ -475,8 +474,8 @@
 	asn_enc_rval_t erval;
 	OCTET_STRING_t *st = (OCTET_STRING_t *)ptr;
 	int add_byte = 0;
-	int is_bit_str = (td->specifics == (void *)-1);
-	int is_ANY_type = (td->specifics == (void *)1);
+	int is_bit_str = (td->specifics == (void *)1);
+	int is_ANY_type = (td->specifics == (void *)2);
 
 	ASN_DEBUG("%s %s as OCTET STRING",
 		cb?"Estimating":"Encoding", td->name);
@@ -498,7 +497,7 @@
 		erval.encoded = 0;
 	} else {
 		erval.encoded = der_write_tags(td, st->size + add_byte,
-			tag_mode, tag, cb, app_key);
+			tag_mode, 0, tag, cb, app_key);
 		if(erval.encoded == -1) {
 			erval.failed_type = td;
 			erval.structure_ptr = ptr;
@@ -510,7 +509,6 @@
 		uint8_t zero;
 		uint8_t *buf;
 		int size;
-		ssize_t ret;
 
 		/* BIT STRING-aware handling */
 		if(add_byte) {
@@ -527,8 +525,7 @@
 		}
 
 		if(size) {
-			ret = cb(buf, size, app_key);
-			if(ret == -1) {
+			if(cb(buf, size, app_key) < 0) {
 				erval.encoded = -1;
 				erval.failed_type = td;
 				erval.structure_ptr = ptr;
@@ -636,11 +633,10 @@
 	uint8_t *buf;
 	uint8_t *end;
 	size_t i;
-	int lvl;
 
 	(void)td;	/* Unused argument */
 
-	if(!st || !st->buf) return cb("<absent>", 8, app_key);
+	if(!st || !st->buf) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	/*
 	 * Dump the contents of the buffer in hexadecimal.
@@ -649,11 +645,9 @@
 	end = buf + st->size;
 	for(i = 0; buf < end; buf++, i++) {
 		if(!(i % 16) && (i || st->size > 16)) {
-			if(cb(scratch, p - scratch, app_key)
-			|| cb("\n", 1, app_key))
+			if(cb(scratch, p - scratch, app_key) < 0)
 				return -1;
-			for(lvl = 0; lvl < ilevel; lvl++)
-				cb(" ", 1, app_key);
+			_i_INDENT(1);
 			p = scratch;
 		}
 		*p++ = h2c[(*buf >> 4) & 0x0F];
@@ -663,7 +657,7 @@
 
 	if(p > scratch) {
 		p--;	/* Remove the tail space */
-		if(cb(scratch, p - scratch, app_key))
+		if(cb(scratch, p - scratch, app_key) < 0)
 			return -1;
 	}
 
@@ -679,9 +673,9 @@
 	(void)ilevel;	/* Unused argument */
 
 	if(st && st->buf) {
-		return cb(st->buf, st->size, app_key);
+		return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
 	} else {
-		return cb("<absent>", 8, app_key);
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 	}
 }
 
diff --git a/skeletons/ObjectDescriptor.c b/skeletons/ObjectDescriptor.c
index 4ddcaac..192b468 100644
--- a/skeletons/ObjectDescriptor.c
+++ b/skeletons/ObjectDescriptor.c
@@ -28,7 +28,6 @@
 	asn1_DEF_ObjectDescriptor_tags,
 	sizeof(asn1_DEF_ObjectDescriptor_tags)
 	  / sizeof(asn1_DEF_ObjectDescriptor_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/PrintableString.c b/skeletons/PrintableString.c
index 1368447..f0d4b16 100644
--- a/skeletons/PrintableString.c
+++ b/skeletons/PrintableString.c
@@ -28,7 +28,6 @@
 	asn1_DEF_PrintableString_tags,
 	sizeof(asn1_DEF_PrintableString_tags)
 	  / sizeof(asn1_DEF_PrintableString_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/REAL.c b/skeletons/REAL.c
index 7c23010..010097b 100644
--- a/skeletons/REAL.c
+++ b/skeletons/REAL.c
@@ -4,7 +4,6 @@
  */
 #include <asn_internal.h>
 #include <REAL.h>
-#include <INTEGER.h>
 #include <stdlib.h>	/* for strtod(3) */
 #include <math.h>
 #include <errno.h>
@@ -30,11 +29,11 @@
 };
 asn1_TYPE_descriptor_t asn1_DEF_REAL = {
 	"REAL",
-	INTEGER_free,
+	ASN__PRIMITIVE_TYPE_free,
 	REAL_print,
 	asn_generic_no_constraint,
-	INTEGER_decode_ber,	/* Implemented in terms of INTEGER type */
-	INTEGER_encode_der,
+	ber_decode_primitive,
+	der_encode_primitive,
 	0,				/* Not implemented yet */
 	REAL_encode_xer,
 	0, /* Use generic outmost tag fetcher */
@@ -42,7 +41,6 @@
 	sizeof(asn1_DEF_REAL_tags) / sizeof(asn1_DEF_REAL_tags[0]),
 	asn1_DEF_REAL_tags,	/* Same as above */
 	sizeof(asn1_DEF_REAL_tags) / sizeof(asn1_DEF_REAL_tags[0]),
-	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -55,6 +53,28 @@
 	const char *fmt = canonical?"%15E":"f";
 	ssize_t ret;
 
+	/*
+	 * Check whether it is a special value.
+	 */
+	if(finite(d) == 0) {
+                if(isinf(d)) {
+                        if(copysign(1.0, d) < 0.0) {
+				buf = "<MINUS-INFINITY/>";
+				buflen = 17;
+                        } else {
+				buf = "<PLUS-INFINITY/>";
+				buflen = 16;
+                        }
+		} else {
+			buf = "<NOT-A-NUMBER/>";
+			buflen = 15;
+		}
+		return (cb(buf, buflen, app_key) < 0) ? -1 : buflen;
+	}
+
+	/*
+	 * Use the libc's double printing, hopefully they got it right.
+	 */
 	do {
 		ret = snprintf(buf, buflen, fmt, d);
 		if(ret < 0) {
@@ -66,7 +86,7 @@
 			break;
 		}
 		if(buf != local_buf) free(buf);
-		(void *)buf = MALLOC(buflen);
+		buf = (char *)MALLOC(buflen);
 		if(!buf) return -1;
 	} while(1);
 
@@ -118,18 +138,20 @@
 REAL_print(asn1_TYPE_descriptor_t *td, const void *sptr, int ilevel,
 	asn_app_consume_bytes_f *cb, void *app_key) {
 	const REAL_t *st = (const REAL_t *)sptr;
+	ssize_t ret;
 	double d;
 
 	(void)td;	/* Unused argument */
 	(void)ilevel;	/* Unused argument */
 
 	if(!st || !st->buf)
-		return cb("<absent>", 8, app_key);
+		ret = cb("<absent>", 8, app_key);
+	else if(asn1_REAL2double(st, &d))
+		ret = cb("<error>", 7, app_key);
+	else
+		ret = REAL__dump(d, 0, cb, app_key);
 
-	if(asn1_REAL2double(st, &d))
-		return cb("<error>", 7, app_key);
-
-	return (REAL__dump(d, 0, cb, app_key) < 0) ? -1 : 0;
+	return (ret < 0) ? -1 : 0;
 }
 
 asn_enc_rval_t
@@ -338,7 +360,7 @@
 	|| expval == INT_MAX	/* catches finite() which catches isnan() */
 	) {
 		if(!st->buf || st->size < 2) {
-			(void *)ptr = MALLOC(2);
+			ptr = (uint8_t *)MALLOC(2);
 			if(!ptr) return -1;
 			st->buf = ptr;
 		}
diff --git a/skeletons/REAL.h b/skeletons/REAL.h
index 2f7809b..c478f41 100644
--- a/skeletons/REAL.h
+++ b/skeletons/REAL.h
@@ -6,11 +6,9 @@
 #define	ASN_TYPE_REAL_H
 
 #include <asn_application.h>
+#include <ber_codec_prim.h>
 
-typedef struct REAL {
-	uint8_t *buf;	/* Buffer with REAL type encoding */
-	int size;	/* Size of the buffer */
-} REAL_t;
+typedef ASN__PRIMITIVE_TYPE_t REAL_t;
 
 extern asn1_TYPE_descriptor_t asn1_DEF_REAL;
 
diff --git a/skeletons/RELATIVE-OID.c b/skeletons/RELATIVE-OID.c
index 5d1e1a9..e928bd0 100644
--- a/skeletons/RELATIVE-OID.c
+++ b/skeletons/RELATIVE-OID.c
@@ -4,6 +4,7 @@
  */
 #include <asn_internal.h>
 #include <RELATIVE-OID.h>
+#include <ber_codec_prim.h>	/* Encoder and decoder of a primitive */
 #include <limits.h>	/* for CHAR_BIT */
 #include <assert.h>
 #include <errno.h>
@@ -16,11 +17,11 @@
 };
 asn1_TYPE_descriptor_t asn1_DEF_RELATIVE_OID = {
 	"RELATIVE-OID",
-	INTEGER_free,
+	ASN__PRIMITIVE_TYPE_free,
 	RELATIVE_OID_print,
 	asn_generic_no_constraint,
-	INTEGER_decode_ber,	/* Implemented in terms of INTEGER type */
-	OBJECT_IDENTIFIER_encode_der,
+	ber_decode_primitive,
+	der_encode_primitive,
 	0,				/* Not implemented yet */
 	RELATIVE_OID_encode_xer,
 	0, /* Use generic outmost tag fetcher */
@@ -30,7 +31,6 @@
 	asn1_DEF_RELATIVE_OID_tags,	/* Same as above */
 	sizeof(asn1_DEF_RELATIVE_OID_tags)
 	    / sizeof(asn1_DEF_RELATIVE_OID_tags[0]),
-	0,	/* Always in primitive form */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -73,16 +73,16 @@
 	(void)ilevel;	/* Unused argument */
 
 	if(!st || !st->buf)
-		return cb("<absent>", 8, app_key);
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	/* Dump preamble */
-	if(cb("{ ", 2, app_key))
+	if(cb("{ ", 2, app_key) < 0)
 		return -1;
 
 	if(RELATIVE_OID__dump_body(st, cb, app_key) < 0)
 		return -1;
 
-	return cb(" }", 2, app_key);
+	return (cb(" }", 2, app_key) < 0) ? -1 : 0;
 }
 
 asn_enc_rval_t
diff --git a/skeletons/T61String.c b/skeletons/T61String.c
index d2ac2d5..14a86b9 100644
--- a/skeletons/T61String.c
+++ b/skeletons/T61String.c
@@ -28,7 +28,6 @@
 	asn1_DEF_T61String_tags,
 	sizeof(asn1_DEF_T61String_tags)
 	  / sizeof(asn1_DEF_T61String_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/TeletexString.c b/skeletons/TeletexString.c
index 7a56953..965ada8 100644
--- a/skeletons/TeletexString.c
+++ b/skeletons/TeletexString.c
@@ -28,7 +28,6 @@
 	asn1_DEF_TeletexString_tags,
 	sizeof(asn1_DEF_TeletexString_tags)
 	  / sizeof(asn1_DEF_TeletexString_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/UTCTime.c b/skeletons/UTCTime.c
index 22e5498..f884eeb 100644
--- a/skeletons/UTCTime.c
+++ b/skeletons/UTCTime.c
@@ -15,7 +15,9 @@
  * UTCTime basic type description.
  */
 static ber_tlv_tag_t asn1_DEF_UTCTime_tags[] = {
-	(ASN_TAG_CLASS_UNIVERSAL | (23 << 2))
+	(ASN_TAG_CLASS_UNIVERSAL | (23 << 2)),	/* [UNIVERSAL 23] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (26 << 2)),  /* [UNIVERSAL 26] IMPLICIT ...*/
+	(ASN_TAG_CLASS_UNIVERSAL | (4 << 2))    /* ... OCTET STRING */
 };
 asn1_TYPE_descriptor_t asn1_DEF_UTCTime = {
 	"UTCTime",
@@ -29,11 +31,10 @@
 	0, /* Use generic outmost tag fetcher */
 	asn1_DEF_UTCTime_tags,
 	sizeof(asn1_DEF_UTCTime_tags)
-	  / sizeof(asn1_DEF_UTCTime_tags[0]),
-	asn1_DEF_UTCTime_tags,	/* Same as above */
+	  / sizeof(asn1_DEF_UTCTime_tags[0]) - 2,
+	asn1_DEF_UTCTime_tags,
 	sizeof(asn1_DEF_UTCTime_tags)
 	  / sizeof(asn1_DEF_UTCTime_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -106,16 +107,16 @@
 
 		errno = EPERM;
 		if(asn_UT2time(st, &tm, 1) == -1 && errno != EPERM)
-			return cb("<bad-value>", 11, app_key);
+			return (cb("<bad-value>", 11, app_key) < 0) ? -1 : 0;
 
 		ret = snprintf(buf, sizeof(buf),
 			"%04d-%02d-%02d %02d:%02d%02d (GMT)",
 			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
 			tm.tm_hour, tm.tm_min, tm.tm_sec);
 		assert(ret > 0 && ret < (int)sizeof(buf));
-		return cb(buf, ret, app_key);
+		return (cb(buf, ret, app_key) < 0) ? -1 : 0;
 	} else {
-		return cb("<absent>", 8, app_key);
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 	}
 }
 
diff --git a/skeletons/UTF8String.c b/skeletons/UTF8String.c
index 7220a67..2d474e9 100644
--- a/skeletons/UTF8String.c
+++ b/skeletons/UTF8String.c
@@ -28,7 +28,6 @@
 	asn1_DEF_UTF8String_tags,
 	sizeof(asn1_DEF_UTF8String_tags)
 	  / sizeof(asn1_DEF_UTF8String_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -122,8 +121,8 @@
 	(void)ilevel;	/* Unused argument */
 
 	if(st && st->buf) {
-		return cb(st->buf, st->size, app_key);
+		return (cb(st->buf, st->size, app_key) < 0) ? -1 : 0;
 	} else {
-		return cb("<absent>", 8, app_key);
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 	}
 }
diff --git a/skeletons/UniversalString.c b/skeletons/UniversalString.c
index d56cd92..3dc0441 100644
--- a/skeletons/UniversalString.c
+++ b/skeletons/UniversalString.c
@@ -28,7 +28,6 @@
 	asn1_DEF_UniversalString_tags,
 	sizeof(asn1_DEF_UniversalString_tags)
 	  / sizeof(asn1_DEF_UniversalString_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
@@ -120,7 +119,7 @@
 	(void)td;	/* Unused argument */
 	(void)ilevel;	/* Unused argument */
 
-	if(!st || !st->buf) return cb("<absent>", 8, app_key);
+	if(!st || !st->buf) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	if(UniversalString__dump(st, cb, app_key) < 0)
 		return -1;
diff --git a/skeletons/VideotexString.c b/skeletons/VideotexString.c
index f313ecb..3520471 100644
--- a/skeletons/VideotexString.c
+++ b/skeletons/VideotexString.c
@@ -28,7 +28,6 @@
 	asn1_DEF_VideotexString_tags,
 	sizeof(asn1_DEF_VideotexString_tags)
 	  / sizeof(asn1_DEF_VideotexString_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/VisibleString.c b/skeletons/VisibleString.c
index dbd0e92..8c7d37c 100644
--- a/skeletons/VisibleString.c
+++ b/skeletons/VisibleString.c
@@ -28,7 +28,6 @@
 	asn1_DEF_VisibleString_tags,
 	sizeof(asn1_DEF_VisibleString_tags)
 	  / sizeof(asn1_DEF_VisibleString_tags[0]),
-	-1,	/* Both ways are fine */
 	0, 0,	/* No members */
 	0	/* No specifics */
 };
diff --git a/skeletons/asn_internal.h b/skeletons/asn_internal.h
index f50b7a1..e8a6993 100644
--- a/skeletons/asn_internal.h
+++ b/skeletons/asn_internal.h
@@ -31,7 +31,7 @@
 			__FILE__, __LINE__);	\
 	} while(0)
 #else	/* !__GNUC__ */
-extern void ASN_DEBUG_f(const char *fmt, ...);
+void ASN_DEBUG_f(const char *fmt, ...);
 #define	ASN_DEBUG	ASN_DEBUG_f
 #endif	/* __GNUC__ */
 #else	/* EMIT_ASN_DEBUG != 1 */
@@ -60,13 +60,20 @@
 		|| __ASN_E_cbc(buf3, size3))
 
 #define	_i_ASN_TEXT_INDENT(nl, level) do {				\
-		int __level = (level);					\
-		int __nl = ((nl) != 0);					\
-		int __i;						\
-		if(__nl) _ASN_CALLBACK("\n", 1);			\
-		for(__i = 0; __i < __level; __i++)			\
-			_ASN_CALLBACK("    ", 4);			\
-		er.encoded += __nl + 4 * __level;			\
+	int __level = (level);						\
+	int __nl = ((nl) != 0);						\
+	int __i;							\
+	if(__nl) _ASN_CALLBACK("\n", 1);				\
+	for(__i = 0; __i < __level; __i++)				\
+		_ASN_CALLBACK("    ", 4);				\
+	er.encoded += __nl + 4 * __level;				\
+} while(0)
+
+#define	_i_INDENT(nl)	do {						\
+	int __i;							\
+	if((nl) && cb("\n", 1, app_key) < 0) return -1;			\
+	for(__i = 0; __i < ilevel; __i++)				\
+		if(cb("    ", 4, app_key) < 0) return -1;		\
 } while(0)
 
 #endif	/* _ASN_INTERNAL_H_ */
diff --git a/skeletons/ber_decoder.c b/skeletons/ber_decoder.c
index 3672b68..a64f36d 100644
--- a/skeletons/ber_decoder.c
+++ b/skeletons/ber_decoder.c
@@ -46,7 +46,7 @@
  */
 ber_dec_rval_t
 ber_check_tags(asn1_TYPE_descriptor_t *td, ber_dec_ctx_t *opt_ctx,
-		void *ptr, size_t size, int tag_mode,
+		void *ptr, size_t size, int tag_mode, int last_tag_form,
 		ber_tlv_len_t *last_length, int *opt_tlv_form) {
 	ssize_t consumed_myself = 0;
 	ssize_t tag_len;
@@ -169,10 +169,10 @@
 				RETURN(RC_FAIL);
 			}
 		} else {
-			if(td->last_tag_form != tlv_constr
-			&& td->last_tag_form != -1) {
+			if(last_tag_form != tlv_constr
+			&& last_tag_form != -1) {
 				ASN_DEBUG("last_tag_form %d != %d",
-					td->last_tag_form, tlv_constr);
+					last_tag_form, tlv_constr);
 				RETURN(RC_FAIL);
 			}
 		}
diff --git a/skeletons/ber_decoder.h b/skeletons/ber_decoder.h
index 3e1b84f..a4a5038 100644
--- a/skeletons/ber_decoder.h
+++ b/skeletons/ber_decoder.h
@@ -21,7 +21,7 @@
 enum ber_dec_rval_code_e {
 	RC_OK,		/* Decoded successfully */
 	RC_WMORE,	/* More data expected, call again */
-	RC_FAIL,	/* Failure to decode data */
+	RC_FAIL		/* Failure to decode data */
 };
 typedef struct ber_dec_rval_s {
 	enum ber_dec_rval_code_e code;	/* Result code */
@@ -71,6 +71,7 @@
 		ber_dec_ctx_t *opt_ctx,	/* saved context */
 		void *ptr, size_t size,
 		int tag_mode,		/* {-1,0,1}: IMPLICIT, no, EXPLICIT */
+		int last_tag_form,	/* {-1,0:1}: any, primitive, constr */
 		ber_tlv_len_t *last_length,
 		int *opt_tlv_form);
 
diff --git a/skeletons/ber_tlv_tag.h b/skeletons/ber_tlv_tag.h
index c02a686..52a1141 100644
--- a/skeletons/ber_tlv_tag.h
+++ b/skeletons/ber_tlv_tag.h
@@ -9,7 +9,7 @@
 	ASN_TAG_CLASS_UNIVERSAL		= 0,	/* 0b00 */
 	ASN_TAG_CLASS_APPLICATION	= 1,	/* 0b01 */
 	ASN_TAG_CLASS_CONTEXT		= 2,	/* 0b10 */
-	ASN_TAG_CLASS_PRIVATE		= 3,	/* 0b11 */
+	ASN_TAG_CLASS_PRIVATE		= 3	/* 0b11 */
 };
 typedef unsigned ber_tlv_tag_t;	/* BER TAG from Tag-Length-Value */
 
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index 41fbae3..5ad33c8 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -148,7 +148,7 @@
 
 		if(tag_mode || td->tags_count) {
 			rval = ber_check_tags(td, ctx, ptr, size,
-				tag_mode, &ctx->left, 0);
+				tag_mode, -1, &ctx->left, 0);
 			if(rval.code != RC_OK) {
 				ASN_DEBUG("%s tagging check failed: %d",
 					td->name, rval.code);
@@ -425,7 +425,7 @@
 			return erval;
 
 		/* Encode CHOICE with parent or my own tag */
-		ret = der_write_tags(td, erval.encoded, tag_mode, tag,
+		ret = der_write_tags(td, erval.encoded, tag_mode, 1, tag,
 			cb, app_key);
 		if(ret == -1) {
 			erval.encoded = -1;
@@ -597,7 +597,7 @@
 	asn1_CHOICE_specifics_t *specs = (asn1_CHOICE_specifics_t *)td->specifics;
 	int present;
 
-	if(!sptr) return cb("<absent>", 8, app_key);
+	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	/*
 	 * Figure out which CHOICE element is encoded.
@@ -613,22 +613,22 @@
 
 		if(elm->flags & ATF_POINTER) {
 			memb_ptr = *(const void * const *)((const char *)sptr + elm->memb_offset);
-			if(!memb_ptr) return cb("<absent>", 8, app_key);
+			if(!memb_ptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 		} else {
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 		}
 
 		/* Print member's name and stuff */
 		if(0) {
-			if(cb(elm->name, strlen(elm->name), app_key)
-			|| cb(": ", 2, app_key))
+			if(cb(elm->name, strlen(elm->name), app_key) < 0
+			|| cb(": ", 2, app_key) < 0)
 				return -1;
 		}
 
 		return elm->type->print_struct(elm->type, memb_ptr, ilevel,
 			cb, app_key);
 	} else {
-		return cb("<absent>", 8, app_key);
+		return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 	}
 }
 
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index f129613..b00ae6f 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -158,7 +158,7 @@
 		 */
 
 		rval = ber_check_tags(td, ctx, ptr, size,
-			tag_mode, &ctx->left, 0);
+			tag_mode, 1, &ctx->left, 0);
 		if(rval.code != RC_OK) {
 			ASN_DEBUG("%s tagging check failed: %d",
 				td->name, rval.code);
@@ -534,7 +534,7 @@
 	/*
 	 * Encode the TLV for the sequence itself.
 	 */
-	ret = der_write_tags(td, computed_size, tag_mode, tag, cb, app_key);
+	ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
 	ASN_DEBUG("Wrote tags: %ld (+%ld)", (long)ret, (long)computed_size);
 	if(ret == -1) {
 		erval.encoded = -1;
@@ -632,11 +632,11 @@
 	int edx;
 	int ret;
 
-	if(!sptr) return cb("<absent>", 8, app_key);
+	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	/* Dump preamble */
-	if(cb(td->name, strlen(td->name), app_key)
-	|| cb(" ::= {\n", 7, app_key))
+	if(cb(td->name, strlen(td->name), app_key) < 0
+	|| cb(" ::= {", 6, app_key) < 0)
 		return -1;
 
 	for(edx = 0; edx < td->elements_count; edx++) {
@@ -651,27 +651,23 @@
 		}
 
 		/* Indentation */
-		for(ret = 0; ret < ilevel; ret++) cb(" ", 1, app_key);
+		_i_INDENT(1);
 
 		/* Print the member's name and stuff */
-		if(cb(elm->name, strlen(elm->name), app_key)
-		|| cb(": ", 2, app_key))
+		if(cb(elm->name, strlen(elm->name), app_key) < 0
+		|| cb(": ", 2, app_key) < 0)
 			return -1;
 
 		/* Print the member itself */
-		ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 4,
+		ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1,
 			cb, app_key);
 		if(ret) return ret;
-
-		/* Print out the terminator */
-		ret = cb("\n", 1, app_key);
-		if(ret) return ret;
 	}
 
-	/* Indentation */
-	for(ret = 0; ret < ilevel - 4; ret++) cb(" ", 1, app_key);
+	ilevel--;
+	_i_INDENT(1);
 
-	return cb("}", 1, app_key);
+	return (cb("}", 1, app_key) < 0) ? -1 : 0;
 }
 
 void
diff --git a/skeletons/constr_SEQUENCE_OF.c b/skeletons/constr_SEQUENCE_OF.c
index 7330f65..be2ed60 100644
--- a/skeletons/constr_SEQUENCE_OF.c
+++ b/skeletons/constr_SEQUENCE_OF.c
@@ -39,7 +39,7 @@
 	/*
 	 * Encode the TLV for the sequence itself.
 	 */
-	encoding_size = der_write_tags(td, computed_size, tag_mode, tag,
+	encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,
 		cb, app_key);
 	if(encoding_size == -1) {
 		erval.encoded = -1;
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index 93da782..6a604e4 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -147,7 +147,7 @@
 		 */
 
 		rval = ber_check_tags(td, ctx, ptr, size,
-			tag_mode, &ctx->left, 0);
+			tag_mode, 1, &ctx->left, 0);
 		if(rval.code != RC_OK) {
 			ASN_DEBUG("%s tagging check failed: %d",
 				td->name, rval.code);
@@ -533,7 +533,7 @@
 	/*
 	 * Encode the TLV for the sequence itself.
 	 */
-	ret = der_write_tags(td, computed_size, tag_mode, tag, cb, app_key);
+	ret = der_write_tags(td, computed_size, tag_mode, 1, tag, cb, app_key);
 	if(ret == -1) {
 		my_erval.encoded = -1;
 		my_erval.failed_type = td;
@@ -633,11 +633,11 @@
 	int edx;
 	int ret;
 
-	if(!sptr) return cb("<absent>", 8, app_key);
+	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	/* Dump preamble */
-	if(cb(td->name, strlen(td->name), app_key)
-	|| cb(" ::= {\n", 7, app_key))
+	if(cb(td->name, strlen(td->name), app_key) < 0
+	|| cb(" ::= {", 6, app_key) < 0)
 		return -1;
 
 	for(edx = 0; edx < td->elements_count; edx++) {
@@ -651,27 +651,23 @@
 			memb_ptr = (const void *)((const char *)sptr + elm->memb_offset);
 		}
 
-		/* Indentation */
-		for(ret = 0; ret < ilevel; ret++) cb(" ", 1, app_key);
+		_i_INDENT(1);
 
 		/* Print the member's name and stuff */
-		if(cb(elm->name, strlen(elm->name), app_key)
-		|| cb(": ", 2, app_key))
+		if(cb(elm->name, strlen(elm->name), app_key) < 0
+		|| cb(": ", 2, app_key) < 0)
 			return -1;
 
 		/* Print the member itself */
-		ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 4,
+		ret = elm->type->print_struct(elm->type, memb_ptr, ilevel + 1,
 			cb, app_key);
 		if(ret) return ret;
-
-		ret = cb("\n", 1, app_key);
-		if(ret) return ret;
 	}
 
-	/* Indentation */
-	for(ret = 0; ret < ilevel - 4; ret++) cb(" ", 1, app_key);
+	ilevel--;
+	_i_INDENT(1);
 
-	return cb("}", 1, app_key);
+	return (cb("}", 1, app_key) < 0) ? -1 : 0;
 }
 
 void
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c
index 0556760..2050d1a 100644
--- a/skeletons/constr_SET_OF.c
+++ b/skeletons/constr_SET_OF.c
@@ -114,7 +114,7 @@
 		 */
 
 		rval = ber_check_tags(td, ctx, ptr, size,
-			tag_mode, &ctx->left, 0);
+			tag_mode, 1, &ctx->left, 0);
 		if(rval.code != RC_OK) {
 			ASN_DEBUG("%s tagging check failed: %d",
 				td->name, rval.code);
@@ -346,7 +346,7 @@
 	/*
 	 * Encode the TLV for the sequence itself.
 	 */
-	encoding_size = der_write_tags(td, computed_size, tag_mode, tag,
+	encoding_size = der_write_tags(td, computed_size, tag_mode, 1, tag,
 		cb, app_key);
 	if(encoding_size == -1) {
 		erval.encoded = -1;
@@ -366,7 +366,8 @@
 	 * according to their encodings. Build an array of the
 	 * encoded elements.
 	 */
-	(void *)encoded_els = MALLOC(list->count * sizeof(encoded_els[0]));
+	encoded_els = (struct _el_buffer *)MALLOC(
+				list->count * sizeof(encoded_els[0]));
 	if(encoded_els == NULL) {
 		erval.encoded = -1;
 		erval.failed_type = td;
@@ -428,7 +429,7 @@
 		struct _el_buffer *encoded_el = &encoded_els[edx];
 		/* Report encoded chunks to the application */
 		if(ret == 0
-		&& cb(encoded_el->buf, encoded_el->length, app_key) == -1)
+		&& cb(encoded_el->buf, encoded_el->length, app_key) < 0)
 			ret = -1;
 		FREEMEM(encoded_el->buf);
 	}
@@ -504,11 +505,11 @@
 	int ret;
 	int i;
 
-	if(!sptr) return cb("<absent>", 8, app_key);
+	if(!sptr) return (cb("<absent>", 8, app_key) < 0) ? -1 : 0;
 
 	/* Dump preamble */
-	if(cb(td->name, strlen(td->name), app_key)
-	|| cb(" ::= {\n", 7, app_key))
+	if(cb(td->name, strlen(td->name), app_key) < 0
+	|| cb(" ::= {", 6, app_key) < 0)
 		return -1;
 
 	(const void *)list = sptr;
@@ -516,21 +517,17 @@
 		const void *memb_ptr = list->array[i];
 		if(!memb_ptr) continue;
 
-		/* Indentation */
-		for(ret = 0; ret < ilevel; ret++) cb(" ", 1, app_key);
+		_i_INDENT(1);
 
 		ret = element->type->print_struct(element->type, memb_ptr,
-			ilevel + 4, cb, app_key);
-		if(ret) return ret;
-
-		ret = cb("\n", 1, app_key);
+			ilevel + 1, cb, app_key);
 		if(ret) return ret;
 	}
 
-	/* Indentation */
-	for(ret = 0; ret < ilevel - 4; ret++) cb(" ", 1, app_key);
+	ilevel--;
+	_i_INDENT(1);
 
-	return cb("}", 1, app_key);
+	return (cb("}", 1, app_key) < 0) ? -1 : 0;
 }
 
 void
diff --git a/skeletons/constr_TYPE.c b/skeletons/constr_TYPE.c
index 5085e4a..c0e966a 100644
--- a/skeletons/constr_TYPE.c
+++ b/skeletons/constr_TYPE.c
@@ -41,7 +41,7 @@
 	}
 
 	/* Invoke type-specific printer */
-	if(td->print_struct(td, struct_ptr, 4, _print2fp, stream))
+	if(td->print_struct(td, struct_ptr, 1, _print2fp, stream))
 		return -1;
 
 	/* Terminate the output */
diff --git a/skeletons/constr_TYPE.h b/skeletons/constr_TYPE.h
index c8982f9..93ed24d 100644
--- a/skeletons/constr_TYPE.h
+++ b/skeletons/constr_TYPE.h
@@ -111,8 +111,6 @@
 	ber_tlv_tag_t *all_tags;/* Every tag for BER/containment */
 	int all_tags_count;	/* Number of tags */
 
-	int last_tag_form;	/* Acceptable form of the tag (prim, constr) */
-
 	/*
 	 * An ASN.1 production type members (members of SEQUENCE, SET, CHOICE).
 	 */
@@ -132,7 +130,7 @@
   enum asn1_TYPE_flags_e {
 	ATF_NOFLAGS,
 	ATF_POINTER	= 0x01,	/* Represented by the pointer */
-	ATF_OPEN_TYPE	= 0x02,	/* ANY type, without meaningful tag */
+	ATF_OPEN_TYPE	= 0x02	/* ANY type, without meaningful tag */
   };
 typedef struct asn1_TYPE_member_s {
 	enum asn1_TYPE_flags_e flags;	/* Element's presentation flags */
diff --git a/skeletons/constraints.c b/skeletons/constraints.c
index 9c34885..9b60545 100644
--- a/skeletons/constraints.c
+++ b/skeletons/constraints.c
@@ -99,7 +99,7 @@
 	}
 
 	if(ret < (ssize_t)sizeof(buf)) {
-		cb(buf, ret, key);
+		(void)cb(buf, ret, key);
 		return;
 	}
 
@@ -120,5 +120,5 @@
 		p = buf;
 	}
 
-	cb(p, ret, key);
+	(void)cb(p, ret, key);
 }
diff --git a/skeletons/constraints.h b/skeletons/constraints.h
index dfc0759..fe693ae 100644
--- a/skeletons/constraints.h
+++ b/skeletons/constraints.h
@@ -45,17 +45,10 @@
 /*
  * Invoke the callback with a complete error message.
  */
-#ifdef	__GNUC__
-#define	_ASN_ERRLOG(app_errlog, app_key, fmt, args...)	do {	\
-	if(app_errlog)						\
-		_asn_i_log_error(app_errlog,			\
-			app_key, fmt, ##args);			\
-} while(0);
-#else	/* Preprocessor does not support variable args macros */
+/* Preprocessor may not support variable args macros, so act strangely */
 #define	_ASN_ERRLOG	if(app_errlog) _asn_i_log_error
-#endif
 
-extern void _asn_i_log_error(asn_app_consume_bytes_f *, void *key,
+void _asn_i_log_error(asn_app_consume_bytes_f *, void *key,
 	const char *fmt, ...) __attribute__ ((format(printf, 3, 4)));
 
 #endif	/* _ASN1_CONSTRAINTS_VALIDATOR_H_ */
diff --git a/skeletons/der_encoder.c b/skeletons/der_encoder.c
index 3d5cc85..9ac0afb 100644
--- a/skeletons/der_encoder.c
+++ b/skeletons/der_encoder.c
@@ -34,7 +34,7 @@
 ssize_t
 der_write_tags(asn1_TYPE_descriptor_t *sd,
 		size_t struct_length,
-		int tag_mode,
+		int tag_mode, int last_tag_form,
 		ber_tlv_tag_t tag,	/* EXPLICIT or IMPLICIT tag */
 		asn_app_consume_bytes_f *cb,
 		void *app_key) {
@@ -112,10 +112,8 @@
 		ssize_t len;
 		int _constr;
 
-		/* If this one happens to be constructed, do it. */
-		if(i < (tags_count - 1) || sd->last_tag_form == 1)
-			_constr = 1;
-		else	_constr = 0;
+		/* Check if this tag happens to be constructed */
+		_constr = (last_tag_form || i < (tags_count - 1));
 
 		len = der_write_TL(tags[i], lens[i], cb, app_key, _constr);
 		if(len == -1) return -1;
@@ -151,9 +149,8 @@
 	 */
 	if(cb) {
 		if(constructed) *buf |= 0x20;
-		if(cb(buf, size, app_key) == -1) {
+		if(cb(buf, size, app_key) < 0)
 			return -1;
-		}
 	}
 
 	return size;
diff --git a/skeletons/der_encoder.h b/skeletons/der_encoder.h
index 2acccaa..5a29613 100644
--- a/skeletons/der_encoder.h
+++ b/skeletons/der_encoder.h
@@ -42,6 +42,7 @@
 		struct asn1_TYPE_descriptor_s *type_descriptor,
 		size_t struct_length,
 		int tag_mode,		/* {-1,0,1}: IMPLICIT, no, EXPLICIT */
+		int last_tag_form,	/* {0,!0}: prim, constructed */
 		ber_tlv_tag_t tag,
 		asn_app_consume_bytes_f *consume_bytes_cb,
 		void *app_key
diff --git a/skeletons/file-dependencies b/skeletons/file-dependencies
index 559d272..0f496cc 100644
--- a/skeletons/file-dependencies
+++ b/skeletons/file-dependencies
@@ -48,6 +48,7 @@
 asn_types.h
 OCTET_STRING.h OCTET_STRING.c	# This one is used too widely
 ber_decoder.h ber_decoder.c
+ber_codec_prim.c ber_codec_prim.h
 ber_tlv_length.h ber_tlv_length.c
 ber_tlv_tag.h ber_tlv_tag.c
 constr_TYPE.h constr_TYPE.c
diff --git a/skeletons/tests/check-INTEGER.c b/skeletons/tests/check-INTEGER.c
index a7edb73..03efc05 100644
--- a/skeletons/tests/check-INTEGER.c
+++ b/skeletons/tests/check-INTEGER.c
@@ -1,4 +1,5 @@
 #include <INTEGER.c>
+#include <ber_codec_prim.c>
 #include <ber_decoder.c>
 #include <ber_tlv_length.c>
 #include <ber_tlv_tag.c>
diff --git a/skeletons/tests/check-OIDs.c b/skeletons/tests/check-OIDs.c
index b992085..e435c01 100644
--- a/skeletons/tests/check-OIDs.c
+++ b/skeletons/tests/check-OIDs.c
@@ -1,6 +1,6 @@
 #include <OBJECT_IDENTIFIER.c>
 #include <RELATIVE-OID.c>
-#include <INTEGER.c>
+#include <ber_codec_prim.c>
 #include <ber_decoder.c>
 #include <ber_tlv_length.c>
 #include <ber_tlv_tag.c>
diff --git a/skeletons/tests/check-REAL.c b/skeletons/tests/check-REAL.c
index 12310e3..0d6d073 100644
--- a/skeletons/tests/check-REAL.c
+++ b/skeletons/tests/check-REAL.c
@@ -1,6 +1,6 @@
 #define	EMIT_ASN_DEBUG	1
-#include <INTEGER.c>
 #include <REAL.c>
+#include <ber_codec_prim.c>
 #include <ber_decoder.c>
 #include <ber_tlv_length.c>
 #include <ber_tlv_tag.c>
diff --git a/skeletons/xer_encoder.h b/skeletons/xer_encoder.h
index fbb7a81..8a619ca 100644
--- a/skeletons/xer_encoder.h
+++ b/skeletons/xer_encoder.h
@@ -13,7 +13,7 @@
 enum xer_encoder_flags_e {
 	/* Mode of encoding */
 	XER_F_BASIC	= 0x01,	/* BASIC-XER (pretty-printing) */
-	XER_F_CANONICAL	= 0x02,	/* Canonical XER (strict rules, unreadable) */
+	XER_F_CANONICAL	= 0x02	/* Canonical XER (strict rules, unreadable) */
 };
 
 /*