TXT_DB *TXT_DB_read(BIO *in, int num)
	{
	TXT_DB *ret=NULL;
	int er=1;
	int esc=0;
	long ln=0;
	int i,add,n;
	int size=BUFSIZE;
	int offset=0;
	char *p,**pp,*f;
	BUF_MEM *buf=NULL;

	if ((buf=BUF_MEM_new()) == NULL) goto err;
	if (!BUF_MEM_grow(buf,size)) goto err;

	if ((ret=(TXT_DB *)OPENSSL_malloc(sizeof(TXT_DB))) == NULL)
		goto err;
	ret->num_fields=num;
	ret->index=NULL;
	ret->qual=NULL;
	if ((ret->data=sk_new_null()) == NULL)
		goto err;
	if ((ret->index=(LHASH **)OPENSSL_malloc(sizeof(LHASH *)*num)) == NULL)
		goto err;
	if ((ret->qual=(int (**)(char **))OPENSSL_malloc(sizeof(int (**)(char **))*num)) == NULL)
		goto err;
	for (i=0; i<num; i++)
		{
		ret->index[i]=NULL;
		ret->qual[i]=NULL;
		}

	add=(num+1)*sizeof(char *);
	buf->data[size-1]='\0';
	offset=0;
	for (;;)
		{
		if (offset != 0)
			{
			size+=BUFSIZE;
			if (!BUF_MEM_grow_clean(buf,size)) goto err;
			}
		buf->data[offset]='\0';
		BIO_gets(in,&(buf->data[offset]),size-offset);
		ln++;
		if (buf->data[offset] == '\0') break;
		if ((offset == 0) && (buf->data[0] == '#')) continue;
		i=strlen(&(buf->data[offset]));
		offset+=i;
		if (buf->data[offset-1] != '\n')
			continue;
		else
			{
			buf->data[offset-1]='\0'; /* blat the '\n' */
			if (!(p=(char *)OPENSSL_malloc(add+offset))) goto err;
			offset=0;
			}
		pp=(char **)p;
		p+=add;
		n=0;
		pp[n++]=p;
		i=0;
		f=buf->data;

		esc=0;
		for (;;)
			{
			if (*f == '\0') break;
			if (*f == '\t')
				{
				if (esc)
					p--;
				else
					{	
					*(p++)='\0';
					f++;
					if (n >=  num) break;
					pp[n++]=p;
					continue;
					}
				}
			esc=(*f == '\\');
			*(p++)= *(f++);
			}
		*(p++)='\0';
		if ((n != num) || (*f != '\0'))
			{
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)	/* temporaty fix :-( */
			fprintf(stderr,"wrong number of fields on line %ld (looking for field %d, got %d, '%s' left)\n",ln,num,n,f);
#endif
			er=2;
			goto err;
			}
		pp[n]=p;
		if (!sk_push(ret->data,(char *)pp))
			{
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)	/* temporaty fix :-( */
			fprintf(stderr,"failure in sk_push\n");
#endif
			er=2;
			goto err;
			}
		}
	er=0;
err:
	BUF_MEM_free(buf);
	if (er)
		{
#if !defined(OPENSSL_NO_STDIO) && !defined(OPENSSL_SYS_WIN16)
		if (er == 1) fprintf(stderr,"OPENSSL_malloc failure\n");
#endif
		if (ret != NULL)
			{
			if (ret->data != NULL) sk_free(ret->data);
			if (ret->index != NULL) OPENSSL_free(ret->index);
			if (ret->qual != NULL) OPENSSL_free(ret->qual);
			if (ret != NULL) OPENSSL_free(ret);
			}
		return(NULL);
		}
	else
		return(ret);
	}