source: trunk/athena/bin/ispell/buildhash.c @ 362

Revision 362, 6.3 KB checked in by ambar, 37 years ago (diff)
Initial revision
Line 
1/*
2 * buildhash.c - make a hash table for ispell
3 *
4 * Pace Willisson, 1983
5 */
6
7#include <stdio.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <sys/param.h>
11#include "ispell.h"
12#include "config.h"
13
14#define NSTAT 100
15struct stat dstat, cstat;
16
17int numwords, hashsize;
18
19char *malloc();
20
21struct dent *hashtbl;
22
23char *Dfile;
24char *Hfile;
25
26char Cfile[MAXPATHLEN];
27char Sfile[MAXPATHLEN];
28
29main (argc,argv)
30int argc;
31char **argv;
32{
33        FILE *countf;
34        FILE *statf;
35        int stats[NSTAT];
36        int i;
37
38        if (argc > 1) {
39                ++argv;
40                Dfile = *argv;
41                if (argc > 2) {
42                        ++argv;
43                        Hfile = *argv;
44                }
45                else
46                        Hfile = DEFHASH;
47        }
48        else {
49                Dfile = DEFDICT;
50                Hfile = DEFHASH;
51        }
52
53        (void) sprintf(Cfile,"%s.cnt",Dfile);
54        (void) sprintf(Sfile,"%s.stat",Dfile);
55
56        if (stat (Dfile, &dstat) < 0) {
57                fprintf (stderr, "No dictionary (%s)\n", Dfile);
58                exit (1);
59        }
60
61        if (stat (Cfile, &cstat) < 0 || dstat.st_mtime > cstat.st_mtime)
62                newcount ();
63
64        if ((countf = fopen (Cfile, "r")) == NULL) {
65                fprintf (stderr, "No count file\n");
66                exit (1);
67        }
68        numwords = 0;
69        (void) fscanf (countf, "%d", &numwords);
70        (void) fclose (countf);
71        if (numwords == 0) {
72                fprintf (stderr, "Bad count file\n");
73                exit (1);
74        }
75        hashsize = numwords;
76        readdict ();
77
78        if ((statf = fopen (Sfile, "w")) == NULL) {
79                fprintf (stderr, "Can't create %s\n", Sfile);
80                exit (1);
81        }
82
83        for (i = 0; i < NSTAT; i++)
84                stats[i] = 0;
85        for (i = 0; i < hashsize; i++) {
86                struct dent *dp;
87                int j;
88                if (hashtbl[i].used == 0) {
89                        stats[0]++;
90                } else {
91                        for (j = 1, dp = &hashtbl[i]; dp->next != NULL; j++, dp = dp->next)
92                                ;
93                        if (j >= NSTAT)
94                                j = NSTAT - 1;
95                        stats[j]++;
96                }
97        }
98        for (i = 0; i < NSTAT; i++)
99                fprintf (statf, "%d: %d\n", i, stats[i]);
100        (void) fclose (statf);
101
102        filltable ();
103
104        output ();
105        exit(0);
106}
107
108output ()
109{
110        FILE *outfile;
111        struct hashheader hashheader;
112        int strptr, n, i;
113
114        if ((outfile = fopen (Hfile, "w")) == NULL) {
115                fprintf (stderr, "can't create %s\n",Hfile);
116                return;
117        }
118        hashheader.magic = MAGIC;
119        hashheader.stringsize = 0;
120        hashheader.tblsize = hashsize;
121        (void) fwrite (&hashheader, sizeof hashheader, 1, outfile);
122        strptr = 0;
123        for (i = 0; i < hashsize; i++) {
124                n = strlen (hashtbl[i].word) + 1;
125                (void) fwrite (hashtbl[i].word, n, 1, outfile);
126                hashtbl[i].word = (char *)strptr;
127                strptr += n;
128        }
129        for (i = 0; i < hashsize; i++) {
130                if (hashtbl[i].next != 0) {
131                        int x;
132                        x = hashtbl[i].next - hashtbl;
133                        hashtbl[i].next = (struct dent *)x;
134                } else {
135                        hashtbl[i].next = (struct dent *)-1;
136                }
137        }
138        (void) fwrite (hashtbl, sizeof (struct dent), hashsize, outfile);
139        hashheader.stringsize = strptr;
140        rewind (outfile);
141        (void) fwrite (&hashheader, sizeof hashheader, 1, outfile);
142        (void) fclose (outfile);
143}
144
145filltable ()
146{
147        struct dent *freepointer, *nextword, *dp;
148        int i;
149
150        for (freepointer = hashtbl; freepointer->used; freepointer++)
151                ;
152        for (nextword = hashtbl, i = numwords; i != 0; nextword++, i--) {
153                if (nextword->used == 0) {
154                        continue;
155                }
156                if (nextword->next == NULL) {
157                        continue;
158                }
159                if (nextword->next >= hashtbl && nextword->next < hashtbl + hashsize) {
160                        continue;
161                }
162                dp = nextword;
163                while (dp->next) {
164                        if (freepointer > hashtbl + hashsize) {
165                                fprintf (stderr, "table overflow\n");
166                                getchar ();
167                                break;
168                        }
169                        *freepointer = *(dp->next);
170                        dp->next = freepointer;
171                        dp = freepointer;
172
173                        while (freepointer->used)
174                                freepointer++;
175                }
176        }
177}
178
179
180readdict ()
181{
182        struct dent d;
183        char lbuf[100];
184        FILE *dictf;
185        int i;
186        int h;
187        char *p;
188
189        if ((dictf = fopen (Dfile, "r")) == NULL) {
190                fprintf (stderr, "Can't open dictionary\n");
191                exit (1);
192        }
193
194        hashtbl = (struct dent *) calloc (numwords, sizeof (struct dent));
195        if (hashtbl == NULL) {
196                fprintf (stderr, "couldn't allocate hash table\n");
197                exit (1);
198        }
199
200        i = 0;
201        while (fgets (lbuf, sizeof lbuf, dictf) != NULL) {
202                if ((i & 1023) == 0) {
203                        printf ("%d ", i);
204                        fflush (stdout);
205                }
206                i++;
207
208                p = &lbuf [ strlen (lbuf) - 1 ];
209                if (*p == '\n')
210                        *p = 0;
211
212                if (makedent (lbuf, &d) < 0)
213                        continue;
214
215                d.word = malloc (strlen (lbuf) + 1);
216                if (d.word == NULL) {
217                        fprintf (stderr, "couldn't allocate space for word %s\n", lbuf);
218                        exit (1);
219                }
220                (void) strcpy (d.word, lbuf);
221
222                h = hash (lbuf, strlen (lbuf), hashsize);
223
224                if (hashtbl[h].used == 0) {
225                        hashtbl[h] = d;
226
227                } else {
228                        struct dent *dp;
229
230                        dp = (struct dent *) malloc (sizeof (struct dent));
231                        if (dp == NULL) {
232                                fprintf (stderr, "couldn't allocate space for collision\n");
233                                exit (1);
234                        }
235                        *dp = d;
236                        dp->next = hashtbl[h].next;
237                        hashtbl[h].next = dp;
238                }
239        }
240        printf ("\n");
241}
242
243/*
244 * fill in the flags in d, and put a null after the word in s
245 */
246
247makedent (lbuf, d)
248char *lbuf;
249struct dent *d;
250{
251        char *p, *index();
252
253        d->next = NULL;
254        d->used = 1;
255        d->v_flag = 0;
256        d->n_flag = 0;
257        d->x_flag = 0;
258        d->h_flag = 0;
259        d->y_flag = 0;
260        d->g_flag = 0;
261        d->j_flag = 0;
262        d->d_flag = 0;
263        d->t_flag = 0;
264        d->r_flag = 0;
265        d->z_flag = 0;
266        d->s_flag = 0;
267        d->p_flag = 0;
268        d->m_flag = 0;
269        d->keep = 0;
270        d->keep = 0;
271
272        p = index (lbuf, '/');
273        if (p != NULL)
274                *p = 0;
275        if (strlen (lbuf) > WORDLEN - 1) {
276                printf ("%s: word too big\n");
277                return (-1);
278        }
279
280        if (p == NULL)
281                return (0);
282
283        p++;
284        while (*p != '\0'  &&  *p != '\n') {
285                switch (*p) {
286                case 'V': d->v_flag = 1; break;
287                case 'N': d->n_flag = 1; break;
288                case 'X': d->x_flag = 1; break;
289                case 'H': d->h_flag = 1; break;
290                case 'Y': d->y_flag = 1; break;
291                case 'G': d->g_flag = 1; break;
292                case 'J': d->j_flag = 1; break;
293                case 'D': d->d_flag = 1; break;
294                case 'T': d->t_flag = 1; break;
295                case 'R': d->r_flag = 1; break;
296                case 'Z': d->z_flag = 1; break;
297                case 'S': d->s_flag = 1; break;
298                case 'P': d->p_flag = 1; break;
299                case 'M': d->m_flag = 1; break;
300                case 0:
301                        fprintf (stderr, "no flags on word %s\n", lbuf);
302                        continue;
303                default:
304                        fprintf (stderr, "unknown flag %c word %s\n",
305                                        *p, lbuf);
306                        break;
307                }
308                p++;
309                if (*p == '/')          /* Handle old-format dictionaries too */
310                        p++;
311        }
312        return (0);
313}
314
315newcount ()
316{
317        char buf[200];
318        FILE *d;
319        int i;
320
321        fprintf (stderr, "Counting words in dictionary ...\n");
322
323        if ((d = fopen (Dfile, "r")) == NULL) {
324                fprintf (stderr, "Can't open dictionary\n");
325                exit (1);
326        }
327
328        for (i = 0; fgets (buf, sizeof buf, d); )
329                if ((++i & 1023) == 0) {
330                        printf ("%d ", i);
331                        fflush (stdout);
332                }
333        (void) fclose (d);
334        printf ("\n%d words\n", i);
335        if ((d = fopen (Cfile, "w")) == NULL) {
336                fprintf (stderr, "can't create %s\n", Cfile);
337                exit (1);
338        }
339        fprintf (d, "%d\n", i);
340        (void) fclose (d);
341}
Note: See TracBrowser for help on using the repository browser.