|
|
1.1 root 1: /*
2: * Common routines to read and write words
3: * in the compressed dictionary for the
4: * simple (but complete) version of spell.
5: */
6:
7: #include <stdio.h>
8: #include <ctype.h>
9:
10: /*
11: * The coding is as follows:
12: * 1-26 are letters, 27 is `-', 28 is apostrophe.
13: * 0 is the pad character at word's end.
14: * 29 is optional `s', 30-31 is unused.
15: * They are packed with 3 per 16 bits (canonically)
16: * and the 16th bit is the end-of-word marker.
17: * This is all done independent of byte-ordering or
18: * word size. All that is required is at least 8-bit
19: * bytes (chars) and at least 16-bit words (ints).
20: */
21:
22: static char compress[256]; /* Initialised in init */
23:
24: static char expand[] = {
25: '\0',
26: 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
27: 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
28: 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
29: 'y', 'z', '-','\'', '#','\0','\0'
30: };
31:
32: #define EWORD 0100000 /* End of word */
33: #define NWORD 50 /* Length of a word */
34: #define NCLONE 500 /* Number of clones to save (maximum) */
35: #define NSPACE 2000 /* Size of string space for plurals */
36:
37: static char word[NWORD]; /* Static space returned by getword() */
38: static char space[NSPACE];
39: static char *spacep = space;
40: static char *clones[NCLONE]; /* Table of saved plurals */
41: static int nclone;
42:
43: /*
44: * Initialise the compressed table.
45: * This is independent of character set
46: * representation (e.g. ascii or ebcdic)
47: * and only has to be called if putword is used.
48: */
49: init()
50: {
51: compress['-'] = 27;
52: compress['\'']= 28;
53: compress['#'] = 29;
54: compress['a'] = compress['A'] = 1;
55: compress['b'] = compress['B'] = 2;
56: compress['c'] = compress['C'] = 3;
57: compress['d'] = compress['D'] = 4;
58: compress['e'] = compress['E'] = 5;
59: compress['f'] = compress['F'] = 6;
60: compress['g'] = compress['G'] = 7;
61: compress['h'] = compress['H'] = 8;
62: compress['i'] = compress['I'] = 9;
63: compress['j'] = compress['J'] = 10;
64: compress['k'] = compress['K'] = 11;
65: compress['l'] = compress['L'] = 12;
66: compress['m'] = compress['M'] = 13;
67: compress['n'] = compress['N'] = 14;
68: compress['o'] = compress['O'] = 15;
69: compress['p'] = compress['P'] = 16;
70: compress['q'] = compress['Q'] = 17;
71: compress['r'] = compress['R'] = 18;
72: compress['s'] = compress['S'] = 19;
73: compress['t'] = compress['T'] = 20;
74: compress['u'] = compress['U'] = 21;
75: compress['v'] = compress['V'] = 22;
76: compress['w'] = compress['W'] = 23;
77: compress['x'] = compress['X'] = 24;
78: compress['y'] = compress['Y'] = 25;
79: compress['z'] = compress['Z'] = 26;
80: }
81:
82: /*
83: * Read a word from the dictionary,
84: * one `dfp'. Return pointer to
85: * word or NULL on EOF.
86: * `*' words are cloned into the singular
87: * and plural. The plural is saved until
88: * it comes up in collating order.
89: */
90: char *
91: getword(dfp)
92: FILE *dfp;
93: {
94: register char *wp;
95: register int t = EWORD;
96: static int clone;
97: static int saved;
98:
99: if (saved) {
100: saved = 0;
101: } else {
102: clone = 0;
103: wp = word;
104: for (;;) {
105: register int c;
106:
107: if ((c = getc(dfp)) == EOF)
108: break;
109: t = c;
110: if ((c = getc(dfp)) == EOF)
111: goto bad;
112: t <<= 8;
113: t |= c;
114: if ((*wp++ = expand[t&037]) == '#')
115: clone++;
116: if ((*wp++ = expand[(t>>5)&037]) == '#')
117: clone++;
118: if ((*wp++ = expand[(t>>10)&037]) == '#')
119: clone++;
120: if (t & EWORD)
121: break;
122: }
123: if (wp == word)
124: return (NULL);
125: if ((t&EWORD) == 0)
126: goto bad;
127: if (clone)
128: while (wp > word)
129: if (*--wp == '#')
130: break;
131: *wp = '\0';
132: }
133: if (nclone && strcmp(word, clones[nclone-1])>0) {
134: wp = clones[--nclone];
135: saved++;
136: return (spacep = wp);
137: } else if (clone) {
138: plural(word);
139: clone = 0;
140: }
141: return (word);
142: bad:
143: fprintf(stderr, "spell: bad dictionary format\n");
144: exit(1);
145: }
146:
147: /*
148: * Pluralise the word, by adding an 's' to it.
149: * Save a copy away in the list of pending plurals
150: * (`clones').
151: */
152: static
153: plural(s)
154: char *s;
155: {
156: register char *cp;
157: register char *as;
158:
159: for (cp=s; *cp++ != '\0'; )
160: ;
161: *--cp = 's';
162: cp++;
163: *cp++ = '\0';
164: if (nclone >= NCLONE) {
165: fprintf(stderr, "spell: too many saved plurals\n");
166: exit(1);
167: }
168: as = spacep;
169: if ((spacep += cp-s) >= &space[NSPACE]) {
170: fprintf(stderr, "spell: out of memory for plurals\n");
171: exit(1);
172: }
173: strcpy(as, s);
174: clones[nclone++] = as;
175: cp[-2] = '\0'; /* Restore original word */
176: }
177:
178: /*
179: * Put out the ascii word, onto the
180: * dictionary file in compressed form.
181: */
182: putword(wp, dfp)
183: register char *wp;
184: FILE *dfp;
185: {
186: register int l;
187:
188: while ((l = compress[*wp++]) != 0)
189: putlet(l, dfp);
190: putlet(0, dfp);
191: }
192:
193: /*
194: * Put out a single compressed letter.
195: * 0 Marks end of word.
196: */
197: putlet(l, fp)
198: register int l;
199: register FILE *fp;
200: {
201: static int n = 0;
202: static int word = 0;
203:
204: if (l != 0) {
205: word |= l<<(n*5);
206: if (++n < 3)
207: return;
208: } else
209: word |= EWORD;
210: putc(word>>8, fp);
211: putc(word&0377, fp);
212: n = word = 0;
213: word = 0;
214: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.