*** empty log message ***


git-svn-id: https://asn1c.svn.sourceforge.net/svnroot/asn1c/trunk@1116 59561ff5-6e30-0410-9f3c-9617f08c8826
diff --git a/skeletons/BIT_STRING.c b/skeletons/BIT_STRING.c
index 900f41d..7434a2e 100644
--- a/skeletons/BIT_STRING.c
+++ b/skeletons/BIT_STRING.c
@@ -45,18 +45,18 @@
  */
 int
 BIT_STRING_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	const BIT_STRING_t *st = (const BIT_STRING_t *)sptr;
 
 	if(st && st->buf) {
 		if(st->size == 1 && st->bits_unused) {
-			_ASN_ERRLOG(app_errlog, app_key,
+			_ASN_CTFAIL(app_key, td,
 				"%s: invalid padding byte (%s:%d)",
 				td->name, __FILE__, __LINE__);
 			return -1;
 		}
 	} else {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
diff --git a/skeletons/GeneralizedTime.c b/skeletons/GeneralizedTime.c
index 79f62e8..015fc6a 100644
--- a/skeletons/GeneralizedTime.c
+++ b/skeletons/GeneralizedTime.c
@@ -148,14 +148,14 @@
  */
 int
 GeneralizedTime_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	const GeneralizedTime_t *st = (const GeneralizedTime_t *)sptr;
 	time_t tloc;
 
 	errno = EPERM;			/* Just an unlikely error code */
 	tloc = asn_GT2time(st, 0, 0);
 	if(tloc == -1 && errno != EPERM) {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: Invalid time format: %s (%s:%d)",
 			td->name, strerror(errno), __FILE__, __LINE__);
 		return -1;
diff --git a/skeletons/IA5String.c b/skeletons/IA5String.c
index a4d7ff8..abc9ff3 100644
--- a/skeletons/IA5String.c
+++ b/skeletons/IA5String.c
@@ -37,7 +37,7 @@
 
 int
 IA5String_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	const IA5String_t *st = (const IA5String_t *)sptr;
 
 	if(st && st->buf) {
@@ -49,7 +49,7 @@
 		 */
 		for(; buf < end; buf++) {
 			if(*buf > 0x7F) {
-				_ASN_ERRLOG(app_errlog, app_key,
+				_ASN_CTFAIL(app_key, td,
 					"%s: value byte %ld out of range: "
 					"%d > 127 (%s:%d)",
 					td->name,
@@ -60,7 +60,7 @@
 			}
 		}
 	} else {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
diff --git a/skeletons/NativeReal.c b/skeletons/NativeReal.c
index 34eef23..1683f90 100644
--- a/skeletons/NativeReal.c
+++ b/skeletons/NativeReal.c
@@ -168,6 +168,7 @@
 		const void *buf_ptr, size_t size) {
 	asn_dec_rval_t rval;
 	REAL_t *st = 0;
+	REAL_t **stp = &st;
 	double *Dbl = (double *)*sptr;
 
 	if(!Dbl) {
@@ -180,7 +181,7 @@
 		}
 	}
 
-	rval = REAL_decode_xer(opt_codec_ctx, td, (void **)&st, opt_mname,
+	rval = REAL_decode_xer(opt_codec_ctx, td, (void **)stp, opt_mname,
 		buf_ptr, size);
 	if(rval.code == RC_OK) {
 		if(asn_REAL2double(st, Dbl)) {
diff --git a/skeletons/NumericString.c b/skeletons/NumericString.c
index e3302c6..f980dcd 100644
--- a/skeletons/NumericString.c
+++ b/skeletons/NumericString.c
@@ -37,7 +37,7 @@
 
 int
 NumericString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	const NumericString_t *st = (const NumericString_t *)sptr;
 
 	if(st && st->buf) {
@@ -55,7 +55,7 @@
 			case 0x35: case 0x36: case 0x37: case 0x38: case 0x39:
 				continue;
 			}
-			_ASN_ERRLOG(app_errlog, app_key,
+			_ASN_CTFAIL(app_key, td,
 				"%s: value byte %ld (%d) "
 				"not in NumericString alphabet (%s:%d)",
 				td->name,
@@ -65,7 +65,7 @@
 			return -1;
 		}
 	} else {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
diff --git a/skeletons/OBJECT_IDENTIFIER.c b/skeletons/OBJECT_IDENTIFIER.c
index a7cd52d..53d5353 100644
--- a/skeletons/OBJECT_IDENTIFIER.c
+++ b/skeletons/OBJECT_IDENTIFIER.c
@@ -39,19 +39,19 @@
 
 int
 OBJECT_IDENTIFIER_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	const OBJECT_IDENTIFIER_t *st = (const OBJECT_IDENTIFIER_t *)sptr;
 
 	if(st && st->buf) {
 		if(st->size < 1) {
-			_ASN_ERRLOG(app_errlog, app_key,
+			_ASN_CTFAIL(app_key, td,
 				"%s: at least one numerical value "
 				"expected (%s:%d)",
 				td->name, __FILE__, __LINE__);
 			return -1;
 		}
 	} else {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
diff --git a/skeletons/PrintableString.c b/skeletons/PrintableString.c
index 57f6573..5533253 100644
--- a/skeletons/PrintableString.c
+++ b/skeletons/PrintableString.c
@@ -60,7 +60,7 @@
 
 int
 PrintableString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	const PrintableString_t *st = (const PrintableString_t *)sptr;
 
 	if(st && st->buf) {
@@ -73,7 +73,7 @@
 		 */
 		for(; buf < end; buf++) {
 			if(!_PrintableString_alphabet[*buf]) {
-				_ASN_ERRLOG(app_errlog, app_key,
+				_ASN_CTFAIL(app_key, td,
 					"%s: value byte %ld (%d) "
 					"not in PrintableString alphabet "
 					"(%s:%d)",
@@ -85,7 +85,7 @@
 			}
 		}
 	} else {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
diff --git a/skeletons/UTCTime.c b/skeletons/UTCTime.c
index 9032dbd..5d7ba84 100644
--- a/skeletons/UTCTime.c
+++ b/skeletons/UTCTime.c
@@ -48,14 +48,14 @@
  */
 int
 UTCTime_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	const UTCTime_t *st = (const UTCTime_t *)sptr;
 	time_t tloc;
 
 	errno = EPERM;			/* Just an unlikely error code */
 	tloc = asn_UT2time(st, 0, 0);
 	if(tloc == -1 && errno != EPERM) {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: Invalid time format: %s (%s:%d)",
 			td->name, strerror(errno), __FILE__, __LINE__);
 		return -1;
diff --git a/skeletons/UTF8String.c b/skeletons/UTF8String.c
index 5d0334f..85f2ccd 100644
--- a/skeletons/UTF8String.c
+++ b/skeletons/UTF8String.c
@@ -67,30 +67,30 @@
 
 int
 UTF8String_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	ssize_t len = UTF8String_length((const UTF8String_t *)sptr);
 	switch(len) {
 	case U8E_EINVAL:
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given", td->name);
 		break;
 	case U8E_TRUNC:
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: truncated UTF-8 sequence (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		break;
 	case U8E_ILLSTART:
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: UTF-8 illegal start of encoding (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		break;
 	case U8E_NOTCONT:
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: UTF-8 not continuation (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		break;
 	case U8E_NOTMIN:
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: UTF-8 not minimal sequence (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		break;
diff --git a/skeletons/VisibleString.c b/skeletons/VisibleString.c
index 2a88169..7c70501 100644
--- a/skeletons/VisibleString.c
+++ b/skeletons/VisibleString.c
@@ -37,7 +37,7 @@
 
 int
 VisibleString_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	const VisibleString_t *st = (const VisibleString_t *)sptr;
 
 	if(st && st->buf) {
@@ -52,7 +52,7 @@
 		 */
 		for(; buf < end; buf++) {
 			if(*buf < 0x20 || *buf > 0x7e) {
-				_ASN_ERRLOG(app_errlog, app_key,
+				_ASN_CTFAIL(app_key, td,
 					"%s: value byte %ld (%d) "
 					"not in VisibleString alphabet (%s:%d)",
 					td->name,
@@ -63,7 +63,7 @@
 			}
 		}
 	} else {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
diff --git a/skeletons/asn_application.h b/skeletons/asn_application.h
index d639341..3f2a450 100644
--- a/skeletons/asn_application.h
+++ b/skeletons/asn_application.h
@@ -1,15 +1,15 @@
 /*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
 /*
- * Application-level ASN.1 API.
+ * Application-level ASN.1 callbacks.
  */
 #ifndef	_ASN_APPLICATION_H_
 #define	_ASN_APPLICATION_H_
 
-#include <asn_system.h>		/* for platform-dependent types */
-#include <asn_codecs.h>		/* for ASN.1 codecs specifics */
+#include "asn_system.h"		/* for platform-dependent types */
+#include "asn_codecs.h"		/* for ASN.1 codecs specifics */
 
 #ifdef __cplusplus
 extern "C" {
@@ -25,10 +25,24 @@
 typedef int (asn_app_consume_bytes_f)(const void *buffer, size_t size,
 	void *application_specific_key);
 
-#include <constr_TYPE.h>	/* for asn_TYPE_descriptor_t */
+/*
+ * A callback of this type is called whenever constraint validation fails
+ * on some ASN.1 type. See "constraints.h" for more details on constraint
+ * validation.
+ * This callback specifies a descriptor of the ASN.1 type which failed
+ * the constraint check, as well as human readable message on what
+ * particular constraint has failed.
+ */
+typedef void (asn_app_constraint_failed_f)(void *application_specific_key,
+	struct asn_TYPE_descriptor_s *type_descriptor_which_failed,
+	const void *structure_which_failed_ptr,
+	const char *error_message_format, ...)
+	__attribute__((format(printf, 4, 5)));
 
 #ifdef __cplusplus
 }
 #endif
 
+#include "constr_TYPE.h"	/* for asn_TYPE_descriptor_t */
+
 #endif	/* _ASN_APPLICATION_H_ */
diff --git a/skeletons/asn_internal.h b/skeletons/asn_internal.h
index 89c9c41..67f055a 100644
--- a/skeletons/asn_internal.h
+++ b/skeletons/asn_internal.h
@@ -9,7 +9,7 @@
 #ifndef	_ASN_INTERNAL_H_
 #define	_ASN_INTERNAL_H_
 
-#include <asn_application.h>	/* Application-visible API */
+#include "asn_application.h"	/* Application-visible API */
 
 #ifndef	__NO_ASSERT_H__		/* Include assert.h only for internal use. */
 #include <assert.h>		/* for assert() macro */
diff --git a/skeletons/constr_CHOICE.c b/skeletons/constr_CHOICE.c
index 26fd8dd..84a3b4e 100644
--- a/skeletons/constr_CHOICE.c
+++ b/skeletons/constr_CHOICE.c
@@ -475,12 +475,12 @@
 
 int
 CHOICE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	asn_CHOICE_specifics_t *specs = (asn_CHOICE_specifics_t *)td->specifics;
 	int present;
 
 	if(!sptr) {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
@@ -499,7 +499,7 @@
 			if(!memb_ptr) {
 				if(elm->optional)
 					return 0;
-				_ASN_ERRLOG(app_errlog, app_key,
+				_ASN_CTFAIL(app_key, td,
 					"%s: mandatory CHOICE element %s absent (%s:%d)",
 					td->name, elm->name, __FILE__, __LINE__);
 				return -1;
@@ -510,10 +510,10 @@
 
 		if(elm->memb_constraints) {
 			return elm->memb_constraints(elm->type, memb_ptr,
-				app_errlog, app_key);
+				ctfailcb, app_key);
 		} else {
 			int ret = elm->type->check_constraints(elm->type,
-					memb_ptr, app_errlog, app_key);
+					memb_ptr, ctfailcb, app_key);
 			/*
 			 * Cannot inherit it eralier:
 			 * need to make sure we get the updated version.
@@ -522,7 +522,7 @@
 			return ret;
 		}
 	} else {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: no CHOICE element given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
diff --git a/skeletons/constr_SEQUENCE.c b/skeletons/constr_SEQUENCE.c
index 80cd6af..d38afb5 100644
--- a/skeletons/constr_SEQUENCE.c
+++ b/skeletons/constr_SEQUENCE.c
@@ -972,11 +972,11 @@
 
 int
 SEQUENCE_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	int edx;
 
 	if(!sptr) {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
@@ -994,7 +994,7 @@
 			if(!memb_ptr) {
 				if(elm->optional)
 					continue;
-				_ASN_ERRLOG(app_errlog, app_key,
+				_ASN_CTFAIL(app_key, td,
 				"%s: mandatory element %s absent (%s:%d)",
 				td->name, elm->name, __FILE__, __LINE__);
 				return -1;
@@ -1005,11 +1005,11 @@
 
 		if(elm->memb_constraints) {
 			int ret = elm->memb_constraints(elm->type, memb_ptr,
-				app_errlog, app_key);
+				ctfailcb, app_key);
 			if(ret) return ret;
 		} else {
 			int ret = elm->type->check_constraints(elm->type,
-				memb_ptr, app_errlog, app_key);
+				memb_ptr, ctfailcb, app_key);
 			if(ret) return ret;
 			/*
 			 * Cannot inherit it earlier:
diff --git a/skeletons/constr_SET.c b/skeletons/constr_SET.c
index bb99eed..6d2d6c1 100644
--- a/skeletons/constr_SET.c
+++ b/skeletons/constr_SET.c
@@ -938,11 +938,11 @@
 
 int
 SET_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	int edx;
 
 	if(!sptr) {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
@@ -960,7 +960,7 @@
 			if(!memb_ptr) {
 				if(elm->optional)
 					continue;
-				_ASN_ERRLOG(app_errlog, app_key,
+				_ASN_CTFAIL(app_key, td,
 				"%s: mandatory element %s absent (%s:%d)",
 				td->name, elm->name, __FILE__, __LINE__);
 				return -1;
@@ -971,11 +971,11 @@
 
 		if(elm->memb_constraints) {
 			int ret = elm->memb_constraints(elm->type, memb_ptr,
-				app_errlog, app_key);
+				ctfailcb, app_key);
 			if(ret) return ret;
 		} else {
 			int ret = elm->type->check_constraints(elm->type,
-				memb_ptr, app_errlog, app_key);
+				memb_ptr, ctfailcb, app_key);
 			if(ret) return ret;
 			/*
 			 * Cannot inherit it earlier:
diff --git a/skeletons/constr_SET_OF.c b/skeletons/constr_SET_OF.c
index bb6d2d3..5642963 100644
--- a/skeletons/constr_SET_OF.c
+++ b/skeletons/constr_SET_OF.c
@@ -812,14 +812,14 @@
 
 int
 SET_OF_constraint(asn_TYPE_descriptor_t *td, const void *sptr,
-		asn_app_consume_bytes_f *app_errlog, void *app_key) {
+		asn_app_constraint_failed_f *ctfailcb, void *app_key) {
 	asn_TYPE_member_t *elm = td->elements;
 	asn_constr_check_f *constr;
 	const asn_anonymous_set_ *list = _A_CSET_FROM_VOID(sptr);
 	int i;
 
 	if(!sptr) {
-		_ASN_ERRLOG(app_errlog, app_key,
+		_ASN_CTFAIL(app_key, td,
 			"%s: value not given (%s:%d)",
 			td->name, __FILE__, __LINE__);
 		return -1;
@@ -838,7 +838,7 @@
 
 		if(!memb_ptr) continue;
 
-		ret = constr(elm->type, memb_ptr, app_errlog, app_key);
+		ret = constr(elm->type, memb_ptr, ctfailcb, app_key);
 		if(ret) return ret;
 	}
 
diff --git a/skeletons/constraints.c b/skeletons/constraints.c
index e384352..1bdda73 100644
--- a/skeletons/constraints.c
+++ b/skeletons/constraints.c
@@ -1,9 +1,9 @@
-#include <asn_internal.h>
-#include <constraints.h>
+#include "asn_internal.h"
+#include "constraints.h"
 
 int
 asn_generic_no_constraint(asn_TYPE_descriptor_t *type_descriptor,
-	const void *struct_ptr, asn_app_consume_bytes_f *cb, void *key) {
+	const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) {
 
 	(void)type_descriptor;	/* Unused argument */
 	(void)struct_ptr;	/* Unused argument */
@@ -16,7 +16,7 @@
 
 int
 asn_generic_unknown_constraint(asn_TYPE_descriptor_t *type_descriptor,
-	const void *struct_ptr, asn_app_consume_bytes_f *cb, void *key) {
+	const void *struct_ptr, asn_app_constraint_failed_f *cb, void *key) {
 
 	(void)type_descriptor;	/* Unused argument */
 	(void)struct_ptr;	/* Unused argument */
@@ -27,98 +27,67 @@
 	return 0;
 }
 
-struct __fill_errbuf_arg {
-	char  *errbuf;
+struct errbufDesc {
+	asn_TYPE_descriptor_t *failed_type;
+	const void *failed_struct_ptr;
+	char *errbuf;
 	size_t errlen;
-	size_t erroff;
 };
 
-static int
-__fill_errbuf(const void *buffer, size_t size, void *app_key) {
-	struct __fill_errbuf_arg *arg = (struct __fill_errbuf_arg *)app_key;
-	size_t avail = arg->errlen - arg->erroff;
+static void
+_asn_i_ctfailcb(void *key, asn_TYPE_descriptor_t *td, const void *sptr, const char *fmt, ...) {
+	struct errbufDesc *arg = key;
+	va_list ap;
+	ssize_t vlen;
+	ssize_t maxlen;
 
-	if(avail > size)
-		avail = size + 1;
+	arg->failed_type = td;
+	arg->failed_struct_ptr = sptr;
 
-	switch(avail) {
-	default:
-		memcpy(arg->errbuf + arg->erroff, buffer, avail - 1);
-		arg->erroff += avail - 1;
-	case 1:
-		arg->errbuf[arg->erroff] = '\0';
-	case 0:
-		return 0;
+	maxlen = arg->errlen;
+	if(maxlen <= 0)
+		return;
+
+	va_start(ap, fmt);
+	vlen = vsnprintf(arg->errbuf, maxlen, fmt, ap);
+	va_end(ap);
+	if(vlen >= maxlen) {
+		arg->errbuf[maxlen-1] = '\0';	/* Ensuring libc correctness */
+		arg->errlen = maxlen - 1;	/* Not counting termination */
+		return;
+	} else if(vlen >= 0) {
+		arg->errbuf[vlen] = '\0';	/* Ensuring libc correctness */
+		arg->errlen = vlen;		/* Not counting termination */
+	} else {
+		/*
+		 * The libc on this system is broken.
+		 */
+		vlen = sizeof("<broken vsnprintf>") - 1;
+		maxlen--;
+		arg->errlen = vlen < maxlen ? vlen : maxlen;
+		memcpy(arg->errbuf, "<broken vsnprintf>", arg->errlen);
+		arg->errbuf[arg->errlen] = 0;
 	}
 
+	return;
 }
 
 int
 asn_check_constraints(asn_TYPE_descriptor_t *type_descriptor,
-	const void *struct_ptr, char *errbuf, size_t *errlen) {
+		const void *struct_ptr, char *errbuf, size_t *errlen) {
+	struct errbufDesc arg;
+	int ret;
 
-	if(errlen) {
-		struct __fill_errbuf_arg arg;
-		int ret;
+	arg.failed_type = 0;
+	arg.failed_struct_ptr = 0;
+	arg.errbuf = errbuf;
+	arg.errlen = errlen ? *errlen : 0;
 
-		arg.errbuf = errbuf;
-		arg.errlen = *errlen;
-		arg.erroff = 0;
-	
-		ret = type_descriptor->check_constraints(type_descriptor,
-			struct_ptr, __fill_errbuf, &arg);
-	
-		if(ret == -1)
-			*errlen = arg.erroff;
+	ret = type_descriptor->check_constraints(type_descriptor,
+		struct_ptr, _asn_i_ctfailcb, &arg);
+	if(ret == -1 && errlen)
+		*errlen = arg.errlen;
 
-		return ret;
-	} else {
-		return type_descriptor->check_constraints(type_descriptor,
-			struct_ptr, 0, 0);
-	}
+	return ret;
 }
 
-void
-_asn_i_log_error(asn_app_consume_bytes_f *cb, void *key, const char *fmt, ...) {
-	char buf[64];
-	char *p;
-	va_list ap;
-	ssize_t ret;
-	size_t len;
-
-	va_start(ap, fmt);
-	ret = vsnprintf(buf, sizeof(buf), fmt, ap);
-	va_end(ap);
-	if(ret < 0) {
-		/*
-		 * The libc on this system is broken.
-		 */
-		ret = sizeof("<broken vsnprintf>") - 1;
-		memcpy(buf, "<broken vsnprintf>", ret + 1);
-		/* Fall through */
-	}
-
-	if(ret < (ssize_t)sizeof(buf)) {
-		(void)cb(buf, ret, key);
-		return;
-	}
-
-	/*
-	 * More space required to hold the message.
-	 */
-	len = ret + 1;
-	p = (char *)alloca(len);
-	if(!p) return;	/* Can fail on !x86. */
-
-	
-	va_start(ap, fmt);
-	ret = vsnprintf(p, len, fmt, ap);
-	va_end(ap);
-	if(ret < 0 || ret >= (ssize_t)len) {
-		ret = sizeof("<broken vsnprintf>") - 1;
-		memcpy(buf, "<broken vsnprintf>", ret + 1);
-		p = buf;
-	}
-
-	(void)cb(p, ret, key);
-}
diff --git a/skeletons/constraints.h b/skeletons/constraints.h
index 51fad8e..5032345 100644
--- a/skeletons/constraints.h
+++ b/skeletons/constraints.h
@@ -1,5 +1,5 @@
 /*-
- * Copyright (c) 2004 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Copyright (c) 2004, 2006 Lev Walkin <vlm@lionet.info>. All rights reserved.
  * Redistribution and modifications are permitted subject to BSD license.
  */
 #ifndef	_ASN1_CONSTRAINTS_VALIDATOR_H_
@@ -20,6 +20,10 @@
  * they could be passed as NULL's. If constraints validation fails,
  * errlen will contain the actual number of bytes taken from the errbuf
  * to encode an error message (properly 0-terminated).
+ * 
+ * RETURN VALUES:
+ * This function returns 0 in case all ASN.1 constraints are met
+ * and -1 if one or more constraints were failed.
  */
 int
 asn_check_constraints(struct asn_TYPE_descriptor_s *type_descriptor,
@@ -28,6 +32,7 @@
 	size_t *errlen		/* Length of the error description */
 	);
 
+
 /*
  * Generic type for constraint checking callback,
  * associated with every type descriptor.
@@ -35,8 +40,8 @@
 typedef int (asn_constr_check_f)(
 	struct asn_TYPE_descriptor_s *type_descriptor,
 	const void *struct_ptr,
-	asn_app_consume_bytes_f *optional_app_errlog,	/* Log the error */
-	void *optional_app_key		/* Opaque key passed to app_errlog */
+	asn_app_constraint_failed_f *optional_callback,	/* Log the error */
+	void *optional_app_key		/* Opaque key passed to a callback */
 	);
 
 /*******************************
@@ -49,11 +54,7 @@
 /*
  * Invoke the callback with a complete error message.
  */
-/* Preprocessor may not support variable args macros, so act strangely */
-#define	_ASN_ERRLOG	if(app_errlog) _asn_i_log_error
-
-void _asn_i_log_error(asn_app_consume_bytes_f *, void *key,
-	const char *fmt, ...) __attribute__ ((format(printf, 3, 4)));
+#define	_ASN_CTFAIL	if(ctfailcb) ctfailcb
 
 #ifdef __cplusplus
 }