|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T t
Length: 10534 (0x2926)
Types: TextFile
Names: »tree.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/ispell/tree.c«
/* -*- 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);
}