/*
 * lookup.c - see if a word appears in the dictionary
 *
 * Pace Willisson, 1983
 */

#include <stdio.h>
#include "ispell.h"
#include "config.h"


struct dent *treelookup();
struct dent *hashtbl;
int hashsize;

extern char hashname[];

static inited = 0;

linit ()
{
	int hashfd;
	struct hashheader hashheader;
	register int i;
	register struct dent *dp;

	if (inited)
		return(-1);

	if ((hashfd = open (hashname, 0)) < 0) {
		fprintf (stderr, "can't open %s\r\n", hashname);
		return (-1);
	}

	hashsize = read (hashfd, &hashheader, sizeof hashheader);
	if (hashsize == 0) {
		/*
		 * Empty file - create an empty dummy table.  We
		 * actually have to have one entry since the hash
		 * algorithm involves a divide by the table size
		 * (actually modulo, but zero is still unacceptable).
		 * So we create an entry with a word of all lowercase,
		 * which can't match because the comparison string has
		 * been converted to uppercase by then.
		 */
		(void) close (hashfd);
		hashsize = 1;		/* This prevents divides by zero */
		hashtbl = (struct dent *) calloc (1, sizeof (struct dent));
		if (hashtbl == NULL) {
			(void) fprintf (stderr,
			    "Couldn't allocate space for hash table\n");
			return (-1);
		}
		hashtbl[0].word = "xxxxxxxxxxx";
		hashtbl[0].next = NULL;
		hashtbl[0].keep = 0;
		hashtbl[0].used = 1;
		/* The flag bits don't matter, but calloc cleared them. */
		inited = 1;
		return 0;
	}
	else if (hashsize < 0  ||  hashheader.magic != MAGIC) {
		fprintf (stderr, "Illegal format hash table\r\n");
		return (-1);
	}
	hashstrings = (char *) malloc (hashheader.stringsize);
	hashtbl = (struct dent *) malloc (hashheader.tblsize * sizeof (struct dent));
	if (hashtbl == NULL  ||  hashstrings == NULL) {
		(void) fprintf (stderr,
		    "Couldn't allocate space for hash table\n");
		return (-1);
	}
	hashsize = hashheader.tblsize;

	(void) read (hashfd, hashstrings, hashheader.stringsize);
	(void) read (hashfd, hashtbl, hashheader.tblsize * sizeof (struct dent));
	(void) close (hashfd);

	for (i = hashsize, dp = hashtbl;  --i >= 0;  dp++) {
		dp->word = &hashstrings [ (int)(dp->word) ];
		if (dp->next == (struct dent *) -1)
			dp->next = NULL;
		else
			dp->next = &hashtbl [ (int)(dp->next) ];
	}

	inited = 1;
	return (0);
}

/* n is length of s */
struct dent *
lookup (s, n, dotree)
register char *s;
{
	int i;
	register struct dent *dp;
	register char *s1, *s2;

	dp = &hashtbl [ hash (s, n, hashsize) ];
	for (  ; dp != NULL; dp = dp->next) {
		/* quick strcmp, but only for equality */
		s1 = dp->word;
		s2 = s;
		while (*s1 == *s2++)
			if (*s1++=='\0') {
				lastdent = dp;
				return (lastdent);
			}
	}
	if (dotree) {
		i = s[n];
		s[n] = '\0';
		if ((dp = treelookup (s)) != NULL)
			lastdent = dp;
		s[n] = i;
		return dp;
	}
	else
		return NULL;
}

