DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T t

⟦2043df1b1⟧ TextFile

    Length: 10534 (0x2926)
    Types: TextFile
    Names: »tree.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/ispell/tree.c« 

TextFile

/* -*- Mode:Text -*- */

/*
 * tree.c - a hash style dictionary for user's personal words
 *
 * Pace Willisson, 1983
 * Hash support added by Geoff Kuenning, 1987
 */

#include <stdio.h>
#include <ctype.h>
#include <sys/param.h>
#include "ispell.h"
#include "config.h"

char *getenv();
struct dent *lookup();
char *upcase();

static int cantexpand = 0;	/* NZ if an expansion fails */
static struct dent *htab = NULL; /* Hash table for our stuff */
static int hsize = 0;		/* Space available in hash table */
static int hcount = 0;		/* Number of items in hash table */

/*
 * Hash table sizes.  Prime is probably a good idea, though in truth I
 * whipped the algorithm up on the spot rather than looking it up, so
 * who knows what's really best?  If we overflow the table, we just
 * use a double-and-add-1 algorithm.
 *
 * The strange pattern in the table is because this table is sometimes
 * used with huge dictionaries, and we want to get the table bigger fast.
 * 23003 just happens to be such that the original dict.191 will fill
 * the table to just under 70%.  31469 is similarly selected for dict.191
 * combined with /usr/dict/words.  The other numbers are on 10000-word
 * intervals starting at 30000.  (The table is still valid if MAXPCT
 * is changed, but the dictionary sizes will no longer fall on neat
 * boundaries).
 */
static int goodsizes[] = {
	53, 223, 907,
#if ((BIG_DICT * 100) / MAXPCT) <= 23003
	23003,				/* ~16000 words */
#endif
#if ((BIG_DICT * 100) / MAXPCT) <= 31469
	31469,				/* ~22000 words */
#endif
#if ((BIG_DICT * 100) / MAXPCT) <= 42859
	42859,				/* ~30000 words */
#endif
#if ((BIG_DICT * 100) / MAXPCT) <= 57143
	57143,				/* ~40000 words */
#endif
	71429				/* ~50000 words */
};

struct dent *treeinsert();
struct dent *tinsert();
struct dent *treelookup();

static char personaldict[MAXPATHLEN];
static FILE *dictf;
static newwords = 0;

extern char *index ();
extern struct dent *hashtbl;
extern int hashsize;

treeinit (p)
char *p;
{
	char *h;
	char *orig;
	char buf[BUFSIZ];
	struct dent *dp;

	/*
	** if p exists and begins with '/' we don't really need HOME,
	** but it's not very likely that HOME isn't set anyway.
	*/
	orig = p;
	if (p == NULL)
		p = getenv (PDICTVAR);
	if ((h = getenv ("HOME")) == NULL)
		return;

	if (p == NULL)
		sprintf(personaldict,"%s/%s",h,DEFPDICT);
	else {
		if (*p == '/')
			strcpy(personaldict,p);
		else {
			/*
			** The user gave us a relative pathname.  How we
			** interpret it depends on how it was given:
			**
			** -p switch:  as-is first, then $HOME/name
			** PDICTVAR:   $HOME/name first, then as-is
			**/
			if (orig == NULL)
				sprintf (personaldict, "%s/%s", h, p);
			else			/* -p switch */
				strcpy (personaldict, p);
		}
	}

	if ((dictf = fopen (personaldict, "r")) == NULL) {
		/* The file doesn't exist. */
		if (p != NULL) {
			/* If pathname is relative, try another place */
			if (*p != '/') {
				if (orig == NULL)
					strcpy (personaldict, p);
				else			/* -p switch */
					sprintf (personaldict, "%s/%s", h, p);
				dictf = fopen (personaldict, "r");
			}
			if (dictf == NULL) {
				(void) fprintf (stderr, "Couldn't open ");
				perror (p);
				if (*p != '/') {
					/*
					** Restore the preferred default, so
					** that output will go th the right
					** place.
					*/
					if (orig == NULL)
						sprintf (personaldict,
						  "%s/%s", h, p);
					else			/* -p switch */
						strcpy (personaldict, p);
				}
			}
		}
		/* If the name wasn't specified explicitly, we don't object */
		return;
	}

	while (fgets (buf, sizeof buf, dictf) != NULL) {
		int len = strlen (buf) - 1;

		if (buf [ len ] == '\n')
			buf [ len-- ] = '\0';
		if ((h = index (buf, '/')) != NULL)
			*h++ = '\0';
		dp = treeinsert (buf, 1);
		while (h != NULL) {
			switch (*h++) {
			case 'D':
			case 'd':
				dp->d_flag = 1;
				break;
			case 'G':
			case 'g':
				dp->g_flag = 1;
				break;
			case 'H':
			case 'h':
				dp->h_flag = 1;
				break;
			case 'J':
			case 'j':
				dp->j_flag = 1;
				break;
			case 'M':
			case 'm':
				dp->m_flag = 1;
				break;
			case 'N':
			case 'n':
				dp->n_flag = 1;
				break;
			case 'P':
			case 'p':
				dp->p_flag = 1;
				break;
			case 'R':
			case 'r':
				dp->r_flag = 1;
				break;
			case 'S':
			case 's':
				dp->s_flag = 1;
				break;
			case 'T':
			case 't':
				dp->t_flag = 1;
				break;
			case 'V':
			case 'v':
				dp->v_flag = 1;
				break;
			case 'X':
			case 'x':
				dp->x_flag = 1;
				break;
			case 'Y':
			case 'y':
				dp->y_flag = 1;
				break;
			case 'Z':
			case 'z':
				dp->z_flag = 1;
				break;
			default:
				fprintf (stderr,
				  "Illegal flag in personal dictionary - %c (word %s)\n",
				  h[-1], buf);
				break;
			}
			/* Exit loop if no more flags */
			if (*h++ != '/')
				break;
		}
	}

	fclose (dictf);

	newwords = 0;

	if (!lflag && !aflag && access (personaldict, 2) < 0)
		printf ("Warning: Cannot update personal dictionary (%s)\r\n", personaldict);
}

treeprint ()
{
	register int i;
	register struct dent *dp;
	register struct dent *cp;

	printf ("(");
	for (i = 0;  i < hsize;  i++) {
		dp = &htab[i];
		if (dp->used) {
			for (cp = dp;  cp != NULL;  cp = cp->next)
				printf ("%s ", cp->word);
		}
	}
	printf (")");
}

struct dent *
treeinsert (word, keep)
char *word;
{
	register int i;
	struct dent *dp;
	struct dent *olddp;
	struct dent *oldhtab;
	int oldhsize;
	char nword[BUFSIZ];

	strcpy (nword, word);
	upcase (nword);
	if ((dp = lookup (nword, strlen (nword), 0)) != NULL) {
		if (keep)
			dp->keep = 1;
		return dp;
	}
	/*
	 * Expand hash table when it is MAXPCT % full.
	 */
	if (!cantexpand  &&  (hcount * 100) / MAXPCT >= hsize) {
		oldhsize = hsize;
		oldhtab = htab;
		for (i = 0;  i < sizeof goodsizes / sizeof (goodsizes[0]);  i++)
			if (goodsizes[i] > hsize)
				break;
		if (i >= sizeof goodsizes / sizeof goodsizes[0])
			hsize += hsize + 1;
		else
			hsize = goodsizes[i];
		htab = (struct dent *) calloc (hsize, sizeof (struct dent));
		if (htab == NULL) {
			(void) fprintf (stderr,
			    "Ran out of space for personal dictionary\n");
			/*
			 * Try to continue anyway, since our overflow
			 * algorithm can handle an overfull (100%+) table,
			 * and the malloc very likely failed because we
			 * already have such a huge table, so small mallocs
			 * for overflow entries will still work.
			 */
			if (oldhtab == NULL)
				exit (1);	/* No old table, can't go on */
			(void) fprintf (stderr,
			    "Continuing anyway (with reduced performance).\n");
			cantexpand = 1;		/* Suppress further messages */
			hsize = oldhsize;	/* Put this back how the were */
			htab = oldhtab;		/* ... */
			newwords = 1;		/* And pretend it worked */
			return tinsert (nword, (struct dent *) NULL, keep);
		}
		/*
		 * Re-insert old entries into new table
		 */
		for (i = 0;  i < oldhsize;  i++) {
			dp = &oldhtab[i];
			if (oldhtab[i].used) {
				tinsert ((char *) NULL, dp, 0);
				dp = dp->next;
				while (dp != NULL) {
					tinsert ((char *) NULL, dp, 0);
					olddp = dp;
					dp = dp->next;
					free ((char *) olddp);
				}
			}
		}
		if (oldhtab != NULL)
			free ((char *) oldhtab);
	}
	newwords = 1;
	return tinsert (nword, (struct dent *) NULL, keep);
}

static
struct dent *
tinsert (word, proto, keep)
char *word;			/* One of word/proto must be null */
struct dent *proto;
{
	int hcode;
	register struct dent *hp; /* Next trial entry in hash table */
	struct dent *php;	/* Previous value of hp, for chaining */

	if (word == NULL)
		word = proto->word;
	hcode = hash (word, strlen (word), hsize);
	php = NULL;
	hp = &htab[hcode];
	if (hp->used) {
		while (hp != NULL) {
			if (strcmp (word, hp->word) == 0) {
				if (keep)
					hp->keep = 1;
				return hp;
			}
			php = hp;
			hp = hp->next;
		}
		hp = (struct dent *) calloc (1, sizeof (struct dent));
		if (hp == NULL) {
			(void) fprintf (stderr,
			    "Ran out of space for personal dictionary\n");
			exit (1);
		}
	}
	if (proto != NULL) {
		*hp = *proto;
		if (php != NULL)
			php->next = hp;
		hp->next = NULL;
		return &htab[hcode];
	} else {
		if (php != NULL)
			php->next = hp;
		hp->word = (char *) malloc (strlen (word) + 1);
		if (hp->word == NULL) {
			(void) fprintf (stderr,
			    "Ran out of space for personal dictionary\n");
			exit (1);
		}
		hp->used = 1;
		hp->next = NULL;
		hp->d_flag = 0;
		hp->g_flag = 0;
		hp->h_flag = 0;
		hp->j_flag = 0;
		hp->m_flag = 0;
		hp->n_flag = 0;
		hp->p_flag = 0;
		hp->r_flag = 0;
		hp->s_flag = 0;
		hp->t_flag = 0;
		hp->v_flag = 0;
		hp->x_flag = 0;
		hp->y_flag = 0;
		hp->z_flag = 0;
		strcpy (hp->word, word);
		hp->keep = keep;
		hcount++;
		return (hp);
	}
}

struct dent *
treelookup (word)
char *word;
{
	int hcode;
	register struct dent *hp;
	char nword[BUFSIZ];

	if (hsize <= 0)
		return NULL;
	strcpy (nword, word);
	hcode = hash (nword, strlen (nword), hsize);
	hp = &htab[hcode];
	while (hp != NULL  &&  hp->used) {
		if (strcmp (nword, hp->word) == 0)
			break;
		hp = hp->next;
	}
	if (hp != NULL  &&  hp->used)
		return hp;
	else
		return NULL;
}

treeoutput ()
{
	if (newwords == 0)
		return;

	if ((dictf = fopen (personaldict, "w")) == NULL) {
		fprintf (stderr, "Can't create %s\r\n", personaldict);
		return;
	}

	toutput1 ();

	fclose (dictf);
}

static
toutput1 ()
{
	register struct dent *cent;	/* Current entry */
	register struct dent *lent;	/* Linked entry */

	for (cent = htab;  cent - htab < hsize;  cent++) {
		for (lent = cent;  lent != NULL;  lent = lent->next) {
			if (lent->used  &&  lent->keep)
				toutput2 (lent);
		}
	}
	for (cent = hashtbl, lent = hashtbl + hashsize;
	    cent < lent;
	    cent++) {
		if (cent->used  &&  cent->keep)
			toutput2 (cent);
	}
}

static
toutput2 (cent)
register struct dent *cent;
{
	fprintf (dictf, "%s", cent->word);
	if (cent->d_flag)
		fprintf (dictf, "/D");
	if (cent->g_flag)
		fprintf (dictf, "/G");
	if (cent->h_flag)
		fprintf (dictf, "/H");
	if (cent->j_flag)
		fprintf (dictf, "/J");
	if (cent->m_flag)
		fprintf (dictf, "/M");
	if (cent->n_flag)
		fprintf (dictf, "/N");
	if (cent->p_flag)
		fprintf (dictf, "/P");
	if (cent->r_flag)
		fprintf (dictf, "/R");
	if (cent->s_flag)
		fprintf (dictf, "/S");
	if (cent->t_flag)
		fprintf (dictf, "/T");
	if (cent->v_flag)
		fprintf (dictf, "/V");
	if (cent->x_flag)
		fprintf (dictf, "/X");
	if (cent->y_flag)
		fprintf (dictf, "/Y");
	if (cent->z_flag)
		fprintf (dictf, "/Z");
	fprintf (dictf, "\n");
}

char *
upcase (s)
register char *s;
{
	register char *os = s;

	while (*s) {
		if (mylower (*s))
			*s = toupper (*s);
		s++;
	}
	return (os);
}