Index: libfdproto/dictionary.c
===================================================================
--- libfdproto/dictionary.c	(revision 1052)
+++ libfdproto/dictionary.c	(revision 1085)
@@ -148,11 +148,11 @@
 
 /* Forward declarations of dump functions */
-static void dump_vendor_data 	  ( void * data );
-static void dump_application_data ( void * data );
-static void dump_type_data 	  ( void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data );
   /* the dump function for enum has a different prototype since it need the datatype */
-static void dump_avp_data 	  ( void * data );
-static void dump_command_data 	  ( void * data );
-static void dump_rule_data 	  ( void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data );
+static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data );
 
 /* Forward declarations of search functions */
@@ -173,5 +173,5 @@
 	enum dict_object_type	parenttype;	/* The type of the parent, when relevant */
 	int			eyecatcher;	/* A kind of signature for this object */
-	void 		      (*dump_data)(void * data );	/* The function to dump the data section */
+	DECLARE_FD_DUMP_PROTOTYPE( (*dump_data), void * data );	/* The function to dump the data section */
 	int 		      (*search_fct)(struct dictionary * dict, int criteria, const void * what, struct dict_object **result );;	/* The function to search an object of this type */
 	int			haslist[NB_LISTS_PER_OBJ];	/* Tell if this list is used */
@@ -1150,27 +1150,27 @@
 /*******************************************************************************************************/
 /* The following functions are used to debug the module, and allow to print out the content of the dictionary */
-static void dump_vendor_data ( void * data )
+static DECLARE_FD_DUMP_PROTOTYPE(dump_vendor_data, void * data )
 {
 	struct dict_vendor_data * vendor = (struct dict_vendor_data *)data;
 	
-	fd_log_debug("data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name);
-}
-static void dump_application_data ( void * data )
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", vendor->vendor_id, vendor->vendor_name);
+}
+static DECLARE_FD_DUMP_PROTOTYPE(dump_application_data, void * data )
 {
 	struct dict_application_data * appli = (struct dict_application_data *) data;
-	fd_log_debug("data: %-6u \"%s\"", appli->application_id, appli->application_name);
-}
-static void dump_type_data ( void * data )
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-6u \"%s\"", appli->application_id, appli->application_name);
+}
+static DECLARE_FD_DUMP_PROTOTYPE(dump_type_data, void * data )
 {
 	struct dict_type_data * type = ( struct dict_type_data * ) data;
 	
-	fd_log_debug("data: %-12s \"%s\"", 
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: %-12s \"%s\"", 
 			type_base_name[type->type_base], 
 			type->type_name);
 }
-static void dump_enumval_data ( struct dict_enumval_data * enumval, enum dict_avp_basetype type )
+static DECLARE_FD_DUMP_PROTOTYPE(dump_enumval_data, struct dict_enumval_data * enumval, enum dict_avp_basetype type )
 {
 	const int LEN_MAX = 20;
-	fd_log_debug("data: (%-12s) \"%s\" -> ", type_base_name[type], enumval->enum_name);
+	CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "data: (%-12s) \"%s\" -> ", type_base_name[type], enumval->enum_name), return NULL);
 	switch (type) {
 		case AVP_TYPE_OCTETSTRING:
@@ -1180,42 +1180,43 @@
 					n = enumval->enum_value.os.len;
 				for (i=0; i < n; i++)
-					fd_log_debug("0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i]));
+					CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "0x%2hhX/'%c' ", enumval->enum_value.os.data[i], ASCII(enumval->enum_value.os.data[i])), return NULL);
 				if (n == LEN_MAX)
-					fd_log_debug("...");
+					CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "..."), return NULL);
 			}
 			break;
 		
 		case AVP_TYPE_INTEGER32:
-			fd_log_debug("%i", enumval->enum_value.i32);
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%i", enumval->enum_value.i32), return NULL);
 			break;
 
 		case AVP_TYPE_INTEGER64:
-			fd_log_debug("%"PRId64, enumval->enum_value.i64);
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRId64, enumval->enum_value.i64), return NULL);
 			break;
 
 		case AVP_TYPE_UNSIGNED32:
-			fd_log_debug("%u", enumval->enum_value.u32);
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%u", enumval->enum_value.u32), return NULL);
 			break;
 
 		case AVP_TYPE_UNSIGNED64:
-			fd_log_debug("%"PRIu64, enumval->enum_value.u64);
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%"PRIu64, enumval->enum_value.u64), return NULL);
 			break;
 
 		case AVP_TYPE_FLOAT32:
-			fd_log_debug("%f", enumval->enum_value.f32);
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", enumval->enum_value.f32), return NULL);
 			break;
 
 		case AVP_TYPE_FLOAT64:
-			fd_log_debug("%g", enumval->enum_value.f64);
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", enumval->enum_value.f64), return NULL);
 			break;
 		
 		default:
-			fd_log_debug("??? (ERROR unknown type %d)", type);
-	}
-}
-static void dump_avp_data ( void * data )
+			CHECK_MALLOC_DO(fd_dump_extend( FD_DUMP_STD_PARAMS, "??? (ERROR unknown type %d)", type), return NULL);
+	}
+	return *buf;
+}
+static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_data, void * data )
 {
 	struct dict_avp_data * avp = (struct dict_avp_data * ) data;
-	fd_log_debug("data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", 
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_AVPFL_str "/" DUMP_AVPFL_str ", %12s, %-6u \"%s\"", 
 			DUMP_AVPFL_val(avp->avp_flag_val), 
 			DUMP_AVPFL_val(avp->avp_flag_mask), 
@@ -1224,14 +1225,14 @@
 			avp->avp_name );
 }
-static void dump_command_data ( void * data )
+static DECLARE_FD_DUMP_PROTOTYPE(dump_command_data, void * data )
 {
 	struct dict_cmd_data * cmd = (struct dict_cmd_data *) data;
-	fd_log_debug("data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", 
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: v/m:" DUMP_CMDFL_str "/" DUMP_CMDFL_str ", %-6u \"%s\"", 
 			DUMP_CMDFL_val(cmd->cmd_flag_val), DUMP_CMDFL_val(cmd->cmd_flag_mask), cmd->cmd_code, cmd->cmd_name);
 }
-static void dump_rule_data ( void * data )
+static DECLARE_FD_DUMP_PROTOTYPE(dump_rule_data, void * data )
 {
 	struct dict_rule_data * rule = (struct dict_rule_data * )data;
-	fd_log_debug("data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"", 
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "data: pos:%d ord:%d m/M:%2d/%2d avp:\"%s\"",
 			rule->rule_position, 
 			rule->rule_order, 
@@ -1241,7 +1242,7 @@
 }
 
-static void dump_object ( struct dict_object * obj, int parents, int depth, int indent );
-
-static void dump_list ( struct fd_list * sentinel, int parents, int depth, int indent )
+static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent );
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_list, struct fd_list * sentinel, int parents, int depth, int indent )
 {
 	struct fd_list * li = sentinel;
@@ -1250,28 +1251,33 @@
 	{
 		li = li->next;
-		dump_object( _O(li->o), parents, depth, indent );
-	}
-}
-
-static void dump_object ( struct dict_object * obj, int parents, int depth, int indent )
-{
-	if (obj == NULL)
-		return;
-	
-	if (parents)
-		dump_object (obj->parent, parents-1, 0, indent + 1 );
-	
-	fd_log_debug("%*s@%p: %s%s (p:%-9p) ", 
-			indent,
-			"",
-			obj, 
-			verify_object(obj) ? "" : "INVALID ", 
-			_OBINFO(obj).name, 
-			obj->parent);
-	
-	if (obj->type == DICT_ENUMVAL)
-		dump_enumval_data ( &obj->data.enumval, obj->parent->data.type.type_base );
-	else
-		_OBINFO(obj).dump_data(&obj->data);
+		CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, _O(li->o), parents, depth, indent ), return NULL);
+	}
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_object, struct dict_object * obj, int parents, int depth, int indent )
+{
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*s{dictobj}(@%p): ", indent, "", obj), return NULL);
+	
+	if (!verify_object(obj)) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL\n"), return NULL);
+		return *buf;
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s p:%p ", 
+								_OBINFO(obj).name, 
+								obj->parent), return NULL);
+	
+	if (obj->type == DICT_ENUMVAL) {
+		CHECK_MALLOC_DO( dump_enumval_data ( FD_DUMP_STD_PARAMS, &obj->data.enumval, obj->parent->data.type.type_base ), return NULL);
+	} else {
+		CHECK_MALLOC_DO( _OBINFO(obj).dump_data(FD_DUMP_STD_PARAMS, &obj->data), return NULL);
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n"), return NULL);
+	
+	if (parents) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*sparent:", indent + 1, ""), return NULL);
+		CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, obj->parent, parents-1, 0, 0 ), return NULL);
+	}
 	
 	if (depth) {
@@ -1279,60 +1285,68 @@
 		for (i=0; i<NB_LISTS_PER_OBJ; i++) {
 			if ((obj->list[i].o == NULL) && (obj->list[i].next != &obj->list[i])) {
-				fd_log_debug("%*s>%p: list[%d]:", indent, "", obj, i);
-				dump_list(&obj->list[i], parents, depth - 1, indent + 2);
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%*slist[%d]:\n", indent + 1, "", i), return NULL);
+				CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &obj->list[i], 0, depth - 1, indent + 2), return NULL);
 			}
 		}
 	}
-}
-
-void fd_dict_dump_object(struct dict_object * obj)
-{
-	fd_log_debug("Dictionary object %p dump:", obj);
-	dump_object( obj, 1, 2, 2 );
-}
-
-void fd_dict_dump(struct dictionary * dict)
+	
+	return *buf;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_object, struct dict_object * obj)
+{
+	size_t o = 0;
+
+	if (!offset)
+		offset = &o;
+	
+	CHECK_MALLOC_DO( dump_object(FD_DUMP_STD_PARAMS, obj, 1, 2, 0), return NULL);
+	
+	return *buf;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump, struct dictionary * dict)
 {
 	int i;
 	struct fd_list * li;
-	
-	CHECK_PARAMS_DO(dict && (dict->dict_eyec == DICT_EYECATCHER), return);
+	size_t o = 0;
+
+	if (!offset)
+		offset = &o;
+		
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{dictionary}(@%p): ", dict), return NULL);
+	
+	if ((dict == NULL) || (dict->dict_eyec != DICT_EYECATCHER)) {
+		return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL\n");
+	}
 	
 	CHECK_POSIX_DO(  pthread_rwlock_rdlock( &dict->dict_lock ), /* ignore */  );
 	
-	fd_log_debug("######################################################");
-	fd_log_debug("###### Dumping vendors, AVPs and related rules #######");
-	
-	dump_object( &dict->dict_vendors, 0, 3, 0 );
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "\n {dict:%p > vendors, AVPs and related rules}\n", dict), goto error);
+	CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_vendors, 0, 3, 3 ), goto error);
 	for (li = dict->dict_vendors.list[0].next; li != &dict->dict_vendors.list[0]; li = li->next)
-		dump_object( li->o, 0, 3, 0 );
-	
-	fd_log_debug("######          Dumping applications           #######");
-
-	dump_object( &dict->dict_applications, 0, 1, 0 );
+		CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 3, 3 ), goto error);
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > applications}\n", dict), goto error);
+	CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, &dict->dict_applications, 0, 1, 3 ), goto error);
 	for (li = dict->dict_applications.list[0].next; li != &dict->dict_applications.list[0]; li = li->next)
-		dump_object( li->o, 0, 1, 0 );
-	
-	fd_log_debug("######             Dumping types               #######");
-
-	dump_list( &dict->dict_types, 0, 2, 0 );
-	
-	fd_log_debug("######      Dumping commands per name          #######");
-
-	dump_list( &dict->dict_cmd_name, 0, 2, 0 );
-	
-	fd_log_debug("######   Dumping commands per code and flags   #######");
-
-	dump_list( &dict->dict_cmd_code, 0, 0, 0 );
-	
-	fd_log_debug("######             Statistics                  #######");
-
+		CHECK_MALLOC_DO( dump_object (FD_DUMP_STD_PARAMS, li->o, 0, 1, 3 ), goto error);
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > types}\n", dict), goto error);
+	CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_types, 0, 2, 3 ), goto error);
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > commands}\n", dict), goto error);
+	CHECK_MALLOC_DO( dump_list(FD_DUMP_STD_PARAMS, &dict->dict_cmd_code, 0, 0, 3 ), goto error);
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " {dict:%p > statistics}\n", dict), goto error);
 	for (i=1; i<=DICT_TYPE_MAX; i++)
-		fd_log_debug(" %5d objects of type %s", dict->dict_count[i], dict_obj_info[i].name);
-	
-	fd_log_debug("######################################################");
-	
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "   %5d: %s\n",  dict->dict_count[i], dict_obj_info[i].name), goto error);
+	
+	CHECK_POSIX_DO(  pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */  );
+	return *buf;
+error:	
 	/* Free the rwlock */
 	CHECK_POSIX_DO(  pthread_rwlock_unlock( &dict->dict_lock ), /* ignore */  );
+	return NULL;
 }
 
@@ -1340,57 +1354,52 @@
 
 /* Default dump functions */
-static int dump_val_os(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_os, union avp_value * value)
 {
 	int i;
-	CHECK_FCT( dump_add_str(outstr, offset, outlen, "<") );
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<"), return NULL);
 	for (i = 0; i < value->os.len; i++) {
 		if (i == 1024) { /* Dump only up to 1024 bytes of the buffer */
-			CHECK_FCT( dump_add_str(outstr, offset, outlen, "[...] (len=%zd)", value->os.len) );
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "[...] (len=%zd)", value->os.len), return NULL);
 			break;
 		}
-		CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s%02.2X", (i==0 ? "" : " "), value->os.data[i]) );
-	}
-	CHECK_FCT( dump_add_str(outstr, offset, outlen, ">") );
-	return 0;
-}
-
-static int dump_val_i32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
-{
-	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%i (0x%x)", value->i32, value->i32) );
-	return 0;
-}
-
-static int dump_val_i64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
-{
-	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%lli (0x%llx)", value->i64, value->i64) );
-	return 0;
-}
-
-static int dump_val_u32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
-{
-	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%u (0x%x)", value->u32, value->u32) );
-	return 0;
-}
-
-static int dump_val_u64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
-{
-	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%llu (0x%llx)", value->u64, value->u64) );
-	return 0;
-}
-
-static int dump_val_f32(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
-{
-	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%f", value->f32) );
-	return 0;
-}
-
-static int dump_val_f64(union avp_value * value, char **outstr, size_t *offset, size_t *outlen)
-{
-	CHECK_FCT( dump_add_str(outstr, offset, outlen, "%g", value->f64) );
-	return 0;
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s%02hhX", (i==0 ? "" : " "), value->os.data[i]), return NULL);
+	}
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ">"), return NULL);
+	return *buf;
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i32, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%i (0x%x)", value->i32, value->i32);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_i64, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRId64 " (0x%" PRIx64 ")", value->i64, value->i64);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u32, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%u (0x%x)", value->u32, value->u32);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_u64, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%" PRIu64 " (0x%" PRIx64 ")", value->u64, value->u64);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f32, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%f", value->f32);
+}
+
+static DECLARE_FD_DUMP_PROTOTYPE(dump_val_f64, union avp_value * value)
+{
+	return fd_dump_extend( FD_DUMP_STD_PARAMS, "%g", value->f64);
 }
 
 /* Get the dump function for basic dict_avp_basetype */
-static int (*get_default_dump_val_cb(enum dict_avp_basetype datatype))(union avp_value *, char **, size_t *, size_t *)
+static DECLARE_FD_DUMP_PROTOTYPE((*get_default_dump_val_cb(enum dict_avp_basetype datatype)), union avp_value *)
 {
 	switch (datatype) {
@@ -1426,61 +1435,61 @@
 #define INOBJHDRVAL 	indent<0 ? 1 : indent, indent<0 ? "-" : "|"
 
+typedef DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb_t), union avp_value *);
+
 /* Formatter for the AVP value dump line */
-static int dump_avp_val(union avp_value *avp_value, 
-			int (*def_dump_val_cb)(union avp_value *, char **, size_t *, size_t *), 
-			char * (*dump_val_cb)(union avp_value *), 
+static DECLARE_FD_DUMP_PROTOTYPE(dump_avp_val, union avp_value *avp_value, 
+			dump_val_cb_t def_dump_val_cb, 
+			dump_val_cb_t dump_val_cb, 
 			enum dict_avp_basetype datatype, 
 			char * type_name, 
 			char * const_name, 
 			int indent, 
-			char **outstr, 
-			size_t *offset, 
-			size_t *outlen,
 		        int header)
 {
 	if (header) {
 		/* Header for all AVP values dumps: */
-		CHECK_FCT( dump_add_str(outstr, offset, outlen, INOBJHDR "value ", INOBJHDRVAL) );
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, INOBJHDR "value ", INOBJHDRVAL), return NULL);
 	
 		/* If the type is provided, write it */
 		if (type_name) {
-			CHECK_FCT( dump_add_str(outstr, offset, outlen, "t: '%s' ", type_name) );
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "t: '%s' ", type_name), return NULL);
 		}
 	
 		/* Always give the base datatype anyway */
-		CHECK_FCT( dump_add_str(outstr, offset, outlen, "(%s) ", type_base_name[datatype]) );
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(%s) ", type_base_name[datatype]), return NULL);
 
 		/* Now, the value */
-		CHECK_FCT( dump_add_str(outstr, offset, outlen, "v: ") );
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "v: "), return NULL);
 	}
 	if (const_name) {
-		CHECK_FCT( dump_add_str(outstr, offset, outlen, "'%s' (", const_name) );
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s' (", const_name), return NULL);
 	}
 	if (dump_val_cb) {
-		char * str;
-		CHECK_MALLOC_DO( str = (*dump_val_cb)(avp_value), dump_add_str(outstr, offset, outlen, "(dump failed)") );
-		CHECK_FCT( dump_add_str(outstr, offset, outlen, "%s", str) );
-		free(str);
+		CHECK_MALLOC_DO( (*dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), fd_dump_extend( FD_DUMP_STD_PARAMS, "(dump failed)"));
 	} else {
-		CHECK_FCT( (*def_dump_val_cb)(avp_value, outstr, offset, outlen) );
+		CHECK_MALLOC_DO( (*def_dump_val_cb)( FD_DUMP_STD_PARAMS, avp_value), return NULL);
 	}
 	if (const_name) {
-		CHECK_FCT( dump_add_str(outstr, offset, outlen, ")") );
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, ")"), return NULL);
 	}
 	
 	/* Done! */
-	return 0;
+	return *buf;
 }
 
 /* Dump the value of an AVP of known type into the returned str */
-int fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, char **outstr, size_t *offset, size_t *outlen, int header)
-{
-	char * (*dump_val_cb)(union avp_value *avp_value) = NULL;
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_avp_value, union avp_value *avp_value, struct dict_object * model, int indent, int header)
+{
+	DECLARE_FD_DUMP_PROTOTYPE((*dump_val_cb), union avp_value *avp_value) = NULL;
 	struct dict_object * type = NULL;
 	char * type_name = NULL;
 	char * const_name = NULL;
+	size_t o = 0;
+	
+	if (!offset)
+		offset = &o;
 	
 	/* Check the parameters are correct */
-	CHECK_PARAMS( avp_value && verify_object(model) && (model->type == DICT_AVP) );
+	CHECK_PARAMS_DO( avp_value && verify_object(model) && (model->type == DICT_AVP), return NULL );
 	
 	/* Get the type definition of this AVP */
@@ -1502,5 +1511,5 @@
 		/* bypass checks */
 		if ((search_enumval( type->dico, ENUMVAL_BY_STRUCT, &request, &enumval ) == 0) && (enumval)) {
-			/* We found a cosntant, get its name */
+			/* We found a constant, get its name */
 			const_name = enumval->data.enumval.enum_name;
 		}
@@ -1508,6 +1517,6 @@
 	
 	/* And finally, dump the value */
-	CHECK_FCT( dump_avp_val(avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, outstr, offset, outlen, header) );
-	return 0;
+	CHECK_MALLOC_DO( dump_avp_val(FD_DUMP_STD_PARAMS, avp_value, get_default_dump_val_cb(model->data.avp.avp_basetype), dump_val_cb, model->data.avp.avp_basetype, type_name, const_name, indent, header), return NULL );
+	return *buf;
 }
 
@@ -1574,5 +1583,5 @@
 	switch (dict_obj_info[type].parent) {
 		case 0:	/* parent is forbidden */
-			CHECK_PARAMS( parent == NULL );
+			CHECK_PARAMS_DO( parent == NULL, goto error_param );
 		
 		case 1:	/* parent is optional */
@@ -1581,11 +1590,11 @@
 		
 		case 2: /* parent is mandatory */
-			CHECK_PARAMS(  verify_object(parent)  );
+			CHECK_PARAMS_DO(  verify_object(parent), goto error_param  );
 			
 			if (type == DICT_RULE ) { /* Special case : grouped AVP or Command parents are allowed */
-				CHECK_PARAMS( (parent->type == DICT_COMMAND ) 
-						|| ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ) );
+				CHECK_PARAMS_DO( (parent->type == DICT_COMMAND ) 
+						|| ( (parent->type == DICT_AVP) && (parent->data.avp.avp_basetype == AVP_TYPE_GROUPED ) ), goto error_param );
 			} else {
-				CHECK_PARAMS( parent->type == dict_obj_info[type].parenttype );
+				CHECK_PARAMS_DO( parent->type == dict_obj_info[type].parenttype, goto error_param );
 			}
 	}
@@ -1594,9 +1603,9 @@
 	if (type == DICT_AVP) {
 		CHECK_FCT_DO(  fd_dict_search( dict, DICT_VENDOR, VENDOR_BY_ID, &(((struct dict_avp_data *)data)->avp_vendor), (void*)&vendor, ENOENT ),
-			{ TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); return EINVAL; }  );
+			{ TRACE_DEBUG(INFO, "Unable to find vendor '%d' referenced in the AVP data", ((struct dict_avp_data *)data)->avp_vendor); goto error_param; }  );
 		
 		/* Also check if a parent is provided, that the type are the same */
 		if (parent) {
-			CHECK_PARAMS(  parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype  );
+			CHECK_PARAMS_DO(  parent->data.type.type_base == ((struct dict_avp_data *)data)->avp_basetype, goto error_param  );
 		}
 	}
@@ -1604,19 +1613,19 @@
 	/* For RULE object, we must also check that the "avp" referenced exists */
 	if (type == DICT_RULE) {
-		CHECK_PARAMS(  verify_object(((struct dict_rule_data *)data)->rule_avp)  );
-		CHECK_PARAMS(  ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP  );
+		CHECK_PARAMS_DO(  verify_object(((struct dict_rule_data *)data)->rule_avp), goto error_param  );
+		CHECK_PARAMS_DO(  ((struct dict_rule_data *)data)->rule_avp->type == DICT_AVP, goto error_param  );
 	}
 	
 	/* For COMMAND object, check that the 'R' flag is fixed */
 	if (type == DICT_COMMAND) {
-		CHECK_PARAMS( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST   );
+		CHECK_PARAMS_DO( ((struct dict_cmd_data *)data)->cmd_flag_mask & CMD_FLAG_REQUEST, goto error_param   );
 	}
 	
 	/* We have to check that the new values are not equal to the sentinels */
 	if (type == DICT_VENDOR) {
-		CHECK_PARAMS( ((struct dict_vendor_data *)data)->vendor_id != 0   );
+		CHECK_PARAMS_DO( ((struct dict_vendor_data *)data)->vendor_id != 0, goto error_param   );
 	}
 	if (type == DICT_APPLICATION) {
-		CHECK_PARAMS( ((struct dict_application_data *)data)->application_id != 0   );
+		CHECK_PARAMS_DO( ((struct dict_application_data *)data)->application_id != 0, goto error_param   );
 	}
 	
@@ -1718,4 +1727,8 @@
 	return 0;
 	
+error_param:
+	ret = EINVAL;
+	goto all_errors;
+
 error_unlock:
 	CHECK_POSIX_DO(  pthread_rwlock_unlock(&dict->dict_lock),  /* continue */  );
@@ -1728,5 +1741,5 @@
 				if (fd_os_cmp(locref->data.vendor.vendor_name, locref->datastr_len, 
 						new->data.vendor.vendor_name, new->datastr_len)) {
-					TRACE_DEBUG(FULL, "Conflicting vendor name");
+					TRACE_DEBUG(INFO, "Conflicting vendor name: %s", new->data.vendor.vendor_name);
 					break;
 				}
@@ -1866,21 +1879,24 @@
 				break;
 		}
-		if (ret) {
-			TRACE_DEBUG(INFO, "An existing object with different non-key data was found: EEXIST");
-			if (TRACE_BOOL(INFO)) {
-				fd_log_debug("New object to insert:");
-				dump_object(new, 0, 0, 3);
-				fd_log_debug("Object already in dictionary:");			
-				dump_object(locref, 0, 0 , 3);
-			}
-		} else {
+		if (!ret) {
 			TRACE_DEBUG(FULL, "An existing object with the same data was found, ignoring the error...");
 		}
 		if (ref)
 			*ref = locref;
-	} else {
-		CHECK_FCT_DO( ret, ); /* log the error */ 
-	}
-
+	}
+all_errors:
+	if (ret != 0) {
+		char * buf = NULL;
+		size_t len = 0;
+		
+		CHECK_MALLOC( dict_obj_info[CHECK_TYPE(type) ? type : 0].dump_data(&buf, &len, NULL, data) );
+		TRACE_DEBUG(INFO, "An error occurred while adding the following data in the dictionary: %s", buf);
+		
+		if (ret == EEXIST) {
+			CHECK_MALLOC( dump_object(&buf, &len, NULL, locref, 0, 0, 0) );
+			TRACE_DEBUG(INFO, "Conflicting entry in the dictionary: %s", buf);
+		}
+		free(buf);
+	}
 error_free:
 	free(new);
Index: libfdproto/dictionary_functions.c
===================================================================
--- libfdproto/dictionary_functions.c	(revision 1052)
+++ libfdproto/dictionary_functions.c	(revision 1085)
@@ -153,8 +153,6 @@
 
 /* Dump the content of an Address AVP */
-char * fd_dictfct_Address_dump(union avp_value * avp_value)
-{
-	char * ret;
-	#define STR_LEN	1024
+DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Address_dump, union avp_value * avp_value)
+{
 	union {
 		sSA	sa;
@@ -164,13 +162,15 @@
 	} s;
 	uint16_t fam;
+	size_t o = 0;
+	
+	if (!offset)
+		offset = &o;
 	
 	memset(&s, 0, sizeof(s));
-	
-	CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL );
 	
 	/* The first two octets represent the address family, http://www.iana.org/assignments/address-family-numbers/ */
 	if (avp_value->os.len < 2) {
-		snprintf(ret, STR_LEN, "[invalid length: %zd]", avp_value->os.len);
-		return ret;
+		CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid length: %zd]", avp_value->os.len), return NULL);
+		return *buf;
 	}
 	
@@ -182,6 +182,6 @@
 			s.sa.sa_family = AF_INET;
 			if (avp_value->os.len != 6) {
-				snprintf(ret, STR_LEN, "[invalid IP length: %zd]", avp_value->os.len);
-				return ret;
+				CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP length: %zd]", avp_value->os.len), return NULL);
+				return *buf;
 			}
 			memcpy(&s.sin.sin_addr.s_addr, avp_value->os.data + 2, 4);
@@ -191,21 +191,15 @@
 			s.sa.sa_family = AF_INET6;
 			if (avp_value->os.len != 18) {
-				snprintf(ret, STR_LEN, "[invalid IP6 length: %zd]", avp_value->os.len);
-				return ret;
+				CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid IP6 length: %zd]", avp_value->os.len), return NULL);
+				return *buf;
 			}
 			memcpy(&s.sin6.sin6_addr.s6_addr, avp_value->os.data + 2, 16);
 			break;
 		default:
-			snprintf(ret, STR_LEN, "[unsupported family: 0x%hx]", fam);
-			return ret;
-	}
-	
-	{
-		int rc = getnameinfo(&s.sa, sSAlen(&s.sa), ret, STR_LEN, NULL, 0, NI_NUMERICHOST);
-		if (rc)
-			snprintf(ret, STR_LEN, "%s", (char *)gai_strerror(rc));
-	}
-	
-	return ret;
+			CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[unsupported family: 0x%hx]", fam), return NULL);
+			return *buf;
+	}
+	
+	return fd_sa_dump_node(FD_DUMP_STD_PARAMS, &s.sa, NI_NUMERICHOST);
 }
 
@@ -216,40 +210,23 @@
 /*******************************/
 
-/* Dump the AVP in a natural human-readable format */
-char * fd_dictfct_UTF8String_dump(union avp_value * avp_value)
-{
-#define TRUNC_LEN	1024 /* avoid very long strings */
-	char * ret;
-	CHECK_MALLOC_DO( ret = malloc(TRUNC_LEN+2+3+1), return NULL );
-	*ret = '"';
-	strncpy(ret+1, (char *)avp_value->os.data, TRUNC_LEN);
-	/* be sure to have a nul-terminated string */
-	ret[TRUNC_LEN+1] = '\0';
-	if (ret[1] != '\0') {
-		/* We sanitize the returned string to avoid UTF8 boundary problem.
-		We do this whether the string is trucated at TRUNC_LEN or not, to avoid potential problem
-		with malformed AVP */
-
-		char * end = strchr(ret, '\0');
-		while (end > ret) {
-			end--;
-			char b = *end;
-			/* after the position pointed by end, we have only \0s */
-			if ((b & 0x80) == 0) {
-				break; /* this is a single byte char, no problem */
-			} else {
-				/* this byte is start or cont. of multibyte sequence, as we do not know the next byte we need to delete it. */
-				*end = '\0';
-				if (b & 0x40)
-					break; /* This was a start byte, we can stop the loop */
-			}
-		}
-		if (strlen((char *)avp_value->os.data) > strlen(ret+1))
-			strcat(end, "...");
-		strcat(end, "\"");
-	} else {
-		*ret = '\0';
-	}
-	return ret;
+/* Dump the AVP in a natural human-readable format. This dumps the complete length of the AVP, it is up to the caller to truncate if needed */
+DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_UTF8String_dump, union avp_value * avp_value)
+{
+	size_t o = 0, l;
+	if (!offset)
+		offset = &o;
+	
+	l = avp_value->os.len;
+	/* Just in case the string ends in invalid UTF-8 chars, we shorten it */
+	while ((l > 0) && (avp_value->os.data[l - 1] & 0x80)) {
+		/* this byte is start or cont. of multibyte sequence, as we do not know the next byte we need to delete it. */
+		l--;
+		if (avp_value->os.data[l] & 0x40)
+			break; /* This was a start byte, we can stop the loop */
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "\"%.*s\"", (int)l, (char *)avp_value->os.data), return NULL);
+	
+	return *buf;
 }
 
@@ -326,21 +303,25 @@
 }
 
-char * fd_dictfct_Time_dump(union avp_value * avp_value)
-{
-	char * ret;
+DECLARE_FD_DUMP_PROTOTYPE(fd_dictfct_Time_dump, union avp_value * avp_value)
+{
+	size_t o = 0;
 	time_t val;
 	struct tm conv;
-	CHECK_MALLOC_DO( ret = malloc(STR_LEN), return NULL );
+		
+	if (!offset)
+		offset = &o;
+	
 	if (avp_value->os.len != 4) {
-		snprintf(ret, STR_LEN, "[invalid length: %zd]", avp_value->os.len);
-		return ret;
-	}
+		CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[invalid length: %zd]", avp_value->os.len), return NULL);
+		return *buf;
+	}
+
 	if (diameter_string_to_time_t((char *)avp_value->os.data, avp_value->os.len, &val) != 0) {
-		snprintf(ret, STR_LEN, "[time conversion error]");
-		return ret;
-	}
-	gmtime_r(&val, &conv);
-	snprintf(ret, STR_LEN, "%d%02d%02dT%02d%02d%02d+00", conv.tm_year+1900, conv.tm_mon+1, conv.tm_mday, conv.tm_hour, conv.tm_min, conv.tm_sec);
-	return ret;
-}
-
+		CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "[time conversion error]"), return NULL);
+		return *buf;
+	}
+	
+	CHECK_MALLOC_DO( fd_dump_extend(FD_DUMP_STD_PARAMS, "%d%02d%02dT%02d%02d%02d+00", conv.tm_year+1900, conv.tm_mon+1, conv.tm_mday, conv.tm_hour, conv.tm_min, conv.tm_sec), return NULL);
+	return *buf;
+}
+
Index: libfdproto/fdproto-internal.h
===================================================================
--- libfdproto/fdproto-internal.h	(revision 1052)
+++ libfdproto/fdproto-internal.h	(revision 1085)
@@ -51,8 +51,4 @@
 extern FILE * fd_g_debug_fstr;
 
-/* Special message dump function */
-void fd_msg_dump_fstr_one ( struct msg * msg, FILE * fstr );
-void fd_msg_dump_fstr ( struct msg * msg, FILE * fstr );
-
 /* Iterator on the rules of a parent object */
 int fd_dict_iterate_rules ( struct dict_object *parent, void * data, int (*cb)(void *, struct dict_rule_data *) );
@@ -60,5 +56,5 @@
 /* Dispatch / messages / dictionary API */
 int fd_dict_disp_cb(enum dict_object_type type, struct dict_object *obj, struct fd_list ** cb_list);
-int fd_dict_dump_avp_value(union avp_value *avp_value, struct dict_object * model, int indent, char **outstr, size_t *offset, size_t *outlen, int header);
+DECLARE_FD_DUMP_PROTOTYPE(fd_dict_dump_avp_value, union avp_value *avp_value, struct dict_object * model, int indent, int header);
 int fd_disp_call_cb_int( struct fd_list * cb_list, struct msg ** msg, struct avp *avp, struct session *sess, enum disp_action *action, 
 			struct dict_object * obj_app, struct dict_object * obj_cmd, struct dict_object * obj_avp, struct dict_object * obj_enu);
@@ -69,39 +65,3 @@
 
 
-/* For dump routines into string buffers */
-#include <stdarg.h>
-static __inline__ int dump_init_str(char **outstr, size_t *offset, size_t *outlen) 
-{
-	*outlen = 1<<12;
-	CHECK_MALLOC( *outstr = malloc(*outlen) );
-	*offset = 0;
-	(*outstr)[0] = 0;
-	return 0;
-}
-static __inline__ int dump_add_str(char **outstr, size_t *offset, size_t *outlen, char * fmt, ...) 
-{
-	va_list argp;
-	int len;
-	va_start(argp, fmt);
-	len = vsnprintf(*outstr + *offset, *outlen - *offset, fmt, argp);
-	va_end(argp);
-	if ((len + *offset) >= *outlen) {
-		char * newstr;
-		/* buffer was too short, extend */
-		size_t newsize = ((len + *offset) + (1<<12)) & ~((1<<12) - 1); /* next multiple of 4k */
-		CHECK_MALLOC( newstr = realloc(*outstr, newsize) );
-		
-		/* redo */
-		*outstr = newstr;
-		*outlen = newsize;
-		va_start(argp, fmt);
-		len = vsnprintf(*outstr + *offset, *outlen - *offset, fmt, argp);
-		va_end(argp);
-	}
-	*offset += len;
-	return 0;
-}
-
-
-
 #endif /* _LIBFDPROTO_INTERNAL_H */
Index: libfdproto/fifo.c
===================================================================
--- libfdproto/fifo.c	(revision 1073)
+++ libfdproto/fifo.c	(revision 1085)
@@ -119,31 +119,27 @@
 
 /* Dump the content of a queue */
-void fd_fifo_dump(int level, char * name, struct fifo * queue, void (*dump_item)(int level, void * item))
-{
-	TRACE_ENTRY("%i %p %p %p", level, name, queue, dump_item);
-	
-	if (!TRACE_BOOL(level))
-		return;
-	
-	fd_log_debug("Dumping queue '%s' (%p):", name ?: "?", queue);
+DECLARE_FD_DUMP_PROTOTYPE(fd_fifo_dump, char * name, struct fifo * queue, fd_fifo_dump_item_cb dump_item)
+{
+	size_t o = 0;
+	if (!offset)
+		offset = &o;
+	
+	if (name) {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(@%p): ", name, queue), return NULL);	
+	} else {
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{fifo}(@%p): ", queue), return NULL);
+	}
+	
 	if (!CHECK_FIFO( queue )) {
-		fd_log_debug("  Queue invalid!");
-		if (queue)
-			fd_log_debug("  (%x != %x)", queue->eyec, FIFO_EYEC);
-		return;
+		return fd_dump_extend(FD_DUMP_STD_PARAMS, "INVALID/NULL\n");
 	}
 	
 	CHECK_POSIX_DO(  pthread_mutex_lock( &queue->mtx ), /* continue */  );
-	fd_log_debug("   %d elements in queue / %d threads waiting", queue->count, queue->thrs);
-	fd_log_debug("   %d elements max / %d threads waiting to push", queue->max, queue->thrs_push);
-	fd_log_debug("   thresholds: %d / %d (h:%d), cb: %p,%p (%p), highest: %d",
-			queue->high, queue->low, queue->highest, 
-			queue->h_cb, queue->l_cb, queue->data,
-			queue->highest_ever);
-	fd_log_debug("   stats: total:%lld in %ld.%06ld, blocking:%ld.%06ld, last:%ld.%06ld",
-			queue->total_items,
-	                (long)queue->total_time.tv_sec,(long)(queue->total_time.tv_nsec/1000), 
-			(long)queue->blocking_time.tv_sec,(long)(queue->blocking_time.tv_nsec/1000),
-			(long)queue->last_time.tv_sec,(long)(queue->last_time.tv_nsec/1000) );
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "items:%d,%d,%d threads:%d,%d stats:%lld/%ld.%06ld,%ld.%06ld,%ld.%06ld thresholds:%d,%d,%d,%p,%p,%p\n", 
+						queue->count, queue->highest_ever, queue->max,
+						queue->thrs, queue->thrs_push,
+						queue->total_items,(long)queue->total_time.tv_sec,(long)(queue->total_time.tv_nsec/1000),(long)queue->blocking_time.tv_sec,(long)(queue->blocking_time.tv_nsec/1000),(long)queue->last_time.tv_sec,(long)(queue->last_time.tv_nsec/1000),
+						queue->high, queue->low, queue->highest, queue->h_cb, queue->l_cb, queue->data), 
+			 goto error);
 	
 	if (dump_item) {
@@ -152,11 +148,15 @@
 		for (li = queue->list.next; li != &queue->list; li = li->next) {
 			struct fifo_item * fi = (struct fifo_item *)li;
-			fd_log_debug("  [%i] item %p in fifo %p, posted:%ld.%06ld", 
-				i++, fi->item.o, queue, (long)fi->posted_on.tv_sec,(long)(fi->posted_on.tv_nsec/1000));
-			(*dump_item)(level, fi->item.o);
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, " [#%i](@%p)@%ld.%06ld: ", 
+						i++, fi->item.o, (long)fi->posted_on.tv_sec,(long)(fi->posted_on.tv_nsec/1000)), 
+					 goto error);
+			CHECK_MALLOC_DO( (*dump_item)(FD_DUMP_STD_PARAMS, fi->item.o), goto error);
 		}
 	}
 	CHECK_POSIX_DO(  pthread_mutex_unlock( &queue->mtx ), /* continue */  );
-	
+	return *buf;
+error:
+	CHECK_POSIX_DO(  pthread_mutex_unlock( &queue->mtx ), /* continue */  );
+	return NULL;
 }
 
Index: libfdproto/log.c
===================================================================
--- libfdproto/log.c	(revision 1027)
+++ libfdproto/log.c	(revision 1085)
@@ -143,12 +143,14 @@
 }
 
-/* Log debug message to file. */
-void fd_log_debug_fstr( FILE * fstr, const char * format, ... )
-{
-	va_list ap;
-	
-	va_start(ap, format);
-	vfprintf(fstr, format, ap);
-	va_end(ap);
+/* Log a debug message */
+void fd_log_va ( int loglevel, const char * format, va_list args )
+{
+	(void)pthread_mutex_lock(&fd_log_lock);
+	
+	pthread_cleanup_push(fd_cleanup_mutex_silent, &fd_log_lock);
+	fd_logger(loglevel, format, args);
+	pthread_cleanup_pop(0);
+	
+	(void)pthread_mutex_unlock(&fd_log_lock);
 }
 
@@ -208,2 +210,50 @@
 	return buf;
 }
+
+
+/* Helper function for fd_*_dump. Prints the format string from 'offset' into '*buf', extends if needed. The location of buf can be updated by this function. */
+char * fd_dump_extend(char ** buf, size_t *len, size_t *offset, const char * format, ... )
+{
+	va_list ap;
+	int to_write;
+	size_t o = 0;
+	static size_t mempagesz = 0;
+	
+	if (!mempagesz) {
+		mempagesz = sysconf(_SC_PAGESIZE); /* We alloc buffer by memory pages for efficiency */
+		if (mempagesz <= 0)
+			mempagesz = 1024; /* default size if above call failed */
+	}
+	
+	/* we do not TRACE_ENTRY this one on purpose */
+	
+	CHECK_PARAMS_DO(buf && len, return NULL);
+	
+	if (*buf == NULL) {
+		CHECK_MALLOC_DO(*buf = malloc(mempagesz), return NULL);
+		*len = mempagesz;
+	}
+	
+	if (offset)
+		o = *offset;
+	
+	va_start(ap, format);
+	to_write = vsnprintf(*buf + o, *len - o, format, ap);
+	va_end(ap);
+	
+	if (to_write + o >= *len) {
+		/* There was no room in the buffer, we extend and redo */
+		size_t new_len = (((to_write + o) / mempagesz) + 1) * mempagesz;
+		CHECK_MALLOC_DO(*buf = realloc(*buf, new_len), return NULL);
+		*len = new_len;
+		
+		va_start(ap, format);
+		to_write = vsnprintf(*buf + o, *len - o, format, ap);
+		va_end(ap);
+	}
+	
+	if (offset)
+		*offset += to_write;
+	
+	return *buf;
+}
Index: libfdproto/messages.c
===================================================================
--- libfdproto/messages.c	(revision 1084)
+++ libfdproto/messages.c	(revision 1085)
@@ -711,4 +711,32 @@
 /* Debug functions: dumping */
 
+#warning "todo"
+DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_summary, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse )
+{
+	return NULL;
+}
+/* one-line dump with all the contents of the message */
+DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_full, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse )
+{
+	return NULL;
+}
+/* multi-line human-readable dump similar to wireshark output */
+DECLARE_FD_DUMP_PROTOTYPE( fd_msg_dump_treeview, msg_or_avp *obj, struct dictionary *dict, int force_parsing, int recurse )
+{
+	return NULL;
+}
+
+#ifndef OLD_CODE_TO_BE_REPLACED
+void fd_msg_dump_walk ( int level, msg_or_avp *obj )
+{
+	LOG_D("fd_msg_dump_walk %d, %p is deprecated", level, obj);
+}
+void fd_msg_dump_one ( int level, msg_or_avp * obj )
+{
+	LOG_D("fd_msg_dump_one %d, %p is deprecated", level, obj);
+}
+#else  /* OLD_CODE_TO_BE_REPLACED */
+
+
 /* indent inside an object */
 #define INOBJHDR 	"%*s   "
@@ -1076,5 +1104,5 @@
 }
 
-
+#endif /*  OLD_CODE_TO_BE_REPLACED */
 /***************************************************************************************************************/
 /* Simple meta-data management */
Index: libfdproto/sessions.c
===================================================================
--- libfdproto/sessions.c	(revision 1027)
+++ libfdproto/sessions.c	(revision 1085)
@@ -70,4 +70,5 @@
 	int		  id;	/* A unique integer to identify this handler */
 	void 		(*cleanup)(session_state *, os0_t, void *); /* The cleanup function to be called for cleaning a state */
+	session_state_dump *state_dump; /* dumper function */
 	void             *opaque; /* a value that is passed as is to the cleanup callback */
 };
@@ -273,5 +274,5 @@
 
 /* Create a new handler */
-int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state *, os0_t, void *), void * opaque )
+int fd_sess_handler_create_internal ( struct session_handler ** handler, void (*cleanup)(session_state *, os0_t, void *), session_state_dump dumper, void * opaque )
 {
 	struct session_handler *new;
@@ -290,4 +291,5 @@
 	new->eyec = SH_EYEC;
 	new->cleanup = cleanup;
+	new->state_dump = dumper;
 	new->opaque = opaque;
 	
@@ -873,47 +875,61 @@
 
 /* Dump functions */
-void fd_sess_dump(int level, struct session * session)
-{
-	struct fd_list * li;
-	char buf[30];
-	struct tm tm;
-	
-	if (!TRACE_BOOL(level))
-		return;
-	
-	fd_log_debug("\t  %*s -- Session @%p --", level, "", session);
+DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump, struct session * session, int with_states)
+{
+	size_t o = 0;
+	if (!offset)
+		offset = &o;
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{session}(@%p): ", session), return NULL);
+	
 	if (!VALIDATE_SI(session)) {
-		fd_log_debug("\t  %*s  Invalid session object", level, "");
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL\n"), return NULL);
 	} else {
-		
-		fd_log_debug("\t  %*s  sid '%s'(%zd), hash %x, msg %d, destroyed %d", level, "", session->sid, session->sidlen, session->hash, session->msg_cnt, session->is_destroyed);
-
-		strftime(buf, sizeof(buf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm ));
-		fd_log_debug("\t  %*s  timeout %s.%09ld", level, "", buf, session->timeout.tv_nsec);
-
-		CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ );
-		pthread_cleanup_push( fd_cleanup_mutex, &session->stlock );
-		for (li = session->states.next; li != &session->states; li = li->next) {
-			struct state * st = (struct state *)(li->o);
-			fd_log_debug("\t  %*s    handler %d registered data %p", level, "", st->hdl->id, st->state);
+		char timebuf[30];
+		struct tm tm;
+
+		strftime(timebuf, sizeof(timebuf), "%D,%T", localtime_r( &session->timeout.tv_sec , &tm ));
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "'%s'(%zd) h:%x m:%d d:%d to:%s.%06ld\n",
+							session->sid, session->sidlen, session->hash, session->msg_cnt, session->is_destroyed,
+							timebuf, session->timeout.tv_nsec/1000), 
+				 return NULL);
+		
+		if (with_states) {
+			struct fd_list * li;
+			CHECK_POSIX_DO( pthread_mutex_lock(&session->stlock), /* ignore */ );
+			pthread_cleanup_push( fd_cleanup_mutex, &session->stlock );
+			
+			for (li = session->states.next; li != &session->states; li = li->next) {
+				struct state * st = (struct state *)(li->o);
+				CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "  {state i:%d}(@%p): \n", st->hdl->id, st), return NULL);
+				if (st->hdl->state_dump) {
+					CHECK_MALLOC_DO( (*st->hdl->state_dump)( FD_DUMP_STD_PARAMS, st->state), 
+							fd_dump_extend( FD_DUMP_STD_PARAMS, "[dumper error]\n"));
+				} else {
+					CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "<%p>\n", st->state), return NULL);
+				}
+			}
+			
+			pthread_cleanup_pop(0);
+			CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ );
 		}
-		pthread_cleanup_pop(0);
-		CHECK_POSIX_DO( pthread_mutex_unlock(&session->stlock), /* ignore */ );
-	}
-	fd_log_debug("\t  %*s -- end of session @%p --", level, "", session);
-}
-
-void fd_sess_dump_hdl(int level, struct session_handler * handler)
-{
-	if (!TRACE_BOOL(level))
-		return;
-	
-	fd_log_debug("\t  %*s -- Handler @%p --", level, "", handler);
+	}
+	return *buf;
+}
+
+DECLARE_FD_DUMP_PROTOTYPE(fd_sess_dump_hdl, struct session_handler * handler)
+{
+	size_t o = 0;
+	if (!offset)
+		offset = &o;
+	
+	CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "{sesshdl}(@%p): ", handler), return NULL);
+	
 	if (!VALIDATE_SH(handler)) {
-		fd_log_debug("\t  %*s  Invalid session handler object", level, "");
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "INVALID/NULL\n"), return NULL);
 	} else {
-		fd_log_debug("\t  %*s  id %d, cleanup %p, opaque %p", level, "", handler->id, handler->cleanup, handler->opaque);
-	}
-	fd_log_debug("\t  %*s -- end of handler @%p --", level, "", handler);
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "i:%d cl:%p d:%p o:%p\n", handler->id, handler->cleanup, handler->state_dump, handler->opaque), return NULL);
+	}
+	return *buf;
 }	
 
Index: libfdproto/utils.c
===================================================================
--- libfdproto/utils.c	(revision 1084)
+++ libfdproto/utils.c	(revision 1085)
@@ -36,32 +36,43 @@
 #include "fdproto-internal.h"
 
-char * fd_sa_dump_node(char * buf, size_t bufsize, sSA * sa, int flags) 
+DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node, sSA * sa, int flags)
 {
 	char addrbuf[INET6_ADDRSTRLEN];
+	size_t o = 0;
+	if (!offset)
+		offset = &o;
+	
 	if (sa) {
 		int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), NULL, 0, flags);
-		if (rc)
-			snprintf(buf, bufsize, "%s", gai_strerror(rc));
-		else
-			snprintf(buf, bufsize, "%s", &addrbuf[0]);
+		if (rc) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", &addrbuf[0]), return NULL);
+		}
 	} else {
-		snprintf(buf, bufsize, "(NULL / ANY)");
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(NULL / ANY)"), return NULL);
 	}
-	return buf;
+	
+	return *buf;
 }
 
-char * fd_sa_dump_node_serv(char * buf, size_t bufsize, sSA * sa, int flags) 
+DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node_serv, sSA * sa, int flags) 
 {
 	char addrbuf[INET6_ADDRSTRLEN];
 	char servbuf[32];
+	size_t o = 0;
+	if (!offset)
+		offset = &o;
+	
 	if (sa) {
 		int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), flags);
-		if (rc)
-			snprintf(buf, bufsize, "%s", gai_strerror(rc));
-		else
-			snprintf(buf, bufsize, "%s", &addrbuf[0]);
+		if (rc) {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL);
+		} else {
+			CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", &addrbuf[0]), return NULL);
+		}
 	} else {
-		snprintf(buf, bufsize, "(NULL / ANY)");
+		CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "(NULL / ANY)"), return NULL);
 	}
-	return buf;
+	return *buf;
 }
