LHASH revamp. make depend.
diff --git a/crypto/conf/conf.h b/crypto/conf/conf.h
index a8ac256..06e0b55 100644
--- a/crypto/conf/conf.h
+++ b/crypto/conf/conf.h
@@ -78,7 +78,8 @@
 	char *value;
 	} CONF_VALUE;
 
-DECLARE_STACK_OF(CONF_VALUE)
+DECLARE_STACK_OF(CONF_VALUE);
+DECLARE_LHASH_OF(CONF_VALUE);
 
 struct conf_st;
 struct conf_method_st;
@@ -118,18 +119,23 @@
 #define CONF_MFLAGS_DEFAULT_SECTION	0x20
 
 int CONF_set_default_method(CONF_METHOD *meth);
-void CONF_set_nconf(CONF *conf,LHASH *hash);
-LHASH *CONF_load(LHASH *conf,const char *file,long *eline);
+void CONF_set_nconf(CONF *conf,LHASH_OF(CONF_VALUE) *hash);
+LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf,const char *file,
+				long *eline);
 #ifndef OPENSSL_NO_FP_API
-LHASH *CONF_load_fp(LHASH *conf, FILE *fp,long *eline);
+LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
+				   long *eline);
 #endif
-LHASH *CONF_load_bio(LHASH *conf, BIO *bp,long *eline);
-STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,const char *section);
-char *CONF_get_string(LHASH *conf,const char *group,const char *name);
-long CONF_get_number(LHASH *conf,const char *group,const char *name);
-void CONF_free(LHASH *conf);
-int CONF_dump_fp(LHASH *conf, FILE *out);
-int CONF_dump_bio(LHASH *conf, BIO *out);
+LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp,long *eline);
+STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf,
+				       const char *section);
+char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf,const char *group,
+		      const char *name);
+long CONF_get_number(LHASH_OF(CONF_VALUE) *conf,const char *group,
+		     const char *name);
+void CONF_free(LHASH_OF(CONF_VALUE) *conf);
+int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out);
+int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out);
 
 void OPENSSL_config(const char *config_name);
 void OPENSSL_no_config(void);
@@ -141,7 +147,7 @@
 	{
 	CONF_METHOD *meth;
 	void *meth_data;
-	LHASH *data;
+	LHASH_OF(CONF_VALUE) *data;
 	};
 
 CONF *NCONF_new(CONF_METHOD *meth);
diff --git a/crypto/conf/conf_api.c b/crypto/conf/conf_api.c
index 599ab25..2438f87 100644
--- a/crypto/conf/conf_api.c
+++ b/crypto/conf/conf_api.c
@@ -69,16 +69,14 @@
 #include <openssl/conf_api.h>
 #include "e_os.h"
 
-static void value_free_hash(CONF_VALUE *a, LHASH *conf);
-static void value_free_stack(CONF_VALUE *a,LHASH *conf);
-static IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_hash, CONF_VALUE *, LHASH *)
-static IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_stack, CONF_VALUE *, LHASH *)
-/* We don't use function pointer casting or wrapper functions - but cast each
- * callback parameter inside the callback functions. */
-/* static unsigned long hash(CONF_VALUE *v); */
-static unsigned long hash(const void *v_void);
-/* static int cmp_conf(CONF_VALUE *a,CONF_VALUE *b); */
-static int cmp_conf(const void *a_void,const void *b_void);
+static void value_free_hash_doall_arg(CONF_VALUE *a,
+				      LHASH_OF(CONF_VALUE) *conf);
+static void value_free_stack_doall_arg(CONF_VALUE *a,
+				       LHASH_OF(CONF_VALUE) *conf);
+static IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_hash, CONF_VALUE,
+				    LHASH_OF(CONF_VALUE))
+static IMPLEMENT_LHASH_DOALL_ARG_FN(value_free_stack, CONF_VALUE,
+				    LHASH_OF(CONF_VALUE))
 
 /* Up until OpenSSL 0.9.5a, this was get_section */
 CONF_VALUE *_CONF_get_section(const CONF *conf, const char *section)
@@ -88,7 +86,7 @@
 	if ((conf == NULL) || (section == NULL)) return(NULL);
 	vv.name=NULL;
 	vv.section=(char *)section;
-	v=(CONF_VALUE *)lh_retrieve(conf->data,&vv);
+	v=lh_CONF_VALUE_retrieve(conf->data,&vv);
 	return(v);
 	}
 
@@ -118,7 +116,7 @@
 		return 0;
 		}
 
-	v = (CONF_VALUE *)lh_insert(conf->data, value);
+	v = lh_CONF_VALUE_insert(conf->data, value);
 	if (v != NULL)
 		{
 		(void)sk_CONF_VALUE_delete_ptr(ts,v);
@@ -141,7 +139,7 @@
 			{
 			vv.name=(char *)name;
 			vv.section=(char *)section;
-			v=(CONF_VALUE *)lh_retrieve(conf->data,&vv);
+			v=lh_CONF_VALUE_retrieve(conf->data,&vv);
 			if (v != NULL) return(v->value);
 			if (strcmp(section,"ENV") == 0)
 				{
@@ -151,7 +149,7 @@
 			}
 		vv.section="default";
 		vv.name=(char *)name;
-		v=(CONF_VALUE *)lh_retrieve(conf->data,&vv);
+		v=lh_CONF_VALUE_retrieve(conf->data,&vv);
 		if (v != NULL)
 			return(v->value);
 		else
@@ -182,6 +180,34 @@
 	}
 #endif
 
+static unsigned long conf_value_hash(const CONF_VALUE *v)
+	{
+	return (lh_strhash(v->section)<<2)^lh_strhash(v->name);
+	}
+static IMPLEMENT_LHASH_HASH_FN(conf_value, CONF_VALUE)
+
+static int conf_value_cmp(const CONF_VALUE *a, const CONF_VALUE *b)
+	{
+	int i;
+
+	if (a->section != b->section)
+		{
+		i=strcmp(a->section,b->section);
+		if (i) return(i);
+		}
+
+	if ((a->name != NULL) && (b->name != NULL))
+		{
+		i=strcmp(a->name,b->name);
+		return(i);
+		}
+	else if (a->name == b->name)
+		return(0);
+	else
+		return((a->name == NULL)?-1:1);
+	}
+static IMPLEMENT_LHASH_COMP_FN(conf_value, CONF_VALUE)
+
 int _CONF_new_data(CONF *conf)
 	{
 	if (conf == NULL)
@@ -189,7 +215,7 @@
 		return 0;
 		}
 	if (conf->data == NULL)
-		if ((conf->data = lh_new(hash, cmp_conf)) == NULL)
+		if ((conf->data = lh_CONF_VALUE_new()) == NULL)
 			{
 			return 0;
 			}
@@ -200,28 +226,29 @@
 	{
 	if (conf == NULL || conf->data == NULL) return;
 
-	conf->data->down_load=0; /* evil thing to make sure the 'OPENSSL_free()'
-				  * works as expected */
-	lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(value_free_hash),
-			conf->data);
+	lh_CONF_VALUE_down_load(conf->data)=0; /* evil thing to make
+				  * sure the 'OPENSSL_free()' works as
+				  * expected */
+	lh_CONF_VALUE_doall_arg(conf->data, LHASH_DOALL_ARG_FN(value_free_hash),
+				LHASH_OF(CONF_VALUE), conf->data);
 
 	/* We now have only 'section' entries in the hash table.
 	 * Due to problems with */
 
-	lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(value_free_stack),
-			conf->data);
-	lh_free(conf->data);
+	lh_CONF_VALUE_doall_arg(conf->data,
+				LHASH_DOALL_ARG_FN(value_free_stack),
+				LHASH_OF(CONF_VALUE), conf->data);
+	lh_CONF_VALUE_free(conf->data);
 	}
 
-static void value_free_hash(CONF_VALUE *a, LHASH *conf)
+static void value_free_hash_doall_arg(CONF_VALUE *a, LHASH_OF(CONF_VALUE) *conf)
 	{
 	if (a->name != NULL)
-		{
-		a=(CONF_VALUE *)lh_delete(conf,a);
-		}
+		lh_CONF_VALUE_delete(conf,a);
 	}
 
-static void value_free_stack(CONF_VALUE *a, LHASH *conf)
+static void value_free_stack_doall_arg(CONF_VALUE *a,
+				       LHASH_OF(CONF_VALUE) *conf)
 	{
 	CONF_VALUE *vv;
 	STACK *sk;
@@ -242,37 +269,6 @@
 	OPENSSL_free(a);
 	}
 
-/* static unsigned long hash(CONF_VALUE *v) */
-static unsigned long hash(const void *v_void)
-	{
-	CONF_VALUE *v = (CONF_VALUE *)v_void;
-	return((lh_strhash(v->section)<<2)^lh_strhash(v->name));
-	}
-
-/* static int cmp_conf(CONF_VALUE *a, CONF_VALUE *b) */
-static int cmp_conf(const void *a_void,const  void *b_void)
-	{
-	int i;
-	CONF_VALUE *a = (CONF_VALUE *)a_void;
-	CONF_VALUE *b = (CONF_VALUE *)b_void;
-
-	if (a->section != b->section)
-		{
-		i=strcmp(a->section,b->section);
-		if (i) return(i);
-		}
-
-	if ((a->name != NULL) && (b->name != NULL))
-		{
-		i=strcmp(a->name,b->name);
-		return(i);
-		}
-	else if (a->name == b->name)
-		return(0);
-	else
-		return((a->name == NULL)?-1:1);
-	}
-
 /* Up until OpenSSL 0.9.5a, this was new_section */
 CONF_VALUE *_CONF_new_section(CONF *conf, const char *section)
 	{
@@ -292,7 +288,7 @@
 	v->name=NULL;
 	v->value=(char *)sk;
 	
-	vv=(CONF_VALUE *)lh_insert(conf->data,v);
+	vv=lh_CONF_VALUE_insert(conf->data,v);
 	assert(vv == NULL);
 	ok=1;
 err:
diff --git a/crypto/conf/conf_def.c b/crypto/conf/conf_def.c
index d8bce87..0b571b0 100644
--- a/crypto/conf/conf_def.c
+++ b/crypto/conf/conf_def.c
@@ -129,7 +129,7 @@
 	{
 	CONF *ret;
 
-	ret = (CONF *)OPENSSL_malloc(sizeof(CONF) + sizeof(unsigned short *));
+	ret = OPENSSL_malloc(sizeof(CONF) + sizeof(unsigned short *));
 	if (ret)
 		if (meth->init(ret) == 0)
 			{
@@ -145,7 +145,7 @@
 		return 0;
 
 	conf->meth = &default_method;
-	conf->meth_data = (void *)CONF_type_default;
+	conf->meth_data = CONF_type_default;
 	conf->data = NULL;
 
 	return 1;
@@ -722,7 +722,7 @@
 	return(p);
 	}
 
-static void dump_value(CONF_VALUE *a, BIO *out)
+static void dump_value_doall_arg(CONF_VALUE *a, BIO *out)
 	{
 	if (a->name)
 		BIO_printf(out, "[%s] %s=%s\n", a->section, a->name, a->value);
@@ -730,11 +730,12 @@
 		BIO_printf(out, "[[%s]]\n", a->section);
 	}
 
-static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE *, BIO *)
+static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_value, CONF_VALUE, BIO)
 
 static int def_dump(const CONF *conf, BIO *out)
 	{
-	lh_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value), out);
+	lh_CONF_VALUE_doall_arg(conf->data, LHASH_DOALL_ARG_FN(dump_value),
+				BIO, out);
 	return 1;
 	}
 
diff --git a/crypto/conf/conf_lib.c b/crypto/conf/conf_lib.c
index 2a3399d..54046de 100644
--- a/crypto/conf/conf_lib.c
+++ b/crypto/conf/conf_lib.c
@@ -69,7 +69,7 @@
 
 /* Init a 'CONF' structure from an old LHASH */
 
-void CONF_set_nconf(CONF *conf, LHASH *hash)
+void CONF_set_nconf(CONF *conf, LHASH_OF(CONF_VALUE) *hash)
 	{
 	if (default_CONF_method == NULL)
 		default_CONF_method = NCONF_default();
@@ -87,9 +87,10 @@
 	return 1;
 	}
 
-LHASH *CONF_load(LHASH *conf, const char *file, long *eline)
+LHASH_OF(CONF_VALUE) *CONF_load(LHASH_OF(CONF_VALUE) *conf, const char *file,
+				long *eline)
 	{
-	LHASH *ltmp;
+	LHASH_OF(CONF_VALUE) *ltmp;
 	BIO *in=NULL;
 
 #ifdef OPENSSL_SYS_VMS
@@ -110,10 +111,11 @@
 	}
 
 #ifndef OPENSSL_NO_FP_API
-LHASH *CONF_load_fp(LHASH *conf, FILE *fp,long *eline)
+LHASH_OF(CONF_VALUE) *CONF_load_fp(LHASH_OF(CONF_VALUE) *conf, FILE *fp,
+				   long *eline)
 	{
 	BIO *btmp;
-	LHASH *ltmp;
+	LHASH_OF(CONF_VALUE) *ltmp;
 	if(!(btmp = BIO_new_fp(fp, BIO_NOCLOSE))) {
 		CONFerr(CONF_F_CONF_LOAD_FP,ERR_R_BUF_LIB);
 		return NULL;
@@ -124,7 +126,8 @@
 	}
 #endif
 
-LHASH *CONF_load_bio(LHASH *conf, BIO *bp,long *eline)
+LHASH_OF(CONF_VALUE) *CONF_load_bio(LHASH_OF(CONF_VALUE) *conf, BIO *bp,
+				    long *eline)
 	{
 	CONF ctmp;
 	int ret;
@@ -137,7 +140,8 @@
 	return NULL;
 	}
 
-STACK_OF(CONF_VALUE) *CONF_get_section(LHASH *conf,const char *section)
+STACK_OF(CONF_VALUE) *CONF_get_section(LHASH_OF(CONF_VALUE) *conf,
+				       const char *section)
 	{
 	if (conf == NULL)
 		{
@@ -151,7 +155,8 @@
 		}
 	}
 
-char *CONF_get_string(LHASH *conf,const char *group,const char *name)
+char *CONF_get_string(LHASH_OF(CONF_VALUE) *conf,const char *group,
+		      const char *name)
 	{
 	if (conf == NULL)
 		{
@@ -165,7 +170,8 @@
 		}
 	}
 
-long CONF_get_number(LHASH *conf,const char *group,const char *name)
+long CONF_get_number(LHASH_OF(CONF_VALUE) *conf,const char *group,
+		     const char *name)
 	{
 	int status;
 	long result = 0;
@@ -189,7 +195,7 @@
 	return result;
 	}
 
-void CONF_free(LHASH *conf)
+void CONF_free(LHASH_OF(CONF_VALUE) *conf)
 	{
 	CONF ctmp;
 	CONF_set_nconf(&ctmp, conf);
@@ -197,7 +203,7 @@
 	}
 
 #ifndef OPENSSL_NO_FP_API
-int CONF_dump_fp(LHASH *conf, FILE *out)
+int CONF_dump_fp(LHASH_OF(CONF_VALUE) *conf, FILE *out)
 	{
 	BIO *btmp;
 	int ret;
@@ -212,7 +218,7 @@
 	}
 #endif
 
-int CONF_dump_bio(LHASH *conf, BIO *out)
+int CONF_dump_bio(LHASH_OF(CONF_VALUE) *conf, BIO *out)
 	{
 	CONF ctmp;
 	CONF_set_nconf(&ctmp, conf);
diff --git a/crypto/engine/eng_table.c b/crypto/engine/eng_table.c
index 1f0fff6..4f28abc 100644
--- a/crypto/engine/eng_table.c
+++ b/crypto/engine/eng_table.c
@@ -70,10 +70,12 @@
 	int uptodate;
 	} ENGINE_PILE;
 
+DECLARE_LHASH_OF(ENGINE_PILE);
+
 /* The type exposed in eng_int.h */
 struct st_engine_table
 	{
-	LHASH piles;
+	LHASH_OF(ENGINE_PILE) piles;
 	}; /* ENGINE_TABLE */
 
 
@@ -92,6 +94,7 @@
 	{
 	return table_flags;
 	}
+
 void ENGINE_set_table_flags(unsigned int flags)
 	{
 	table_flags = flags;
@@ -102,19 +105,21 @@
 	{
 	return c->nid;
 	}
+
 static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b)
 	{
 	return a->nid - b->nid;
 	}
-static IMPLEMENT_LHASH_HASH_FN(engine_pile_hash, const ENGINE_PILE *)
-static IMPLEMENT_LHASH_COMP_FN(engine_pile_cmp, const ENGINE_PILE *)
+static IMPLEMENT_LHASH_HASH_FN(engine_pile, const ENGINE_PILE)
+static IMPLEMENT_LHASH_COMP_FN(engine_pile, const ENGINE_PILE)
+
 static int int_table_check(ENGINE_TABLE **t, int create)
 	{
-	LHASH *lh;
+	LHASH_OF(ENGINE_PILE) *lh;
+
 	if(*t) return 1;
 	if(!create) return 0;
-	if((lh = lh_new(LHASH_HASH_FN(engine_pile_hash),
-			LHASH_COMP_FN(engine_pile_cmp))) == NULL)
+	if((lh = lh_ENGINE_PILE_new()) == NULL)
 		return 0;
 	*t = (ENGINE_TABLE *)lh;
 	return 1;
@@ -138,7 +143,7 @@
 	while(num_nids--)
 		{
 		tmplate.nid = *nids;
-		fnd = lh_retrieve(&(*table)->piles, &tmplate);
+		fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
 		if(!fnd)
 			{
 			fnd = OPENSSL_malloc(sizeof(ENGINE_PILE));
@@ -152,7 +157,7 @@
 				goto end;
 				}
 			fnd->funct = NULL;
-			lh_insert(&(*table)->piles, fnd);
+			lh_ENGINE_PILE_insert(&(*table)->piles, fnd);
 			}
 		/* A registration shouldn't add duplciate entries */
 		(void)sk_ENGINE_delete_ptr(fnd->sk, e);
@@ -181,7 +186,7 @@
 	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
 	return ret;
 	}
-static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e)
+static void int_unregister_cb_doall_arg(ENGINE_PILE *pile, ENGINE *e)
 	{
 	int n;
 	/* Iterate the 'c->sk' stack removing any occurance of 'e' */
@@ -196,31 +201,35 @@
 		pile->funct = NULL;
 		}
 	}
-static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb,ENGINE_PILE *,ENGINE *)
+static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb, ENGINE_PILE, ENGINE)
+
 void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)
 	{
 	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
 	if(int_table_check(table, 0))
-		lh_doall_arg(&(*table)->piles,
-			LHASH_DOALL_ARG_FN(int_unregister_cb), e);
+		lh_ENGINE_PILE_doall_arg(&(*table)->piles,
+					 LHASH_DOALL_ARG_FN(int_unregister_cb),
+					 ENGINE, e);
 	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
 	}
 
-static void int_cleanup_cb(ENGINE_PILE *p)
+static void int_cleanup_cb_doall(ENGINE_PILE *p)
 	{
 	sk_ENGINE_free(p->sk);
 	if(p->funct)
 		engine_unlocked_finish(p->funct, 0);
 	OPENSSL_free(p);
 	}
-static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb,ENGINE_PILE *)
+static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb, ENGINE_PILE)
+
 void engine_table_cleanup(ENGINE_TABLE **table)
 	{
 	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
 	if(*table)
 		{
-		lh_doall(&(*table)->piles, LHASH_DOALL_FN(int_cleanup_cb));
-		lh_free(&(*table)->piles);
+		lh_ENGINE_PILE_doall(&(*table)->piles,
+				     LHASH_DOALL_FN(int_cleanup_cb));
+		lh_ENGINE_PILE_free(&(*table)->piles);
 		*table = NULL;
 		}
 	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
@@ -250,7 +259,7 @@
 	 * operations. But don't worry about a fprintf(stderr). */
 	if(!int_table_check(table, 0)) goto end;
 	tmplate.nid = nid;
-	fnd = lh_retrieve(&(*table)->piles, &tmplate);
+	fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
 	if(!fnd) goto end;
 	if(fnd->funct && engine_unlocked_init(fnd->funct))
 		{
@@ -324,18 +333,18 @@
 
 /* Table enumeration */
 
-static void int_doall_cb(ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall)
+static void int_cb_doall_arg(ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall)
 	{
 	dall->cb(pile->nid, pile->sk, pile->funct, dall->arg);
 	}
+static IMPLEMENT_LHASH_DOALL_ARG_FN(int_cb, ENGINE_PILE,ENGINE_PILE_DOALL)
 
-static IMPLEMENT_LHASH_DOALL_ARG_FN(int_doall_cb,ENGINE_PILE *,ENGINE_PILE_DOALL *)
 void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb,
 								void *arg)
 	{
 	ENGINE_PILE_DOALL dall;
 	dall.cb = cb;
 	dall.arg = arg;
-	lh_doall_arg(&table->piles,
-			LHASH_DOALL_ARG_FN(int_doall_cb), &dall);
+	lh_ENGINE_PILE_doall_arg(&table->piles, LHASH_DOALL_ARG_FN(int_cb),
+				 ENGINE_PILE_DOALL, &dall);
 	}
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 8adcd9f..66d4da8 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -119,6 +119,9 @@
 #include <openssl/bio.h>
 #include <openssl/err.h>
 
+DECLARE_LHASH_OF(ERR_STRING_DATA);
+DECLARE_LHASH_OF(ERR_STATE);
+
 static void err_load_strings(int lib, ERR_STRING_DATA *str);
 
 static void ERR_STATE_free(ERR_STATE *s);
@@ -223,14 +226,14 @@
 struct st_ERR_FNS
 	{
 	/* Works on the "error_hash" string table */
-	LHASH *(*cb_err_get)(int create);
+	LHASH_OF(ERR_STRING_DATA) *(*cb_err_get)(int create);
 	void (*cb_err_del)(void);
 	ERR_STRING_DATA *(*cb_err_get_item)(const ERR_STRING_DATA *);
 	ERR_STRING_DATA *(*cb_err_set_item)(ERR_STRING_DATA *);
 	ERR_STRING_DATA *(*cb_err_del_item)(ERR_STRING_DATA *);
 	/* Works on the "thread_hash" error-state table */
-	LHASH *(*cb_thread_get)(int create);
-	void (*cb_thread_release)(LHASH **hash);
+	LHASH_OF(ERR_STATE) *(*cb_thread_get)(int create);
+	void (*cb_thread_release)(LHASH_OF(ERR_STATE) **hash);
 	ERR_STATE *(*cb_thread_get_item)(const ERR_STATE *);
 	ERR_STATE *(*cb_thread_set_item)(ERR_STATE *);
 	void (*cb_thread_del_item)(const ERR_STATE *);
@@ -239,13 +242,13 @@
 	};
 
 /* Predeclarations of the "err_defaults" functions */
-static LHASH *int_err_get(int create);
+static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create);
 static void int_err_del(void);
 static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
 static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *);
 static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *);
-static LHASH *int_thread_get(int create);
-static void int_thread_release(LHASH **hash);
+static LHASH_OF(ERR_STATE) *int_thread_get(int create);
+static void int_thread_release(LHASH_OF(ERR_STATE) **hash);
 static ERR_STATE *int_thread_get_item(const ERR_STATE *);
 static ERR_STATE *int_thread_set_item(ERR_STATE *);
 static void int_thread_del_item(const ERR_STATE *);
@@ -277,8 +280,8 @@
  * "err_defaults" functions. This way, a linked module can completely defer all
  * ERR state operation (together with requisite locking) to the implementations
  * and state in the loading application. */
-static LHASH *int_error_hash = NULL;
-static LHASH *int_thread_hash = NULL;
+static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
+static LHASH_OF(ERR_STATE) *int_thread_hash = NULL;
 static int int_thread_hash_references = 0;
 static int int_err_library_number= ERR_LIB_USER;
 
@@ -321,28 +324,37 @@
 /* These are the callbacks provided to "lh_new()" when creating the LHASH tables
  * internal to the "err_defaults" implementation. */
 
-/* static unsigned long err_hash(ERR_STRING_DATA *a); */
-static unsigned long err_hash(const void *a_void);
-/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b); */
-static int err_cmp(const void *a_void, const void *b_void);
-/* static unsigned long pid_hash(ERR_STATE *pid); */
-static unsigned long pid_hash(const void *pid_void);
-/* static int pid_cmp(ERR_STATE *a,ERR_STATE *pid); */
-static int pid_cmp(const void *a_void,const void *pid_void);
 static unsigned long get_error_values(int inc,int top,const char **file,int *line,
 				      const char **data,int *flags);
 
 /* The internal functions used in the "err_defaults" implementation */
 
-static LHASH *int_err_get(int create)
+static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
 	{
-	LHASH *ret = NULL;
+	unsigned long ret,l;
+
+	l=a->error;
+	ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
+	return(ret^ret%19*13);
+	}
+static IMPLEMENT_LHASH_HASH_FN(err_string_data, ERR_STRING_DATA);
+
+static int err_string_data_cmp(const ERR_STRING_DATA *a,
+			       const ERR_STRING_DATA *b)
+	{
+	return (int)(a->error - b->error);
+	}
+static IMPLEMENT_LHASH_COMP_FN(err_string_data, ERR_STRING_DATA);
+
+static LHASH_OF(ERR_STRING_DATA) *int_err_get(int create)
+	{
+	LHASH_OF(ERR_STRING_DATA) *ret = NULL;
 
 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
 	if (!int_error_hash && create)
 		{
 		CRYPTO_push_info("int_err_get (err.c)");
-		int_error_hash = lh_new(err_hash, err_cmp);
+		int_error_hash = lh_ERR_STRING_DATA_new();
 		CRYPTO_pop_info();
 		}
 	if (int_error_hash)
@@ -357,7 +369,7 @@
 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
 	if (int_error_hash)
 		{
-		lh_free(int_error_hash);
+		lh_ERR_STRING_DATA_free(int_error_hash);
 		int_error_hash = NULL;
 		}
 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
@@ -366,7 +378,7 @@
 static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
 	{
 	ERR_STRING_DATA *p;
-	LHASH *hash;
+	LHASH_OF(ERR_STRING_DATA) *hash;
 
 	err_fns_check();
 	hash = ERRFN(err_get)(0);
@@ -374,7 +386,7 @@
 		return NULL;
 
 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STRING_DATA *)lh_retrieve(hash, d);
+	p = lh_ERR_STRING_DATA_retrieve(hash, d);
 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
 
 	return p;
@@ -383,7 +395,7 @@
 static ERR_STRING_DATA *int_err_set_item(ERR_STRING_DATA *d)
 	{
 	ERR_STRING_DATA *p;
-	LHASH *hash;
+	LHASH_OF(ERR_STRING_DATA) *hash;
 
 	err_fns_check();
 	hash = ERRFN(err_get)(1);
@@ -391,7 +403,7 @@
 		return NULL;
 
 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STRING_DATA *)lh_insert(hash, d);
+	p = lh_ERR_STRING_DATA_insert(hash, d);
 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
 
 	return p;
@@ -400,7 +412,7 @@
 static ERR_STRING_DATA *int_err_del_item(ERR_STRING_DATA *d)
 	{
 	ERR_STRING_DATA *p;
-	LHASH *hash;
+	LHASH_OF(ERR_STRING_DATA) *hash;
 
 	err_fns_check();
 	hash = ERRFN(err_get)(0);
@@ -408,21 +420,33 @@
 		return NULL;
 
 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STRING_DATA *)lh_delete(hash, d);
+	p = lh_ERR_STRING_DATA_delete(hash, d);
 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
 
 	return p;
 	}
 
-static LHASH *int_thread_get(int create)
+static unsigned long err_state_hash(const ERR_STATE *a)
 	{
-	LHASH *ret = NULL;
+	return CRYPTO_THREADID_hash(&a->tid);
+	}
+static IMPLEMENT_LHASH_HASH_FN(err_state, ERR_STATE);
+
+static int err_state_cmp(const ERR_STATE *a, const ERR_STATE *b)
+	{
+	return CRYPTO_THREADID_cmp(&a->tid, &b->tid);
+	}
+static IMPLEMENT_LHASH_COMP_FN(err_state, ERR_STATE);
+
+static LHASH_OF(ERR_STATE) *int_thread_get(int create)
+	{
+	LHASH_OF(ERR_STATE) *ret = NULL;
 
 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
 	if (!int_thread_hash && create)
 		{
 		CRYPTO_push_info("int_thread_get (err.c)");
-		int_thread_hash = lh_new(pid_hash, pid_cmp);
+		int_thread_hash = lh_ERR_STATE_new();
 		CRYPTO_pop_info();
 		}
 	if (int_thread_hash)
@@ -434,7 +458,7 @@
 	return ret;
 	}
 
-static void int_thread_release(LHASH **hash)
+static void int_thread_release(LHASH_OF(ERR_STATE) **hash)
 	{
 	int i;
 
@@ -460,7 +484,7 @@
 static ERR_STATE *int_thread_get_item(const ERR_STATE *d)
 	{
 	ERR_STATE *p;
-	LHASH *hash;
+	LHASH_OF(ERR_STATE) *hash;
 
 	err_fns_check();
 	hash = ERRFN(thread_get)(0);
@@ -468,7 +492,7 @@
 		return NULL;
 
 	CRYPTO_r_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STATE *)lh_retrieve(hash, d);
+	p = lh_ERR_STATE_retrieve(hash, d);
 	CRYPTO_r_unlock(CRYPTO_LOCK_ERR);
 
 	ERRFN(thread_release)(&hash);
@@ -478,7 +502,7 @@
 static ERR_STATE *int_thread_set_item(ERR_STATE *d)
 	{
 	ERR_STATE *p;
-	LHASH *hash;
+	LHASH_OF(ERR_STATE) *hash;
 
 	err_fns_check();
 	hash = ERRFN(thread_get)(1);
@@ -486,7 +510,7 @@
 		return NULL;
 
 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STATE *)lh_insert(hash, d);
+	p = lh_ERR_STATE_insert(hash, d);
 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
 
 	ERRFN(thread_release)(&hash);
@@ -496,7 +520,7 @@
 static void int_thread_del_item(const ERR_STATE *d)
 	{
 	ERR_STATE *p;
-	LHASH *hash;
+	LHASH_OF(ERR_STATE) *hash;
 
 	err_fns_check();
 	hash = ERRFN(thread_get)(0);
@@ -504,12 +528,12 @@
 		return;
 
 	CRYPTO_w_lock(CRYPTO_LOCK_ERR);
-	p = (ERR_STATE *)lh_delete(hash, d);
+	p = lh_ERR_STATE_delete(hash, d);
 	/* make sure we don't leak memory */
 	if (int_thread_hash_references == 1
-		&& int_thread_hash && (lh_num_items(int_thread_hash) == 0))
+	    && int_thread_hash && lh_ERR_STATE_num_items(int_thread_hash) == 0)
 		{
-		lh_free(int_thread_hash);
+		lh_ERR_STATE_free(int_thread_hash);
 		int_thread_hash = NULL;
 		}
 	CRYPTO_w_unlock(CRYPTO_LOCK_ERR);
@@ -894,19 +918,19 @@
 	return ret;
 	}
 
-LHASH *ERR_get_string_table(void)
+LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void)
 	{
 	err_fns_check();
 	return ERRFN(err_get)(0);
 	}
 
-LHASH *ERR_get_err_state_table(void)
+LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void)
 	{
 	err_fns_check();
 	return ERRFN(thread_get)(0);
 	}
 
-void ERR_release_err_state_table(LHASH **hash)
+void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash)
 	{
 	err_fns_check();
 	ERRFN(thread_release)(hash);
@@ -955,36 +979,6 @@
 	return((p == NULL)?NULL:p->string);
 	}
 
-/* static unsigned long err_hash(ERR_STRING_DATA *a) */
-static unsigned long err_hash(const void *a_void)
-	{
-	unsigned long ret,l;
-
-	l=((const ERR_STRING_DATA *)a_void)->error;
-	ret=l^ERR_GET_LIB(l)^ERR_GET_FUNC(l);
-	return(ret^ret%19*13);
-	}
-
-/* static int err_cmp(ERR_STRING_DATA *a, ERR_STRING_DATA *b) */
-static int err_cmp(const void *a_void, const void *b_void)
-	{
-	return((int)(((const ERR_STRING_DATA *)a_void)->error -
-			((const ERR_STRING_DATA *)b_void)->error));
-	}
-
-/* static unsigned long pid_hash(ERR_STATE *a) */
-static unsigned long pid_hash(const void *a_void)
-	{
-	return CRYPTO_THREADID_hash(&((const ERR_STATE *)a_void)->tid);
-	}
-
-/* static int pid_cmp(ERR_STATE *a, ERR_STATE *b) */
-static int pid_cmp(const void *a_void, const void *b_void)
-	{
-	return CRYPTO_THREADID_cmp(&((const ERR_STATE *)a_void)->tid,
-				&((const ERR_STATE *)b_void)->tid);
-	}
-
 void ERR_remove_thread_state(CRYPTO_THREADID *tid)
 	{
 	ERR_STATE tmp;
diff --git a/crypto/err/err.h b/crypto/err/err.h
index c56f5aa..c34ce72 100644
--- a/crypto/err/err.h
+++ b/crypto/err/err.h
@@ -358,9 +358,9 @@
 ERR_STATE *ERR_get_state(void);
 
 #ifndef OPENSSL_NO_LHASH
-LHASH *ERR_get_string_table(void);
-LHASH *ERR_get_err_state_table(void);
-void ERR_release_err_state_table(LHASH **hash);
+LHASH_OF(ERR_STRING_DATA) *ERR_get_string_table(void);
+LHASH_OF(ERR_STATE) *ERR_get_err_state_table(void);
+void ERR_release_err_state_table(LHASH_OF(ERR_STATE) **hash);
 #endif
 
 int ERR_get_next_error_library(void);
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index 3b11e7a..05e5ec3 100644
--- a/crypto/ex_data.c
+++ b/crypto/ex_data.c
@@ -245,18 +245,21 @@
 static int ex_class = CRYPTO_EX_INDEX_USER;
 
 /* The global hash table of EX_CLASS_ITEM items */
-static LHASH *ex_data = NULL;
+DECLARE_LHASH_OF(EX_CLASS_ITEM);
+static LHASH_OF(EX_CLASS_ITEM) *ex_data = NULL;
 
 /* The callbacks required in the "ex_data" hash table */
-static unsigned long ex_hash_cb(const void *a_void)
+static unsigned long ex_class_item_hash(const EX_CLASS_ITEM *a)
 	{
-	return ((const EX_CLASS_ITEM *)a_void)->class_index;
+	return a->class_index;
 	}
-static int ex_cmp_cb(const void *a_void, const void *b_void)
+static IMPLEMENT_LHASH_HASH_FN(ex_class_item, EX_CLASS_ITEM);
+
+static int ex_class_item_cmp(const EX_CLASS_ITEM *a, const EX_CLASS_ITEM *b)
 	{
-	return (((const EX_CLASS_ITEM *)a_void)->class_index -
-		((const EX_CLASS_ITEM *)b_void)->class_index);
+	return a->class_index - b->class_index;
 	}
+static IMPLEMENT_LHASH_COMP_FN(ex_class_item, EX_CLASS_ITEM);
 
 /* Internal functions used by the "impl_default" implementation to access the
  * state */
@@ -265,7 +268,8 @@
 	{
 	int toret = 1;
 	CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
-	if(!ex_data && ((ex_data = lh_new(ex_hash_cb, ex_cmp_cb)) == NULL))
+	if(!ex_data
+	   && (ex_data = lh_EX_CLASS_ITEM_new()) == NULL)
 		toret = 0;
 	CRYPTO_w_unlock(CRYPTO_LOCK_EX_DATA);
 	return toret;
@@ -298,7 +302,7 @@
 	EX_DATA_CHECK(return NULL;)
 	d.class_index = class_index;
 	CRYPTO_w_lock(CRYPTO_LOCK_EX_DATA);
-	p = lh_retrieve(ex_data, &d);
+	p = lh_EX_CLASS_ITEM_retrieve(ex_data, &d);
 	if(!p)
 		{
 		gen = OPENSSL_malloc(sizeof(EX_CLASS_ITEM));
@@ -313,7 +317,7 @@
 				{
 				/* Because we're inside the ex_data lock, the
 				 * return value from the insert will be NULL */
-				lh_insert(ex_data, gen);
+				lh_EX_CLASS_ITEM_insert(ex_data, gen);
 				p = gen;
 				}
 			}
@@ -375,8 +379,8 @@
 static void int_cleanup(void)
 	{
 	EX_DATA_CHECK(return;)
-	lh_doall(ex_data, def_cleanup_cb);
-	lh_free(ex_data);
+	lh_EX_CLASS_ITEM_doall(ex_data, def_cleanup_cb);
+	lh_EX_CLASS_ITEM_free(ex_data);
 	ex_data = NULL;
 	impl = NULL;
 	}
diff --git a/crypto/lhash/lh_stats.c b/crypto/lhash/lh_stats.c
index 5aa7766..815615e 100644
--- a/crypto/lhash/lh_stats.c
+++ b/crypto/lhash/lh_stats.c
@@ -139,7 +139,7 @@
 #else
 
 #ifndef OPENSSL_NO_FP_API
-void lh_stats(const LHASH *lh, FILE *fp)
+void lh_stats(const _LHASH *lh, FILE *fp)
 	{
 	BIO *bp;
 
@@ -151,7 +151,7 @@
 end:;
 	}
 
-void lh_node_stats(const LHASH *lh, FILE *fp)
+void lh_node_stats(const _LHASH *lh, FILE *fp)
 	{
 	BIO *bp;
 
@@ -163,7 +163,7 @@
 end:;
 	}
 
-void lh_node_usage_stats(const LHASH *lh, FILE *fp)
+void lh_node_usage_stats(const _LHASH *lh, FILE *fp)
 	{
 	BIO *bp;
 
@@ -177,7 +177,7 @@
 
 #endif
 
-void lh_stats_bio(const LHASH *lh, BIO *out)
+void lh_stats_bio(const _LHASH *lh, BIO *out)
 	{
 	BIO_printf(out,"num_items             = %lu\n",lh->num_items);
 	BIO_printf(out,"num_nodes             = %u\n",lh->num_nodes);
@@ -205,7 +205,7 @@
 #endif
 	}
 
-void lh_node_stats_bio(const LHASH *lh, BIO *out)
+void lh_node_stats_bio(const _LHASH *lh, BIO *out)
 	{
 	LHASH_NODE *n;
 	unsigned int i,num;
@@ -218,7 +218,7 @@
 		}
 	}
 
-void lh_node_usage_stats_bio(const LHASH *lh, BIO *out)
+void lh_node_usage_stats_bio(const _LHASH *lh, BIO *out)
 	{
 	LHASH_NODE *n;
 	unsigned long num;
diff --git a/crypto/lhash/lhash.c b/crypto/lhash/lhash.c
index 34a54f5..47f7480 100644
--- a/crypto/lhash/lhash.c
+++ b/crypto/lhash/lhash.c
@@ -107,18 +107,18 @@
 #define UP_LOAD		(2*LH_LOAD_MULT) /* load times 256  (default 2) */
 #define DOWN_LOAD	(LH_LOAD_MULT)   /* load times 256  (default 1) */
 
-static void expand(LHASH *lh);
-static void contract(LHASH *lh);
-static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash);
+static void expand(_LHASH *lh);
+static void contract(_LHASH *lh);
+static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash);
 
-LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c)
+_LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c)
 	{
-	LHASH *ret;
+	_LHASH *ret;
 	int i;
 
-	if ((ret=(LHASH *)OPENSSL_malloc(sizeof(LHASH))) == NULL)
+	if ((ret=OPENSSL_malloc(sizeof(_LHASH))) == NULL)
 		goto err0;
-	if ((ret->b=(LHASH_NODE **)OPENSSL_malloc(sizeof(LHASH_NODE *)*MIN_NODES)) == NULL)
+	if ((ret->b=OPENSSL_malloc(sizeof(LHASH_NODE *)*MIN_NODES)) == NULL)
 		goto err1;
 	for (i=0; i<MIN_NODES; i++)
 		ret->b[i]=NULL;
@@ -154,7 +154,7 @@
 	return(NULL);
 	}
 
-void lh_free(LHASH *lh)
+void lh_free(_LHASH *lh)
 	{
 	unsigned int i;
 	LHASH_NODE *n,*nn;
@@ -176,7 +176,7 @@
 	OPENSSL_free(lh);
 	}
 
-void *lh_insert(LHASH *lh, void *data)
+void *lh_insert(_LHASH *lh, void *data)
 	{
 	unsigned long hash;
 	LHASH_NODE *nn,**rn;
@@ -214,7 +214,7 @@
 	return(ret);
 	}
 
-void *lh_delete(LHASH *lh, const void *data)
+void *lh_delete(_LHASH *lh, const void *data)
 	{
 	unsigned long hash;
 	LHASH_NODE *nn,**rn;
@@ -245,7 +245,7 @@
 	return(ret);
 	}
 
-void *lh_retrieve(LHASH *lh, const void *data)
+void *lh_retrieve(_LHASH *lh, const void *data)
 	{
 	unsigned long hash;
 	LHASH_NODE **rn;
@@ -267,7 +267,7 @@
 	return(ret);
 	}
 
-static void doall_util_fn(LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func,
+static void doall_util_fn(_LHASH *lh, int use_arg, LHASH_DOALL_FN_TYPE func,
 			  LHASH_DOALL_ARG_FN_TYPE func_arg, void *arg)
 	{
 	int i;
@@ -285,6 +285,8 @@
 			{
 			/* 28/05/91 - eay - n added so items can be deleted
 			 * via lh_doall */
+			/* 22/05/08 - ben - eh? since a is not passed,
+			 * this should not be needed */
 			n=a->next;
 			if(use_arg)
 				func_arg(a->data,arg);
@@ -295,17 +297,17 @@
 		}
 	}
 
-void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func)
+void lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func)
 	{
 	doall_util_fn(lh, 0, func, (LHASH_DOALL_ARG_FN_TYPE)0, NULL);
 	}
 
-void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg)
+void lh_doall_arg(_LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg)
 	{
 	doall_util_fn(lh, 1, (LHASH_DOALL_FN_TYPE)0, func, arg);
 	}
 
-static void expand(LHASH *lh)
+static void expand(_LHASH *lh)
 	{
 	LHASH_NODE **n,**n1,**n2,*np;
 	unsigned int p,i,j;
@@ -361,7 +363,7 @@
 		}
 	}
 
-static void contract(LHASH *lh)
+static void contract(_LHASH *lh)
 	{
 	LHASH_NODE **n,*n1,*np;
 
@@ -400,7 +402,7 @@
 		}
 	}
 
-static LHASH_NODE **getrn(LHASH *lh, const void *data, unsigned long *rhash)
+static LHASH_NODE **getrn(_LHASH *lh, const void *data, unsigned long *rhash)
 	{
 	LHASH_NODE **ret,*n1;
 	unsigned long hash,nn;
@@ -467,7 +469,7 @@
 	return((ret>>16)^ret);
 	}
 
-unsigned long lh_num_items(const LHASH *lh)
+unsigned long lh_num_items(const _LHASH *lh)
 	{
 	return lh ? lh->num_items : 0;
 	}
diff --git a/crypto/lhash/lhash.h b/crypto/lhash/lhash.h
index d392d0c..29afe00 100644
--- a/crypto/lhash/lhash.h
+++ b/crypto/lhash/lhash.h
@@ -98,42 +98,42 @@
  * macros if the functions are strictly internal. */
 
 /* First: "hash" functions */
-#define DECLARE_LHASH_HASH_FN(f_name,o_type) \
-	unsigned long f_name##_LHASH_HASH(const void *);
-#define IMPLEMENT_LHASH_HASH_FN(f_name,o_type) \
-	unsigned long f_name##_LHASH_HASH(const void *arg) { \
-		o_type a = (o_type)arg; \
-		return f_name(a); }
-#define LHASH_HASH_FN(f_name) f_name##_LHASH_HASH
+#define DECLARE_LHASH_HASH_FN(name, o_type) \
+	unsigned long name##_LHASH_HASH(const void *);
+#define IMPLEMENT_LHASH_HASH_FN(name, o_type) \
+	unsigned long name##_LHASH_HASH(const void *arg) { \
+		const o_type *a = arg; \
+		return name##_hash(a); }
+#define LHASH_HASH_FN(name) name##_LHASH_HASH
 
 /* Second: "compare" functions */
-#define DECLARE_LHASH_COMP_FN(f_name,o_type) \
-	int f_name##_LHASH_COMP(const void *, const void *);
-#define IMPLEMENT_LHASH_COMP_FN(f_name,o_type) \
-	int f_name##_LHASH_COMP(const void *arg1, const void *arg2) { \
-		o_type a = (o_type)arg1; \
-		o_type b = (o_type)arg2; \
-		return f_name(a,b); }
-#define LHASH_COMP_FN(f_name) f_name##_LHASH_COMP
+#define DECLARE_LHASH_COMP_FN(name, o_type) \
+	int name##_LHASH_COMP(const void *, const void *);
+#define IMPLEMENT_LHASH_COMP_FN(name, o_type) \
+	int name##_LHASH_COMP(const void *arg1, const void *arg2) { \
+		const o_type *a = arg1;		    \
+		const o_type *b = arg2; \
+		return name##_cmp(a,b); }
+#define LHASH_COMP_FN(name) name##_LHASH_COMP
 
 /* Third: "doall" functions */
-#define DECLARE_LHASH_DOALL_FN(f_name,o_type) \
-	void f_name##_LHASH_DOALL(void *);
-#define IMPLEMENT_LHASH_DOALL_FN(f_name,o_type) \
-	void f_name##_LHASH_DOALL(void *arg) { \
-		o_type a = (o_type)arg; \
-		f_name(a); }
-#define LHASH_DOALL_FN(f_name) f_name##_LHASH_DOALL
+#define DECLARE_LHASH_DOALL_FN(name, o_type) \
+	void name##_LHASH_DOALL(void *);
+#define IMPLEMENT_LHASH_DOALL_FN(name, o_type) \
+	void name##_LHASH_DOALL(void *arg) { \
+		o_type *a = arg; \
+		name##_doall(a); }
+#define LHASH_DOALL_FN(name) name##_LHASH_DOALL
 
 /* Fourth: "doall_arg" functions */
-#define DECLARE_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
-	void f_name##_LHASH_DOALL_ARG(void *, void *);
-#define IMPLEMENT_LHASH_DOALL_ARG_FN(f_name,o_type,a_type) \
-	void f_name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \
-		o_type a = (o_type)arg1; \
-		a_type b = (a_type)arg2; \
-		f_name(a,b); }
-#define LHASH_DOALL_ARG_FN(f_name) f_name##_LHASH_DOALL_ARG
+#define DECLARE_LHASH_DOALL_ARG_FN(name, o_type, a_type) \
+	void name##_LHASH_DOALL_ARG(void *, void *);
+#define IMPLEMENT_LHASH_DOALL_ARG_FN(name, o_type, a_type) \
+	void name##_LHASH_DOALL_ARG(void *arg1, void *arg2) { \
+		o_type *a = arg1; \
+		a_type *b = arg2; \
+		name##_doall_arg(a, b); }
+#define LHASH_DOALL_ARG_FN(name) name##_LHASH_DOALL_ARG
 
 typedef struct lhash_st
 	{
@@ -163,7 +163,8 @@
 	unsigned long num_hash_comps;
 
 	int error;
-	} LHASH;
+	} _LHASH;	/* Do not use _LHASH directly, use LHASH_OF
+			 * and friends */
 
 #define LH_LOAD_MULT	256
 
@@ -171,27 +172,84 @@
  * in lh_insert(). */
 #define lh_error(lh)	((lh)->error)
 
-LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c);
-void lh_free(LHASH *lh);
-void *lh_insert(LHASH *lh, void *data);
-void *lh_delete(LHASH *lh, const void *data);
-void *lh_retrieve(LHASH *lh, const void *data);
-void lh_doall(LHASH *lh, LHASH_DOALL_FN_TYPE func);
-void lh_doall_arg(LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg);
+_LHASH *lh_new(LHASH_HASH_FN_TYPE h, LHASH_COMP_FN_TYPE c);
+void lh_free(_LHASH *lh);
+void *lh_insert(_LHASH *lh, void *data);
+void *lh_delete(_LHASH *lh, const void *data);
+void *lh_retrieve(_LHASH *lh, const void *data);
+void lh_doall(_LHASH *lh, LHASH_DOALL_FN_TYPE func);
+void lh_doall_arg(_LHASH *lh, LHASH_DOALL_ARG_FN_TYPE func, void *arg);
 unsigned long lh_strhash(const char *c);
-unsigned long lh_num_items(const LHASH *lh);
+unsigned long lh_num_items(const _LHASH *lh);
 
 #ifndef OPENSSL_NO_FP_API
-void lh_stats(const LHASH *lh, FILE *out);
-void lh_node_stats(const LHASH *lh, FILE *out);
-void lh_node_usage_stats(const LHASH *lh, FILE *out);
+void lh_stats(const _LHASH *lh, FILE *out);
+void lh_node_stats(const _LHASH *lh, FILE *out);
+void lh_node_usage_stats(const _LHASH *lh, FILE *out);
 #endif
 
 #ifndef OPENSSL_NO_BIO
-void lh_stats_bio(const LHASH *lh, BIO *out);
-void lh_node_stats_bio(const LHASH *lh, BIO *out);
-void lh_node_usage_stats_bio(const LHASH *lh, BIO *out);
+void lh_stats_bio(const _LHASH *lh, BIO *out);
+void lh_node_stats_bio(const _LHASH *lh, BIO *out);
+void lh_node_usage_stats_bio(const _LHASH *lh, BIO *out);
 #endif
+
+// Type checking...
+
+#define LHASH_OF(type) struct lhash_st_##type
+
+#define DECLARE_LHASH_OF(type) LHASH_OF(type) { }
+
+#define CHECKED_LHASH_OF(type,lh) \
+  ((_LHASH *)CHECKED_PTR_OF(LHASH_OF(type),lh))
+
+// Define wrapper functions.
+#define LHM_lh_new(type, name) \
+  ((LHASH_OF(type) *)lh_new(LHASH_HASH_FN(name), LHASH_COMP_FN(name)))
+#define LHM_lh_error(type, lh) \
+  lh_error(CHECKED_LHASH_OF(type,lh))
+#define LHM_lh_insert(type, lh, inst) \
+  ((type *)lh_insert(CHECKED_LHASH_OF(type, lh), \
+		     CHECKED_PTR_OF(type, inst)))
+#define LHM_lh_retrieve(type, lh, inst) \
+  ((type *)lh_retrieve(CHECKED_LHASH_OF(type, lh), \
+		       CHECKED_PTR_OF(type, inst)))
+#define LHM_lh_delete(type, lh, inst) \
+  ((type *)lh_delete(CHECKED_LHASH_OF(type, lh),			\
+		     CHECKED_PTR_OF(type, inst)))
+#define LHM_lh_doall(type, lh,fn) lh_doall(CHECKED_LHASH_OF(type, lh), fn)
+#define LHM_lh_doall_arg(type, lh, fn, arg_type, arg) \
+  lh_doall_arg(CHECKED_LHASH_OF(type, lh), fn, CHECKED_PTR_OF(arg_type, arg))
+#define LHM_lh_num_items(type, lh) lh_num_items(CHECKED_LHASH_OF(type, lh))
+#define LHM_lh_down_load(type, lh) (CHECKED_LHASH_OF(type, lh)->down_load)
+#define LHM_lh_node_stats_bio(type, lh, out) \
+  lh_node_stats_bio(CHECKED_LHASH_OF(type, lh), out)
+#define LHM_lh_node_usage_stats_bio(type, lh, out) \
+  lh_node_usage_stats_bio(CHECKED_LHASH_OF(type, lh), out)
+#define LHM_lh_stats_bio(type, lh, out) \
+  lh_stats_bio(CHECKED_LHASH_OF(type, lh), out)
+#define LHM_lh_free(type, lh) lh_free(CHECKED_LHASH_OF(type, lh))
+
+
+/* Strings are special: normally an lhash entry will point to a single
+ * (somewhat) mutable object. In the case of strings:
+ *
+ * a) Instead of a single char, there is an array of chars, NUL-terminated.
+ * b) The string may have be immutable.
+ *
+ * So, they need their own declarations. Especially important for
+ * type-checking tools, such as Deputy.
+ *
+ * In practice, however, it appears to be hard to have a const
+ * string. For now, I'm settling for dealing with the fact it is a
+ * string at all.
+ */
+typedef char *STRING;
+DECLARE_LHASH_OF(STRING);
+
+typedef const char *CSTRING;
+DECLARE_LHASH_OF(CSTRING);
+
 #ifdef  __cplusplus
 }
 #endif
diff --git a/crypto/mem_dbg.c b/crypto/mem_dbg.c
index 1d94d3c..939cee1 100644
--- a/crypto/mem_dbg.c
+++ b/crypto/mem_dbg.c
@@ -134,8 +134,11 @@
  */
 
 static unsigned long order = 0; /* number of memory requests */
-static LHASH *mh=NULL; /* hash-table of memory requests (address as key);
-                        * access requires MALLOC2 lock */
+
+DECLARE_LHASH_OF(MEM);
+static LHASH_OF(MEM) *mh=NULL; /* hash-table of memory requests
+				* (address as key); access requires
+				* MALLOC2 lock */
 
 
 typedef struct app_mem_info_st
@@ -157,10 +160,13 @@
 
 static void app_info_free(APP_INFO *);
 
-static LHASH *amih=NULL; /* hash-table with those app_mem_info_st's
-                          * that are at the top of their thread's stack
-                          * (with `thread' as key);
-                          * access requires MALLOC2 lock */
+DECLARE_LHASH_OF(APP_INFO);
+static LHASH_OF(APP_INFO) *amih=NULL; /* hash-table with those
+				       * app_mem_info_st's that are at
+				       * the top of their thread's
+				       * stack (with `thread' as key);
+				       * access requires MALLOC2
+				       * lock */
 
 typedef struct mem_st
 /* memory-block description */
@@ -306,31 +312,30 @@
 	return options;
 	}
 
-/* static int mem_cmp(MEM *a, MEM *b) */
-static int mem_cmp(const void *a_void, const void *b_void)
+static int mem_cmp(const MEM *a, const MEM *b)
 	{
 #ifdef _WIN64
-	const char *a=(const char *)((const MEM *)a_void)->addr,
-		   *b=(const char *)((const MEM *)b_void)->addr;
+	const char *a=(const char *)a->addr,
+		   *b=(const char *)b->addr;
 	if (a==b)	return 0;
 	else if (a>b)	return 1;
 	else		return -1;
 #else
-	return((const char *)((const MEM *)a_void)->addr
-		- (const char *)((const MEM *)b_void)->addr);
+	return (const char *)a->addr - (const char *)b->addr;
 #endif
 	}
+static IMPLEMENT_LHASH_COMP_FN(mem, MEM)
 
-/* static unsigned long mem_hash(MEM *a) */
-static unsigned long mem_hash(const void *a_void)
+static unsigned long mem_hash(const MEM *a)
 	{
 	unsigned long ret;
 
-	ret=(unsigned long)((const MEM *)a_void)->addr;
+	ret=(unsigned long)a->addr;
 
 	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
 	return(ret);
 	}
+static IMPLEMENT_LHASH_HASH_FN(mem, MEM)
 
 /* static int app_info_cmp(APP_INFO *a, APP_INFO *b) */
 static int app_info_cmp(const void *a_void, const void *b_void)
@@ -338,15 +343,16 @@
 	return CRYPTO_THREADID_cmp(&((const APP_INFO *)a_void)->threadid,
 				&((const APP_INFO *)b_void)->threadid);
 	}
+static IMPLEMENT_LHASH_COMP_FN(app_info, APP_INFO)
 
-/* static unsigned long app_info_hash(APP_INFO *a) */
-static unsigned long app_info_hash(const void *a_void)
+static unsigned long app_info_hash(const APP_INFO *a)
 	{
 	unsigned long ret;
-	ret = CRYPTO_THREADID_hash(&((const APP_INFO *)a_void)->threadid);
+	ret = CRYPTO_THREADID_hash(&a->threadid);
 	ret=ret*17851+(ret>>14)*7+(ret>>4)*251;
 	return(ret);
 	}
+static IMPLEMENT_LHASH_HASH_FN(app_info, APP_INFO)
 
 static APP_INFO *pop_info(void)
 	{
@@ -356,14 +362,14 @@
 	if (amih != NULL)
 		{
 		CRYPTO_THREADID_set(&tmp.threadid);
-		if ((ret=(APP_INFO *)lh_delete(amih,&tmp)) != NULL)
+		if ((ret=lh_APP_INFO_delete(amih,&tmp)) != NULL)
 			{
 			APP_INFO *next=ret->next;
 
 			if (next != NULL)
 				{
 				next->references++;
-				lh_insert(amih,(char *)next);
+				lh_APP_INFO_insert(amih,next);
 				}
 #ifdef LEVITTE_DEBUG_MEM
 			if (CRYPTO_THREADID_cmp(&ret->threadid, &tmp.threadid))
@@ -402,7 +408,7 @@
 			}
 		if (amih == NULL)
 			{
-			if ((amih=lh_new(app_info_hash, app_info_cmp)) == NULL)
+			if ((amih=lh_APP_INFO_new()) == NULL)
 				{
 				OPENSSL_free(ami);
 				ret=0;
@@ -417,7 +423,7 @@
 		ami->references=1;
 		ami->next=NULL;
 
-		if ((amim=(APP_INFO *)lh_insert(amih,(char *)ami)) != NULL)
+		if ((amim=lh_APP_INFO_insert(amih,ami)) != NULL)
 			{
 #ifdef LEVITTE_DEBUG_MEM
 			if (CRYPTO_THREADID_cmp(&ami->threadid, &amim->threadid))
@@ -496,7 +502,7 @@
 				}
 			if (mh == NULL)
 				{
-				if ((mh=lh_new(mem_hash, mem_cmp)) == NULL)
+				if ((mh=lh_MEM_new()) == NULL)
 					{
 					OPENSSL_free(addr);
 					OPENSSL_free(m);
@@ -531,13 +537,13 @@
 			CRYPTO_THREADID_set(&m->threadid);
 			m->app_info=NULL;
 			if (amih != NULL
-				&& (amim=(APP_INFO *)lh_retrieve(amih,(char *)&tmp)) != NULL)
+			    && (amim=lh_APP_INFO_retrieve(amih,&tmp)) != NULL)
 				{
 				m->app_info = amim;
 				amim->references++;
 				}
 
-			if ((mm=(MEM *)lh_insert(mh,(char *)m)) != NULL)
+			if ((mm=lh_MEM_insert(mh, m)) != NULL)
 				{
 				/* Not good, but don't sweat it */
 				if (mm->app_info != NULL)
@@ -570,7 +576,7 @@
 			MemCheck_off(); /* make sure we hold MALLOC2 lock */
 
 			m.addr=addr;
-			mp=(MEM *)lh_delete(mh,(char *)&m);
+			mp=lh_MEM_delete(mh,&m);
 			if (mp != NULL)
 				{
 #ifdef LEVITTE_DEBUG_MEM
@@ -620,7 +626,7 @@
 			MemCheck_off(); /* make sure we hold MALLOC2 lock */
 
 			m.addr=addr1;
-			mp=(MEM *)lh_delete(mh,(char *)&m);
+			mp=lh_MEM_delete(mh,&m);
 			if (mp != NULL)
 				{
 #ifdef LEVITTE_DEBUG_MEM
@@ -631,7 +637,7 @@
 #endif
 				mp->addr=addr2;
 				mp->num=num;
-				lh_insert(mh,(char *)mp);
+				lh_MEM_insert(mh,mp);
 				}
 
 			MemCheck_on(); /* release MALLOC2 lock
@@ -650,7 +656,7 @@
 	long bytes;
 	} MEM_LEAK;
 
-static void print_leak(const MEM *m, MEM_LEAK *l)
+static void print_leak_doall_arg(const MEM *m, MEM_LEAK *l)
 	{
 	char buf[1024];
 	char *bufp = buf;
@@ -739,7 +745,7 @@
 #endif
 	}
 
-static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM *, MEM_LEAK *)
+static IMPLEMENT_LHASH_DOALL_ARG_FN(print_leak, const MEM, MEM_LEAK)
 
 void CRYPTO_mem_leaks(BIO *b)
 	{
@@ -754,8 +760,8 @@
 	ml.bytes=0;
 	ml.chunks=0;
 	if (mh != NULL)
-		lh_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak),
-				(char *)&ml);
+		lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(print_leak), MEM_LEAK,
+				 &ml);
 	if (ml.chunks != 0)
 		{
 		BIO_printf(b,"%ld bytes leaked in %d chunks\n",
@@ -789,14 +795,14 @@
 
 		if (mh != NULL)
 			{
-			lh_free(mh);
+			lh_MEM_free(mh);
 			mh = NULL;
 			}
 		if (amih != NULL)
 			{
-			if (lh_num_items(amih) == 0) 
+			if (lh_APP_INFO_num_items(amih) == 0) 
 				{
-				lh_free(amih);
+				lh_APP_INFO_free(amih);
 				amih = NULL;
 				}
 			}
@@ -834,17 +840,18 @@
 /* NB: The prototypes have been typedef'd to CRYPTO_MEM_LEAK_CB inside crypto.h
  * If this code is restructured, remove the callback type if it is no longer
  * needed. -- Geoff Thorpe */
-static void cb_leak(const MEM *m, CRYPTO_MEM_LEAK_CB **cb)
+static void cb_leak_doall_arg(const MEM *m, CRYPTO_MEM_LEAK_CB *cb)
 	{
-	(**cb)(m->order,m->file,m->line,m->num,m->addr);
+	cb(m->order,m->file,m->line,m->num,m->addr);
 	}
 
-static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM *, CRYPTO_MEM_LEAK_CB **)
+static IMPLEMENT_LHASH_DOALL_ARG_FN(cb_leak, const MEM, CRYPTO_MEM_LEAK_CB)
 
 void CRYPTO_mem_leaks_cb(CRYPTO_MEM_LEAK_CB *cb)
 	{
 	if (mh == NULL) return;
 	CRYPTO_w_lock(CRYPTO_LOCK_MALLOC2);
-	lh_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), &cb);
+	lh_MEM_doall_arg(mh, LHASH_DOALL_ARG_FN(cb_leak), CRYPTO_MEM_LEAK_CB,
+			 cb);
 	CRYPTO_w_unlock(CRYPTO_LOCK_MALLOC2);
 	}
diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c
index adb5731..84380a9 100644
--- a/crypto/objects/o_names.c
+++ b/crypto/objects/o_names.c
@@ -22,7 +22,8 @@
 /* I use the ex_data stuff to manage the identifiers for the obj_name_types
  * that applications may define.  I only really use the free function field.
  */
-static LHASH *names_lh=NULL;
+DECLARE_LHASH_OF(OBJ_NAME);
+static LHASH_OF(OBJ_NAME) *names_lh=NULL;
 static int names_type_num=OBJ_NAME_TYPE_NUM;
 
 typedef struct name_funcs_st
@@ -46,11 +47,14 @@
 /* static int obj_name_cmp(OBJ_NAME *a,OBJ_NAME *b); */
 static int obj_name_cmp(const void *a_void,const void *b_void);
 
+static IMPLEMENT_LHASH_HASH_FN(obj_name, OBJ_NAME)
+static IMPLEMENT_LHASH_COMP_FN(obj_name, OBJ_NAME)
+
 int OBJ_NAME_init(void)
 	{
 	if (names_lh != NULL) return(1);
 	MemCheck_off();
-	names_lh=lh_new(obj_name_hash, obj_name_cmp);
+	names_lh=lh_OBJ_NAME_new();
 	MemCheck_on();
 	return(names_lh != NULL);
 	}
@@ -164,7 +168,7 @@
 
 	for (;;)
 	{
-		ret=(OBJ_NAME *)lh_retrieve(names_lh,&on);
+		ret=lh_OBJ_NAME_retrieve(names_lh,&on);
 		if (ret == NULL) return(NULL);
 		if ((ret->alias) && !alias)
 			{
@@ -200,7 +204,7 @@
 	onp->type=type;
 	onp->data=data;
 
-	ret=(OBJ_NAME *)lh_insert(names_lh,onp);
+	ret=lh_OBJ_NAME_insert(names_lh,onp);
 	if (ret != NULL)
 		{
 		/* free things */
@@ -217,7 +221,7 @@
 		}
 	else
 		{
-		if (lh_error(names_lh))
+		if (lh_OBJ_NAME_error(names_lh))
 			{
 			/* ERROR */
 			return(0);
@@ -235,7 +239,7 @@
 	type&= ~OBJ_NAME_ALIAS;
 	on.name=name;
 	on.type=type;
-	ret=(OBJ_NAME *)lh_delete(names_lh,&on);
+	ret=lh_OBJ_NAME_delete(names_lh,&on);
 	if (ret != NULL)
 		{
 		/* free things */
@@ -262,13 +266,13 @@
 	void *arg;
 	};
 
-static void do_all_fn(const OBJ_NAME *name,struct doall *d)
+static void do_all_fn_doall_arg(const OBJ_NAME *name,struct doall *d)
 	{
 	if(name->type == d->type)
 		d->fn(name,d->arg);
 	}
 
-static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME *, struct doall *)
+static IMPLEMENT_LHASH_DOALL_ARG_FN(do_all_fn, const OBJ_NAME, struct doall)
 
 void OBJ_NAME_do_all(int type,void (*fn)(const OBJ_NAME *,void *arg),void *arg)
 	{
@@ -278,7 +282,8 @@
 	d.fn=fn;
 	d.arg=arg;
 
-	lh_doall_arg(names_lh,LHASH_DOALL_ARG_FN(do_all_fn),&d);
+	lh_OBJ_NAME_doall_arg(names_lh, LHASH_DOALL_ARG_FN(do_all_fn),
+			      struct doall, &d);
 	}
 
 struct doall_sorted
@@ -313,7 +318,7 @@
 	int n;
 
 	d.type=type;
-	d.names=OPENSSL_malloc(lh_num_items(names_lh)*sizeof *d.names);
+	d.names=OPENSSL_malloc(lh_OBJ_NAME_num_items(names_lh)*sizeof *d.names);
 	d.n=0;
 	OBJ_NAME_do_all(type,do_all_sorted_fn,&d);
 
@@ -327,18 +332,16 @@
 
 static int free_type;
 
-static void names_lh_free(OBJ_NAME *onp)
-{
-	if(onp == NULL)
+static void names_lh_free_doall(OBJ_NAME *onp)
+	{
+	if (onp == NULL)
 		return;
 
-	if ((free_type < 0) || (free_type == onp->type))
-		{
+	if (free_type < 0 || free_type == onp->type)
 		OBJ_NAME_remove(onp->name,onp->type);
-		}
 	}
 
-static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME *)
+static IMPLEMENT_LHASH_DOALL_FN(names_lh_free, OBJ_NAME)
 
 static void name_funcs_free(NAME_FUNCS *ptr)
 	{
@@ -352,18 +355,18 @@
 	if (names_lh == NULL) return;
 
 	free_type=type;
-	down_load=names_lh->down_load;
-	names_lh->down_load=0;
+	down_load=lh_OBJ_NAME_down_load(names_lh);
+	lh_OBJ_NAME_down_load(names_lh)=0;
 
-	lh_doall(names_lh,LHASH_DOALL_FN(names_lh_free));
+	lh_OBJ_NAME_doall(names_lh,LHASH_DOALL_FN(names_lh_free));
 	if (type < 0)
 		{
-		lh_free(names_lh);
+		lh_OBJ_NAME_free(names_lh);
 		sk_NAME_FUNCS_pop_free(name_funcs_stack,name_funcs_free);
 		names_lh=NULL;
 		name_funcs_stack = NULL;
 		}
 	else
-		names_lh->down_load=down_load;
+		lh_OBJ_NAME_down_load(names_lh)=down_load;
 	}
 
diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c
index fa4496c..db88f5f 100644
--- a/crypto/objects/obj_dat.c
+++ b/crypto/objects/obj_dat.c
@@ -94,9 +94,10 @@
 	int type;
 	ASN1_OBJECT *obj;
 	} ADDED_OBJ;
+DECLARE_LHASH_OF(ADDED_OBJ);
 
 static int new_nid=NUM_NID;
-static LHASH *added=NULL;
+static LHASH_OF(ADDED_OBJ) *added=NULL;
 
 static int sn_cmp(const void *a, const void *b)
 	{
@@ -112,14 +113,12 @@
 	return(strcmp((*ap)->ln,nid_objs[*bp].ln));
 	}
 
-/* static unsigned long add_hash(ADDED_OBJ *ca) */
-static unsigned long add_hash(const void *ca_void)
+static unsigned long added_obj_hash(const ADDED_OBJ *ca)
 	{
 	const ASN1_OBJECT *a;
 	int i;
 	unsigned long ret=0;
 	unsigned char *p;
-	const ADDED_OBJ *ca = (const ADDED_OBJ *)ca_void;
 
 	a=ca->obj;
 	switch (ca->type)
@@ -147,14 +146,12 @@
 	ret|=ca->type<<30L;
 	return(ret);
 	}
+static IMPLEMENT_LHASH_HASH_FN(added_obj, ADDED_OBJ)
 
-/* static int add_cmp(ADDED_OBJ *ca, ADDED_OBJ *cb) */
-static int add_cmp(const void *ca_void, const void *cb_void)
+static int added_obj_cmp(const ADDED_OBJ *ca, const ADDED_OBJ *cb)
 	{
 	ASN1_OBJECT *a,*b;
 	int i;
-	const ADDED_OBJ *ca = (const ADDED_OBJ *)ca_void;
-	const ADDED_OBJ *cb = (const ADDED_OBJ *)cb_void;
 
 	i=ca->type-cb->type;
 	if (i) return(i);
@@ -181,15 +178,16 @@
 		return 0;
 		}
 	}
+static IMPLEMENT_LHASH_COMP_FN(added_obj, ADDED_OBJ)
 
 static int init_added(void)
 	{
 	if (added != NULL) return(1);
-	added=lh_new(add_hash,add_cmp);
+	added=lh_ADDED_OBJ_new();
 	return(added != NULL);
 	}
 
-static void cleanup1(ADDED_OBJ *a)
+static void cleanup1_doall(ADDED_OBJ *a)
 	{
 	a->obj->nid=0;
 	a->obj->flags|=ASN1_OBJECT_FLAG_DYNAMIC|
@@ -197,19 +195,19 @@
 			ASN1_OBJECT_FLAG_DYNAMIC_DATA;
 	}
 
-static void cleanup2(ADDED_OBJ *a)
+static void cleanup2_doall(ADDED_OBJ *a)
 	{ a->obj->nid++; }
 
-static void cleanup3(ADDED_OBJ *a)
+static void cleanup3_doall(ADDED_OBJ *a)
 	{
 	if (--a->obj->nid == 0)
 		ASN1_OBJECT_free(a->obj);
 	OPENSSL_free(a);
 	}
 
-static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ *)
-static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ *)
-static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ *)
+static IMPLEMENT_LHASH_DOALL_FN(cleanup1, ADDED_OBJ)
+static IMPLEMENT_LHASH_DOALL_FN(cleanup2, ADDED_OBJ)
+static IMPLEMENT_LHASH_DOALL_FN(cleanup3, ADDED_OBJ)
 
 /* The purpose of obj_cleanup_defer is to avoid EVP_cleanup() attempting
  * to use freed up OIDs. If neccessary the actual freeing up of OIDs is
@@ -232,11 +230,11 @@
 		return ;
 		}
 	if (added == NULL) return;
-	added->down_load=0;
-	lh_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */
-	lh_doall(added,LHASH_DOALL_FN(cleanup2)); /* set counters */
-	lh_doall(added,LHASH_DOALL_FN(cleanup3)); /* free objects */
-	lh_free(added);
+	lh_ADDED_OBJ_down_load(added) = 0;
+	lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup1)); /* zero counters */
+	lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup2)); /* set counters */
+	lh_ADDED_OBJ_doall(added,LHASH_DOALL_FN(cleanup3)); /* free objects */
+	lh_ADDED_OBJ_free(added);
 	added=NULL;
 	}
 
@@ -272,7 +270,7 @@
 			{
 			ao[i]->type=i;
 			ao[i]->obj=o;
-			aop=(ADDED_OBJ *)lh_insert(added,ao[i]);
+			aop=lh_ADDED_OBJ_insert(added,ao[i]);
 			/* memory leak, buit should not normally matter */
 			if (aop != NULL)
 				OPENSSL_free(aop);
@@ -312,7 +310,7 @@
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
-		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
+		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj);
 		else
@@ -344,7 +342,7 @@
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
-		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
+		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj->sn);
 		else
@@ -376,7 +374,7 @@
 		ad.type=ADDED_NID;
 		ad.obj= &ob;
 		ob.nid=n;
-		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
+		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL)
 			return(adp->obj->ln);
 		else
@@ -401,7 +399,7 @@
 		{
 		ad.type=ADDED_DATA;
 		ad.obj=(ASN1_OBJECT *)a; /* XXX: ugly but harmless */
-		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
+		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=(const unsigned int *)OBJ_bsearch((const char *)&a,(const char *)obj_objs,
@@ -636,7 +634,7 @@
 		{
 		ad.type=ADDED_LNAME;
 		ad.obj= &o;
-		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
+		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=(const unsigned int*)OBJ_bsearch((char *)&oo,(char *)ln_objs, NUM_LN,
@@ -656,7 +654,7 @@
 		{
 		ad.type=ADDED_SNAME;
 		ad.obj= &o;
-		adp=(ADDED_OBJ *)lh_retrieve(added,&ad);
+		adp=lh_ADDED_OBJ_retrieve(added,&ad);
 		if (adp != NULL) return (adp->obj->nid);
 		}
 	op=(const unsigned int *)OBJ_bsearch((char *)&oo,(char *)sn_objs,NUM_SN,
diff --git a/crypto/stack/safestack.h b/crypto/stack/safestack.h
index 926210f..d57519f 100644
--- a/crypto/stack/safestack.h
+++ b/crypto/stack/safestack.h
@@ -2118,6 +2118,240 @@
 
 #define PKCS12_decrypt_d2i_PKCS7(algor, d2i_func, free_func, pass, passlen, oct, seq) \
 	SKM_PKCS12_decrypt_d2i(PKCS7, (algor), (d2i_func), (free_func), (pass), (passlen), (oct), (seq))
+
+#define lh_ADDED_OBJ_new() LHM_lh_new(ADDED_OBJ,added_obj)
+#define lh_ADDED_OBJ_insert(lh,inst) LHM_lh_insert(ADDED_OBJ,lh,inst)
+#define lh_ADDED_OBJ_retrieve(lh,inst) LHM_lh_retrieve(ADDED_OBJ,lh,inst)
+#define lh_ADDED_OBJ_delete(lh,inst) LHM_lh_delete(ADDED_OBJ,lh,inst)
+#define lh_ADDED_OBJ_doall(lh,fn) LHM_lh_doall(ADDED_OBJ,lh,fn)
+#define lh_ADDED_OBJ_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(ADDED_OBJ,lh,fn,arg_type,arg)
+#define lh_ADDED_OBJ_error(lh) LHM_lh_error(ADDED_OBJ,lh)
+#define lh_ADDED_OBJ_num_items(lh) LHM_lh_num_items(ADDED_OBJ,lh)
+#define lh_ADDED_OBJ_down_load(lh) LHM_lh_down_load(ADDED_OBJ,lh)
+#define lh_ADDED_OBJ_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(ADDED_OBJ,lh,out)
+#define lh_ADDED_OBJ_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(ADDED_OBJ,lh,out)
+#define lh_ADDED_OBJ_stats_bio(lh,out) \
+  LHM_lh_stats_bio(ADDED_OBJ,lh,out)
+#define lh_ADDED_OBJ_free(lh) LHM_lh_free(ADDED_OBJ,lh)
+
+#define lh_APP_INFO_new() LHM_lh_new(APP_INFO,app_info)
+#define lh_APP_INFO_insert(lh,inst) LHM_lh_insert(APP_INFO,lh,inst)
+#define lh_APP_INFO_retrieve(lh,inst) LHM_lh_retrieve(APP_INFO,lh,inst)
+#define lh_APP_INFO_delete(lh,inst) LHM_lh_delete(APP_INFO,lh,inst)
+#define lh_APP_INFO_doall(lh,fn) LHM_lh_doall(APP_INFO,lh,fn)
+#define lh_APP_INFO_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(APP_INFO,lh,fn,arg_type,arg)
+#define lh_APP_INFO_error(lh) LHM_lh_error(APP_INFO,lh)
+#define lh_APP_INFO_num_items(lh) LHM_lh_num_items(APP_INFO,lh)
+#define lh_APP_INFO_down_load(lh) LHM_lh_down_load(APP_INFO,lh)
+#define lh_APP_INFO_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(APP_INFO,lh,out)
+#define lh_APP_INFO_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(APP_INFO,lh,out)
+#define lh_APP_INFO_stats_bio(lh,out) \
+  LHM_lh_stats_bio(APP_INFO,lh,out)
+#define lh_APP_INFO_free(lh) LHM_lh_free(APP_INFO,lh)
+
+#define lh_CONF_VALUE_new() LHM_lh_new(CONF_VALUE,conf_value)
+#define lh_CONF_VALUE_insert(lh,inst) LHM_lh_insert(CONF_VALUE,lh,inst)
+#define lh_CONF_VALUE_retrieve(lh,inst) LHM_lh_retrieve(CONF_VALUE,lh,inst)
+#define lh_CONF_VALUE_delete(lh,inst) LHM_lh_delete(CONF_VALUE,lh,inst)
+#define lh_CONF_VALUE_doall(lh,fn) LHM_lh_doall(CONF_VALUE,lh,fn)
+#define lh_CONF_VALUE_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(CONF_VALUE,lh,fn,arg_type,arg)
+#define lh_CONF_VALUE_error(lh) LHM_lh_error(CONF_VALUE,lh)
+#define lh_CONF_VALUE_num_items(lh) LHM_lh_num_items(CONF_VALUE,lh)
+#define lh_CONF_VALUE_down_load(lh) LHM_lh_down_load(CONF_VALUE,lh)
+#define lh_CONF_VALUE_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(CONF_VALUE,lh,out)
+#define lh_CONF_VALUE_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(CONF_VALUE,lh,out)
+#define lh_CONF_VALUE_stats_bio(lh,out) \
+  LHM_lh_stats_bio(CONF_VALUE,lh,out)
+#define lh_CONF_VALUE_free(lh) LHM_lh_free(CONF_VALUE,lh)
+
+#define lh_CSTRING_new() LHM_lh_new(CSTRING,cstring)
+#define lh_CSTRING_insert(lh,inst) LHM_lh_insert(CSTRING,lh,inst)
+#define lh_CSTRING_retrieve(lh,inst) LHM_lh_retrieve(CSTRING,lh,inst)
+#define lh_CSTRING_delete(lh,inst) LHM_lh_delete(CSTRING,lh,inst)
+#define lh_CSTRING_doall(lh,fn) LHM_lh_doall(CSTRING,lh,fn)
+#define lh_CSTRING_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(CSTRING,lh,fn,arg_type,arg)
+#define lh_CSTRING_error(lh) LHM_lh_error(CSTRING,lh)
+#define lh_CSTRING_num_items(lh) LHM_lh_num_items(CSTRING,lh)
+#define lh_CSTRING_down_load(lh) LHM_lh_down_load(CSTRING,lh)
+#define lh_CSTRING_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(CSTRING,lh,out)
+#define lh_CSTRING_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(CSTRING,lh,out)
+#define lh_CSTRING_stats_bio(lh,out) \
+  LHM_lh_stats_bio(CSTRING,lh,out)
+#define lh_CSTRING_free(lh) LHM_lh_free(CSTRING,lh)
+
+#define lh_ENGINE_PILE_new() LHM_lh_new(ENGINE_PILE,engine_pile)
+#define lh_ENGINE_PILE_insert(lh,inst) LHM_lh_insert(ENGINE_PILE,lh,inst)
+#define lh_ENGINE_PILE_retrieve(lh,inst) LHM_lh_retrieve(ENGINE_PILE,lh,inst)
+#define lh_ENGINE_PILE_delete(lh,inst) LHM_lh_delete(ENGINE_PILE,lh,inst)
+#define lh_ENGINE_PILE_doall(lh,fn) LHM_lh_doall(ENGINE_PILE,lh,fn)
+#define lh_ENGINE_PILE_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(ENGINE_PILE,lh,fn,arg_type,arg)
+#define lh_ENGINE_PILE_error(lh) LHM_lh_error(ENGINE_PILE,lh)
+#define lh_ENGINE_PILE_num_items(lh) LHM_lh_num_items(ENGINE_PILE,lh)
+#define lh_ENGINE_PILE_down_load(lh) LHM_lh_down_load(ENGINE_PILE,lh)
+#define lh_ENGINE_PILE_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(ENGINE_PILE,lh,out)
+#define lh_ENGINE_PILE_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(ENGINE_PILE,lh,out)
+#define lh_ENGINE_PILE_stats_bio(lh,out) \
+  LHM_lh_stats_bio(ENGINE_PILE,lh,out)
+#define lh_ENGINE_PILE_free(lh) LHM_lh_free(ENGINE_PILE,lh)
+
+#define lh_ERR_STATE_new() LHM_lh_new(ERR_STATE,err_state)
+#define lh_ERR_STATE_insert(lh,inst) LHM_lh_insert(ERR_STATE,lh,inst)
+#define lh_ERR_STATE_retrieve(lh,inst) LHM_lh_retrieve(ERR_STATE,lh,inst)
+#define lh_ERR_STATE_delete(lh,inst) LHM_lh_delete(ERR_STATE,lh,inst)
+#define lh_ERR_STATE_doall(lh,fn) LHM_lh_doall(ERR_STATE,lh,fn)
+#define lh_ERR_STATE_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(ERR_STATE,lh,fn,arg_type,arg)
+#define lh_ERR_STATE_error(lh) LHM_lh_error(ERR_STATE,lh)
+#define lh_ERR_STATE_num_items(lh) LHM_lh_num_items(ERR_STATE,lh)
+#define lh_ERR_STATE_down_load(lh) LHM_lh_down_load(ERR_STATE,lh)
+#define lh_ERR_STATE_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(ERR_STATE,lh,out)
+#define lh_ERR_STATE_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(ERR_STATE,lh,out)
+#define lh_ERR_STATE_stats_bio(lh,out) \
+  LHM_lh_stats_bio(ERR_STATE,lh,out)
+#define lh_ERR_STATE_free(lh) LHM_lh_free(ERR_STATE,lh)
+
+#define lh_ERR_STRING_DATA_new() LHM_lh_new(ERR_STRING_DATA,err_string_data)
+#define lh_ERR_STRING_DATA_insert(lh,inst) LHM_lh_insert(ERR_STRING_DATA,lh,inst)
+#define lh_ERR_STRING_DATA_retrieve(lh,inst) LHM_lh_retrieve(ERR_STRING_DATA,lh,inst)
+#define lh_ERR_STRING_DATA_delete(lh,inst) LHM_lh_delete(ERR_STRING_DATA,lh,inst)
+#define lh_ERR_STRING_DATA_doall(lh,fn) LHM_lh_doall(ERR_STRING_DATA,lh,fn)
+#define lh_ERR_STRING_DATA_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(ERR_STRING_DATA,lh,fn,arg_type,arg)
+#define lh_ERR_STRING_DATA_error(lh) LHM_lh_error(ERR_STRING_DATA,lh)
+#define lh_ERR_STRING_DATA_num_items(lh) LHM_lh_num_items(ERR_STRING_DATA,lh)
+#define lh_ERR_STRING_DATA_down_load(lh) LHM_lh_down_load(ERR_STRING_DATA,lh)
+#define lh_ERR_STRING_DATA_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(ERR_STRING_DATA,lh,out)
+#define lh_ERR_STRING_DATA_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(ERR_STRING_DATA,lh,out)
+#define lh_ERR_STRING_DATA_stats_bio(lh,out) \
+  LHM_lh_stats_bio(ERR_STRING_DATA,lh,out)
+#define lh_ERR_STRING_DATA_free(lh) LHM_lh_free(ERR_STRING_DATA,lh)
+
+#define lh_EX_CLASS_ITEM_new() LHM_lh_new(EX_CLASS_ITEM,ex_class_item)
+#define lh_EX_CLASS_ITEM_insert(lh,inst) LHM_lh_insert(EX_CLASS_ITEM,lh,inst)
+#define lh_EX_CLASS_ITEM_retrieve(lh,inst) LHM_lh_retrieve(EX_CLASS_ITEM,lh,inst)
+#define lh_EX_CLASS_ITEM_delete(lh,inst) LHM_lh_delete(EX_CLASS_ITEM,lh,inst)
+#define lh_EX_CLASS_ITEM_doall(lh,fn) LHM_lh_doall(EX_CLASS_ITEM,lh,fn)
+#define lh_EX_CLASS_ITEM_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(EX_CLASS_ITEM,lh,fn,arg_type,arg)
+#define lh_EX_CLASS_ITEM_error(lh) LHM_lh_error(EX_CLASS_ITEM,lh)
+#define lh_EX_CLASS_ITEM_num_items(lh) LHM_lh_num_items(EX_CLASS_ITEM,lh)
+#define lh_EX_CLASS_ITEM_down_load(lh) LHM_lh_down_load(EX_CLASS_ITEM,lh)
+#define lh_EX_CLASS_ITEM_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(EX_CLASS_ITEM,lh,out)
+#define lh_EX_CLASS_ITEM_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(EX_CLASS_ITEM,lh,out)
+#define lh_EX_CLASS_ITEM_stats_bio(lh,out) \
+  LHM_lh_stats_bio(EX_CLASS_ITEM,lh,out)
+#define lh_EX_CLASS_ITEM_free(lh) LHM_lh_free(EX_CLASS_ITEM,lh)
+
+#define lh_FUNCTION_new() LHM_lh_new(FUNCTION,function)
+#define lh_FUNCTION_insert(lh,inst) LHM_lh_insert(FUNCTION,lh,inst)
+#define lh_FUNCTION_retrieve(lh,inst) LHM_lh_retrieve(FUNCTION,lh,inst)
+#define lh_FUNCTION_delete(lh,inst) LHM_lh_delete(FUNCTION,lh,inst)
+#define lh_FUNCTION_doall(lh,fn) LHM_lh_doall(FUNCTION,lh,fn)
+#define lh_FUNCTION_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(FUNCTION,lh,fn,arg_type,arg)
+#define lh_FUNCTION_error(lh) LHM_lh_error(FUNCTION,lh)
+#define lh_FUNCTION_num_items(lh) LHM_lh_num_items(FUNCTION,lh)
+#define lh_FUNCTION_down_load(lh) LHM_lh_down_load(FUNCTION,lh)
+#define lh_FUNCTION_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(FUNCTION,lh,out)
+#define lh_FUNCTION_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(FUNCTION,lh,out)
+#define lh_FUNCTION_stats_bio(lh,out) \
+  LHM_lh_stats_bio(FUNCTION,lh,out)
+#define lh_FUNCTION_free(lh) LHM_lh_free(FUNCTION,lh)
+
+#define lh_MEM_new() LHM_lh_new(MEM,mem)
+#define lh_MEM_insert(lh,inst) LHM_lh_insert(MEM,lh,inst)
+#define lh_MEM_retrieve(lh,inst) LHM_lh_retrieve(MEM,lh,inst)
+#define lh_MEM_delete(lh,inst) LHM_lh_delete(MEM,lh,inst)
+#define lh_MEM_doall(lh,fn) LHM_lh_doall(MEM,lh,fn)
+#define lh_MEM_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(MEM,lh,fn,arg_type,arg)
+#define lh_MEM_error(lh) LHM_lh_error(MEM,lh)
+#define lh_MEM_num_items(lh) LHM_lh_num_items(MEM,lh)
+#define lh_MEM_down_load(lh) LHM_lh_down_load(MEM,lh)
+#define lh_MEM_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(MEM,lh,out)
+#define lh_MEM_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(MEM,lh,out)
+#define lh_MEM_stats_bio(lh,out) \
+  LHM_lh_stats_bio(MEM,lh,out)
+#define lh_MEM_free(lh) LHM_lh_free(MEM,lh)
+
+#define lh_OBJ_NAME_new() LHM_lh_new(OBJ_NAME,obj_name)
+#define lh_OBJ_NAME_insert(lh,inst) LHM_lh_insert(OBJ_NAME,lh,inst)
+#define lh_OBJ_NAME_retrieve(lh,inst) LHM_lh_retrieve(OBJ_NAME,lh,inst)
+#define lh_OBJ_NAME_delete(lh,inst) LHM_lh_delete(OBJ_NAME,lh,inst)
+#define lh_OBJ_NAME_doall(lh,fn) LHM_lh_doall(OBJ_NAME,lh,fn)
+#define lh_OBJ_NAME_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(OBJ_NAME,lh,fn,arg_type,arg)
+#define lh_OBJ_NAME_error(lh) LHM_lh_error(OBJ_NAME,lh)
+#define lh_OBJ_NAME_num_items(lh) LHM_lh_num_items(OBJ_NAME,lh)
+#define lh_OBJ_NAME_down_load(lh) LHM_lh_down_load(OBJ_NAME,lh)
+#define lh_OBJ_NAME_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(OBJ_NAME,lh,out)
+#define lh_OBJ_NAME_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(OBJ_NAME,lh,out)
+#define lh_OBJ_NAME_stats_bio(lh,out) \
+  LHM_lh_stats_bio(OBJ_NAME,lh,out)
+#define lh_OBJ_NAME_free(lh) LHM_lh_free(OBJ_NAME,lh)
+
+#define lh_SSL_SESSION_new() LHM_lh_new(SSL_SESSION,ssl_session)
+#define lh_SSL_SESSION_insert(lh,inst) LHM_lh_insert(SSL_SESSION,lh,inst)
+#define lh_SSL_SESSION_retrieve(lh,inst) LHM_lh_retrieve(SSL_SESSION,lh,inst)
+#define lh_SSL_SESSION_delete(lh,inst) LHM_lh_delete(SSL_SESSION,lh,inst)
+#define lh_SSL_SESSION_doall(lh,fn) LHM_lh_doall(SSL_SESSION,lh,fn)
+#define lh_SSL_SESSION_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(SSL_SESSION,lh,fn,arg_type,arg)
+#define lh_SSL_SESSION_error(lh) LHM_lh_error(SSL_SESSION,lh)
+#define lh_SSL_SESSION_num_items(lh) LHM_lh_num_items(SSL_SESSION,lh)
+#define lh_SSL_SESSION_down_load(lh) LHM_lh_down_load(SSL_SESSION,lh)
+#define lh_SSL_SESSION_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(SSL_SESSION,lh,out)
+#define lh_SSL_SESSION_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(SSL_SESSION,lh,out)
+#define lh_SSL_SESSION_stats_bio(lh,out) \
+  LHM_lh_stats_bio(SSL_SESSION,lh,out)
+#define lh_SSL_SESSION_free(lh) LHM_lh_free(SSL_SESSION,lh)
+
+#define lh_STRING_new() LHM_lh_new(STRING,string)
+#define lh_STRING_insert(lh,inst) LHM_lh_insert(STRING,lh,inst)
+#define lh_STRING_retrieve(lh,inst) LHM_lh_retrieve(STRING,lh,inst)
+#define lh_STRING_delete(lh,inst) LHM_lh_delete(STRING,lh,inst)
+#define lh_STRING_doall(lh,fn) LHM_lh_doall(STRING,lh,fn)
+#define lh_STRING_doall_arg(lh,fn,arg_type,arg) \
+  LHM_lh_doall_arg(STRING,lh,fn,arg_type,arg)
+#define lh_STRING_error(lh) LHM_lh_error(STRING,lh)
+#define lh_STRING_num_items(lh) LHM_lh_num_items(STRING,lh)
+#define lh_STRING_down_load(lh) LHM_lh_down_load(STRING,lh)
+#define lh_STRING_node_stats_bio(lh,out) \
+  LHM_lh_node_stats_bio(STRING,lh,out)
+#define lh_STRING_node_usage_stats_bio(lh,out) \
+  LHM_lh_node_usage_stats_bio(STRING,lh,out)
+#define lh_STRING_stats_bio(lh,out) \
+  LHM_lh_stats_bio(STRING,lh,out)
+#define lh_STRING_free(lh) LHM_lh_free(STRING,lh)
 /* End of util/mkstack.pl block, you may now edit :-) */
 
 #endif /* !defined HEADER_SAFESTACK_H */
diff --git a/crypto/txt_db/txt_db.c b/crypto/txt_db/txt_db.c
index 3ed5f72..f6df74c 100644
--- a/crypto/txt_db/txt_db.c
+++ b/crypto/txt_db/txt_db.c
@@ -90,9 +90,9 @@
 	ret->qual=NULL;
 	if ((ret->data=sk_new_null()) == NULL)
 		goto err;
-	if ((ret->index=(LHASH **)OPENSSL_malloc(sizeof(LHASH *)*num)) == NULL)
+	if ((ret->index=OPENSSL_malloc(sizeof(*ret->index)*num)) == NULL)
 		goto err;
-	if ((ret->qual=(int (**)(char **))OPENSSL_malloc(sizeof(int (**)(char **))*num)) == NULL)
+	if ((ret->qual=OPENSSL_malloc(sizeof(*(ret->qual))*num)) == NULL)
 		goto err;
 	for (i=0; i<num; i++)
 		{
@@ -192,10 +192,10 @@
 		return(ret);
 	}
 
-char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value)
+STRING *TXT_DB_get_by_index(TXT_DB *db, int idx, STRING *value)
 	{
-	char **ret;
-	LHASH *lh;
+	STRING *ret;
+	LHASH_OF(STRING) *lh;
 
 	if (idx >= db->num_fields)
 		{
@@ -208,16 +208,16 @@
 		db->error=DB_ERROR_NO_INDEX;
 		return(NULL);
 		}
-	ret=(char **)lh_retrieve(lh,value);
+	ret=lh_STRING_retrieve(lh,value);
 	db->error=DB_ERROR_OK;
 	return(ret);
 	}
 
-int TXT_DB_create_index(TXT_DB *db, int field, int (*qual)(char **),
-		LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp)
+int TXT_DB_create_index(TXT_DB *db, int field, int (*qual)(STRING *),
+			LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp)
 	{
-	LHASH *idx;
-	char **r;
+	LHASH_OF(STRING) *idx;
+	STRING *r;
 	int i,n;
 
 	if (field >= db->num_fields)
@@ -225,7 +225,8 @@
 		db->error=DB_ERROR_INDEX_OUT_OF_RANGE;
 		return(0);
 		}
-	if ((idx=lh_new(hash,cmp)) == NULL)
+	/* FIXME: we lose type checking at this point */
+	if ((idx=(LHASH_OF(STRING) *)lh_new(hash,cmp)) == NULL)
 		{
 		db->error=DB_ERROR_MALLOC;
 		return(0);
@@ -233,18 +234,18 @@
 	n=sk_num(db->data);
 	for (i=0; i<n; i++)
 		{
-		r=(char **)sk_value(db->data,i);
+		r=(STRING *)sk_value(db->data,i);
 		if ((qual != NULL) && (qual(r) == 0)) continue;
-		if ((r=lh_insert(idx,r)) != NULL)
+		if ((r=lh_STRING_insert(idx,r)) != NULL)
 			{
 			db->error=DB_ERROR_INDEX_CLASH;
 			db->arg1=sk_find(db->data,(char *)r);
 			db->arg2=i;
-			lh_free(idx);
+			lh_STRING_free(idx);
 			return(0);
 			}
 		}
-	if (db->index[field] != NULL) lh_free(db->index[field]);
+	if (db->index[field] != NULL) lh_STRING_free(db->index[field]);
 	db->index[field]=idx;
 	db->qual[field]=qual;
 	return(1);
@@ -298,10 +299,10 @@
 	return(ret);
 	}
 
-int TXT_DB_insert(TXT_DB *db, char **row)
+int TXT_DB_insert(TXT_DB *db, STRING *row)
 	{
 	int i;
-	char **r;
+	STRING *r;
 
 	for (i=0; i<db->num_fields; i++)
 		{
@@ -309,7 +310,7 @@
 			{
 			if ((db->qual[i] != NULL) &&
 				(db->qual[i](row) == 0)) continue;
-			r=(char **)lh_retrieve(db->index[i],row);
+			r=lh_STRING_retrieve(db->index[i],row);
 			if (r != NULL)
 				{
 				db->error=DB_ERROR_INDEX_CLASH;
@@ -332,7 +333,7 @@
 			{
 			if ((db->qual[i] != NULL) &&
 				(db->qual[i](row) == 0)) continue;
-			lh_insert(db->index[i],row);
+			lh_STRING_insert(db->index[i],row);
 			}
 		}
 	return(1);
@@ -351,7 +352,7 @@
 	if (db->index != NULL)
 		{
 		for (i=db->num_fields-1; i>=0; i--)
-			if (db->index[i] != NULL) lh_free(db->index[i]);
+			if (db->index[i] != NULL) lh_STRING_free(db->index[i]);
 		OPENSSL_free(db->index);
 		}
 	if (db->qual != NULL)
diff --git a/crypto/txt_db/txt_db.h b/crypto/txt_db/txt_db.h
index 307e1ba..3ef94d5 100644
--- a/crypto/txt_db/txt_db.h
+++ b/crypto/txt_db/txt_db.h
@@ -81,12 +81,12 @@
 	{
 	int num_fields;
 	STACK /* char ** */ *data;
-	LHASH **index;
-	int (**qual)(char **);
+	LHASH_OF(STRING) **index;
+	int (**qual)(STRING *);
 	long error;
 	long arg1;
 	long arg2;
-	char **arg_row;
+	STRING *arg_row;
 	} TXT_DB;
 
 #ifndef OPENSSL_NO_BIO
@@ -96,11 +96,11 @@
 TXT_DB *TXT_DB_read(char *in, int num);
 long TXT_DB_write(char *out, TXT_DB *db);
 #endif
-int TXT_DB_create_index(TXT_DB *db,int field,int (*qual)(char **),
-		LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp);
+int TXT_DB_create_index(TXT_DB *db,int field,int (*qual)(STRING *),
+			LHASH_HASH_FN_TYPE hash, LHASH_COMP_FN_TYPE cmp);
 void TXT_DB_free(TXT_DB *db);
-char **TXT_DB_get_by_index(TXT_DB *db, int idx, char **value);
-int TXT_DB_insert(TXT_DB *db,char **value);
+STRING *TXT_DB_get_by_index(TXT_DB *db, int idx, STRING *value);
+int TXT_DB_insert(TXT_DB *db, STRING *value);
 
 #ifdef  __cplusplus
 }
diff --git a/crypto/x509v3/v3_conf.c b/crypto/x509v3/v3_conf.c
index 2b86730..e654ae7 100644
--- a/crypto/x509v3/v3_conf.c
+++ b/crypto/x509v3/v3_conf.c
@@ -79,7 +79,7 @@
 /* char *name:  Name    */
 /* char *value:  Value    */
 X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name,
-	     char *value)
+				 char *value)
 	{
 	int crit;
 	int ext_type;
@@ -99,7 +99,7 @@
 /* CONF *conf:  Config file    */
 /* char *value:  Value    */
 X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
-	     char *value)
+				     char *value)
 	{
 	int crit;
 	int ext_type;
@@ -113,7 +113,7 @@
 /* CONF *conf:  Config file    */
 /* char *value:  Value    */
 static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
-	     int crit, char *value)
+				    int crit, char *value)
 	{
 	X509V3_EXT_METHOD *method;
 	X509_EXTENSION *ext;
@@ -173,7 +173,7 @@
 	}
 
 static X509_EXTENSION *do_ext_i2d(X509V3_EXT_METHOD *method, int ext_nid,
-						 int crit, void *ext_struc)
+				  int crit, void *ext_struc)
 	{
 	unsigned char *ext_der;
 	int ext_len;
@@ -258,7 +258,8 @@
 
 /* Create a generic extension: for now just handle DER type */
 static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
-	     int crit, int gen_type, X509V3_CTX *ctx)
+					    int crit, int gen_type,
+					    X509V3_CTX *ctx)
 	{
 	unsigned char *ext_der=NULL;
 	long ext_len;
@@ -322,7 +323,7 @@
 
 
 int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section,
-	     STACK_OF(X509_EXTENSION) **sk)
+			    STACK_OF(X509_EXTENSION) **sk)
 	{
 	X509_EXTENSION *ext;
 	STACK_OF(CONF_VALUE) *nval;
@@ -343,7 +344,7 @@
 /* Convenience functions to add extensions to a certificate, CRL and request */
 
 int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
-	     X509 *cert)
+			 X509 *cert)
 	{
 	STACK_OF(X509_EXTENSION) **sk = NULL;
 	if (cert)
@@ -354,7 +355,7 @@
 /* Same as above but for a CRL */
 
 int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
-	     X509_CRL *crl)
+			     X509_CRL *crl)
 	{
 	STACK_OF(X509_EXTENSION) **sk = NULL;
 	if (crl)
@@ -443,7 +444,7 @@
 	}
 
 void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
-	     X509_CRL *crl, int flags)
+		    X509_CRL *crl, int flags)
 	{
 	ctx->issuer_cert = issuer;
 	ctx->subject_cert = subj;
@@ -454,8 +455,8 @@
 
 /* Old conf compatibility functions */
 
-X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name,
-	     char *value)
+X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+				char *name, char *value)
 	{
 	CONF ctmp;
 	CONF_set_nconf(&ctmp, conf);
@@ -464,8 +465,8 @@
 
 /* LHASH *conf:  Config file    */
 /* char *value:  Value    */
-X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid,
-	     char *value)
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+				    int ext_nid, char *value)
 	{
 	CONF ctmp;
 	CONF_set_nconf(&ctmp, conf);
@@ -489,14 +490,14 @@
 NULL
 };
 
-void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash)
+void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash)
 	{
 	ctx->db_meth = &conf_lhash_method;
 	ctx->db = lhash;
 	}
 
-int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section,
-	     X509 *cert)
+int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+			char *section, X509 *cert)
 	{
 	CONF ctmp;
 	CONF_set_nconf(&ctmp, conf);
@@ -505,8 +506,8 @@
 
 /* Same as above but for a CRL */
 
-int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section,
-	     X509_CRL *crl)
+int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+			    char *section, X509_CRL *crl)
 	{
 	CONF ctmp;
 	CONF_set_nconf(&ctmp, conf);
@@ -515,8 +516,8 @@
 
 /* Add extensions to certificate request */
 
-int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section,
-	     X509_REQ *req)
+int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+			    char *section, X509_REQ *req)
 	{
 	CONF ctmp;
 	CONF_set_nconf(&ctmp, conf);
diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h
index f7e1059..462ac8f 100644
--- a/crypto/x509v3/x509v3.h
+++ b/crypto/x509v3/x509v3.h
@@ -577,18 +577,23 @@
 int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
 int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
 
-X509_EXTENSION *X509V3_EXT_conf_nid(LHASH *conf, X509V3_CTX *ctx, int ext_nid, char *value);
-X509_EXTENSION *X509V3_EXT_conf(LHASH *conf, X509V3_CTX *ctx, char *name, char *value);
-int X509V3_EXT_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509 *cert);
-int X509V3_EXT_REQ_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_REQ *req);
-int X509V3_EXT_CRL_add_conf(LHASH *conf, X509V3_CTX *ctx, char *section, X509_CRL *crl);
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+				    int ext_nid, char *value);
+X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+				char *name, char *value);
+int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+			char *section, X509 *cert);
+int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+			    char *section, X509_REQ *req);
+int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
+			    char *section, X509_CRL *crl);
 
 int X509V3_add_value_bool_nf(char *name, int asn1_bool,
-						STACK_OF(CONF_VALUE) **extlist);
+			     STACK_OF(CONF_VALUE) **extlist);
 int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool);
 int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint);
 void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf);
-void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH *lhash);
+void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash);
 #endif
 
 char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section);