Blame


1 c8af1ab1 2004-04-19 devnull #include <u.h>
2 c8af1ab1 2004-04-19 devnull #include <libc.h>
3 c8af1ab1 2004-04-19 devnull #include <bio.h>
4 c8af1ab1 2004-04-19 devnull /* Macros for Rune support of ctype.h-like functions */
5 c8af1ab1 2004-04-19 devnull
6 c8af1ab1 2004-04-19 devnull #define isupper(r) (L'A' <= (r) && (r) <= L'Z')
7 c8af1ab1 2004-04-19 devnull #define islower(r) (L'a' <= (r) && (r) <= L'z')
8 c8af1ab1 2004-04-19 devnull #define isalpha(r) (isupper(r) || islower(r))
9 c8af1ab1 2004-04-19 devnull #define islatin1(r) (0xC0 <= (r) && (r) <= 0xFF)
10 c8af1ab1 2004-04-19 devnull
11 c8af1ab1 2004-04-19 devnull #define isdigit(r) (L'0' <= (r) && (r) <= L'9')
12 c8af1ab1 2004-04-19 devnull
13 c8af1ab1 2004-04-19 devnull #define isalnum(r) (isalpha(r) || isdigit(r))
14 c8af1ab1 2004-04-19 devnull
15 c8af1ab1 2004-04-19 devnull #define isspace(r) ((r) == L' ' || (r) == L'\t' \
16 c8af1ab1 2004-04-19 devnull || (0x0A <= (r) && (r) <= 0x0D))
17 c8af1ab1 2004-04-19 devnull
18 c8af1ab1 2004-04-19 devnull #define tolower(r) ((r)-'A'+'a')
19 c8af1ab1 2004-04-19 devnull
20 c8af1ab1 2004-04-19 devnull #define sgn(v) ((v) < 0 ? -1 : ((v) > 0 ? 1 : 0))
21 c8af1ab1 2004-04-19 devnull
22 c8af1ab1 2004-04-19 devnull #define WORDSIZ 4000
23 c8af1ab1 2004-04-19 devnull char *filename = "#9/lib/words";
24 c8af1ab1 2004-04-19 devnull Biobuf *dfile;
25 c8af1ab1 2004-04-19 devnull Biobuf bout;
26 c8af1ab1 2004-04-19 devnull Biobuf bin;
27 c8af1ab1 2004-04-19 devnull
28 c8af1ab1 2004-04-19 devnull int fold;
29 c8af1ab1 2004-04-19 devnull int direc;
30 c8af1ab1 2004-04-19 devnull int exact;
31 c8af1ab1 2004-04-19 devnull int iflag;
32 c8af1ab1 2004-04-19 devnull int rev = 1; /*-1 for reverse-ordered file, not implemented*/
33 c8af1ab1 2004-04-19 devnull int (*compare)(Rune*, Rune*);
34 c8af1ab1 2004-04-19 devnull Rune tab = '\t';
35 c8af1ab1 2004-04-19 devnull Rune entry[WORDSIZ];
36 c8af1ab1 2004-04-19 devnull Rune word[WORDSIZ];
37 c8af1ab1 2004-04-19 devnull Rune key[50], orig[50];
38 c8af1ab1 2004-04-19 devnull Rune latin_fold_tab[] =
39 c8af1ab1 2004-04-19 devnull {
40 c8af1ab1 2004-04-19 devnull /* Table to fold latin 1 characters to ASCII equivalents
41 c8af1ab1 2004-04-19 devnull based at Rune value 0xc0
42 c8af1ab1 2004-04-19 devnull
43 c8af1ab1 2004-04-19 devnull À Á Â Ã Ä Å Æ Ç
44 c8af1ab1 2004-04-19 devnull È É Ê Ë Ì Í Î Ï
45 c8af1ab1 2004-04-19 devnull Ð Ñ Ò Ó Ô Õ Ö ×
46 c8af1ab1 2004-04-19 devnull Ø Ù Ú Û Ü Ý Þ ß
47 c8af1ab1 2004-04-19 devnull à á â ã ä å æ ç
48 c8af1ab1 2004-04-19 devnull è é ê ë ì í î ï
49 c8af1ab1 2004-04-19 devnull ð ñ ò ó ô õ ö ÷
50 c8af1ab1 2004-04-19 devnull ø ù ú û ü ý þ ÿ
51 c8af1ab1 2004-04-19 devnull */
52 c8af1ab1 2004-04-19 devnull 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c',
53 c8af1ab1 2004-04-19 devnull 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
54 c8af1ab1 2004-04-19 devnull 'd', 'n', 'o', 'o', 'o', 'o', 'o', 0 ,
55 c8af1ab1 2004-04-19 devnull 'o', 'u', 'u', 'u', 'u', 'y', 0 , 0 ,
56 c8af1ab1 2004-04-19 devnull 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c',
57 c8af1ab1 2004-04-19 devnull 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i',
58 c8af1ab1 2004-04-19 devnull 'd', 'n', 'o', 'o', 'o', 'o', 'o', 0 ,
59 c8af1ab1 2004-04-19 devnull 'o', 'u', 'u', 'u', 'u', 'y', 0 , 'y',
60 c8af1ab1 2004-04-19 devnull };
61 c8af1ab1 2004-04-19 devnull
62 c8af1ab1 2004-04-19 devnull int locate(void);
63 c8af1ab1 2004-04-19 devnull int acomp(Rune*, Rune*);
64 c8af1ab1 2004-04-19 devnull int getword(Biobuf*, Rune *rp, int n);
65 c8af1ab1 2004-04-19 devnull void torune(char*, Rune*);
66 c8af1ab1 2004-04-19 devnull void rcanon(Rune*, Rune*);
67 c8af1ab1 2004-04-19 devnull int ncomp(Rune*, Rune*);
68 c8af1ab1 2004-04-19 devnull
69 c8af1ab1 2004-04-19 devnull void
70 c8af1ab1 2004-04-19 devnull main(int argc, char *argv[])
71 c8af1ab1 2004-04-19 devnull {
72 c8af1ab1 2004-04-19 devnull int n;
73 c8af1ab1 2004-04-19 devnull
74 c8af1ab1 2004-04-19 devnull filename = unsharp(filename);
75 c8af1ab1 2004-04-19 devnull
76 c8af1ab1 2004-04-19 devnull Binit(&bin, 0, OREAD);
77 c8af1ab1 2004-04-19 devnull Binit(&bout, 1, OWRITE);
78 c8af1ab1 2004-04-19 devnull compare = acomp;
79 c8af1ab1 2004-04-19 devnull ARGBEGIN{
80 c8af1ab1 2004-04-19 devnull case 'd':
81 c8af1ab1 2004-04-19 devnull direc++;
82 c8af1ab1 2004-04-19 devnull break;
83 c8af1ab1 2004-04-19 devnull case 'f':
84 c8af1ab1 2004-04-19 devnull fold++;
85 c8af1ab1 2004-04-19 devnull break;
86 c8af1ab1 2004-04-19 devnull case 'i':
87 c8af1ab1 2004-04-19 devnull iflag++;
88 c8af1ab1 2004-04-19 devnull break;
89 c8af1ab1 2004-04-19 devnull case 'n':
90 c8af1ab1 2004-04-19 devnull compare = ncomp;
91 c8af1ab1 2004-04-19 devnull break;
92 c8af1ab1 2004-04-19 devnull case 't':
93 c8af1ab1 2004-04-19 devnull chartorune(&tab,ARGF());
94 c8af1ab1 2004-04-19 devnull break;
95 c8af1ab1 2004-04-19 devnull case 'x':
96 c8af1ab1 2004-04-19 devnull exact++;
97 c8af1ab1 2004-04-19 devnull break;
98 c8af1ab1 2004-04-19 devnull default:
99 c8af1ab1 2004-04-19 devnull fprint(2, "%s: bad option %c\n", argv0, ARGC());
100 c8af1ab1 2004-04-19 devnull fprint(2, "usage: %s -[dfinx] [-t c] [string] [file]\n", argv0);
101 c8af1ab1 2004-04-19 devnull exits("usage");
102 c8af1ab1 2004-04-19 devnull } ARGEND
103 c8af1ab1 2004-04-19 devnull if(!iflag){
104 c8af1ab1 2004-04-19 devnull if(argc >= 1) {
105 c8af1ab1 2004-04-19 devnull torune(argv[0], orig);
106 c8af1ab1 2004-04-19 devnull argv++;
107 c8af1ab1 2004-04-19 devnull argc--;
108 c8af1ab1 2004-04-19 devnull } else
109 c8af1ab1 2004-04-19 devnull iflag++;
110 c8af1ab1 2004-04-19 devnull }
111 c8af1ab1 2004-04-19 devnull if(argc < 1) {
112 c8af1ab1 2004-04-19 devnull direc++;
113 c8af1ab1 2004-04-19 devnull fold++;
114 c8af1ab1 2004-04-19 devnull } else
115 c8af1ab1 2004-04-19 devnull filename = argv[0];
116 c8af1ab1 2004-04-19 devnull if (!iflag)
117 c8af1ab1 2004-04-19 devnull rcanon(orig, key);
118 c8af1ab1 2004-04-19 devnull dfile = Bopen(filename, OREAD);
119 c8af1ab1 2004-04-19 devnull if(dfile == 0) {
120 c8af1ab1 2004-04-19 devnull fprint(2, "look: can't open %s\n", filename);
121 c8af1ab1 2004-04-19 devnull exits("no dictionary");
122 c8af1ab1 2004-04-19 devnull }
123 c8af1ab1 2004-04-19 devnull if(!iflag)
124 c8af1ab1 2004-04-19 devnull if(!locate())
125 c8af1ab1 2004-04-19 devnull exits("not found");
126 c8af1ab1 2004-04-19 devnull do {
127 c8af1ab1 2004-04-19 devnull if(iflag) {
128 c8af1ab1 2004-04-19 devnull Bflush(&bout);
129 c8af1ab1 2004-04-19 devnull if(!getword(&bin, orig, sizeof(orig)/sizeof(orig[0])))
130 c8af1ab1 2004-04-19 devnull exits(0);
131 c8af1ab1 2004-04-19 devnull rcanon(orig, key);
132 c8af1ab1 2004-04-19 devnull if(!locate())
133 c8af1ab1 2004-04-19 devnull continue;
134 c8af1ab1 2004-04-19 devnull }
135 c8af1ab1 2004-04-19 devnull if (!exact || !acomp(word, key))
136 c8af1ab1 2004-04-19 devnull Bprint(&bout, "%S\n", entry);
137 c8af1ab1 2004-04-19 devnull while(getword(dfile, entry, sizeof(entry)/sizeof(entry[0]))) {
138 c8af1ab1 2004-04-19 devnull rcanon(entry, word);
139 c8af1ab1 2004-04-19 devnull n = compare(key, word);
140 c8af1ab1 2004-04-19 devnull switch(n) {
141 c8af1ab1 2004-04-19 devnull case -1:
142 c8af1ab1 2004-04-19 devnull if(exact)
143 c8af1ab1 2004-04-19 devnull break;
144 c8af1ab1 2004-04-19 devnull case 0:
145 c8af1ab1 2004-04-19 devnull if (!exact || !acomp(word, orig))
146 c8af1ab1 2004-04-19 devnull Bprint(&bout, "%S\n", entry);
147 c8af1ab1 2004-04-19 devnull continue;
148 c8af1ab1 2004-04-19 devnull }
149 c8af1ab1 2004-04-19 devnull break;
150 c8af1ab1 2004-04-19 devnull }
151 c8af1ab1 2004-04-19 devnull } while(iflag);
152 c8af1ab1 2004-04-19 devnull exits(0);
153 c8af1ab1 2004-04-19 devnull }
154 c8af1ab1 2004-04-19 devnull
155 c8af1ab1 2004-04-19 devnull int
156 c8af1ab1 2004-04-19 devnull locate(void)
157 c8af1ab1 2004-04-19 devnull {
158 c8af1ab1 2004-04-19 devnull long top, bot, mid;
159 c8af1ab1 2004-04-19 devnull long c;
160 c8af1ab1 2004-04-19 devnull int n;
161 c8af1ab1 2004-04-19 devnull
162 c8af1ab1 2004-04-19 devnull bot = 0;
163 c8af1ab1 2004-04-19 devnull top = Bseek(dfile, 0L, 2);
164 c8af1ab1 2004-04-19 devnull for(;;) {
165 c8af1ab1 2004-04-19 devnull mid = (top+bot) / 2;
166 c8af1ab1 2004-04-19 devnull Bseek(dfile, mid, 0);
167 c8af1ab1 2004-04-19 devnull do
168 c8af1ab1 2004-04-19 devnull c = Bgetrune(dfile);
169 c8af1ab1 2004-04-19 devnull while(c>=0 && c!='\n');
170 c8af1ab1 2004-04-19 devnull mid = Boffset(dfile);
171 c8af1ab1 2004-04-19 devnull if(!getword(dfile, entry, sizeof(entry)/sizeof(entry[0])))
172 c8af1ab1 2004-04-19 devnull break;
173 c8af1ab1 2004-04-19 devnull rcanon(entry, word);
174 c8af1ab1 2004-04-19 devnull n = compare(key, word);
175 c8af1ab1 2004-04-19 devnull switch(n) {
176 c8af1ab1 2004-04-19 devnull case -2:
177 c8af1ab1 2004-04-19 devnull case -1:
178 c8af1ab1 2004-04-19 devnull case 0:
179 c8af1ab1 2004-04-19 devnull if(top <= mid)
180 c8af1ab1 2004-04-19 devnull break;
181 c8af1ab1 2004-04-19 devnull top = mid;
182 c8af1ab1 2004-04-19 devnull continue;
183 c8af1ab1 2004-04-19 devnull case 1:
184 c8af1ab1 2004-04-19 devnull case 2:
185 c8af1ab1 2004-04-19 devnull bot = mid;
186 c8af1ab1 2004-04-19 devnull continue;
187 c8af1ab1 2004-04-19 devnull }
188 c8af1ab1 2004-04-19 devnull break;
189 c8af1ab1 2004-04-19 devnull }
190 c8af1ab1 2004-04-19 devnull Bseek(dfile, bot, 0);
191 c8af1ab1 2004-04-19 devnull while(getword(dfile, entry, sizeof(entry)/sizeof(entry[0]))) {
192 c8af1ab1 2004-04-19 devnull rcanon(entry, word);
193 c8af1ab1 2004-04-19 devnull n = compare(key, word);
194 c8af1ab1 2004-04-19 devnull switch(n) {
195 c8af1ab1 2004-04-19 devnull case -2:
196 c8af1ab1 2004-04-19 devnull return 0;
197 c8af1ab1 2004-04-19 devnull case -1:
198 c8af1ab1 2004-04-19 devnull if(exact)
199 c8af1ab1 2004-04-19 devnull return 0;
200 c8af1ab1 2004-04-19 devnull case 0:
201 c8af1ab1 2004-04-19 devnull return 1;
202 c8af1ab1 2004-04-19 devnull case 1:
203 c8af1ab1 2004-04-19 devnull case 2:
204 c8af1ab1 2004-04-19 devnull continue;
205 c8af1ab1 2004-04-19 devnull }
206 c8af1ab1 2004-04-19 devnull }
207 c8af1ab1 2004-04-19 devnull return 0;
208 c8af1ab1 2004-04-19 devnull }
209 c8af1ab1 2004-04-19 devnull
210 c8af1ab1 2004-04-19 devnull /*
211 c8af1ab1 2004-04-19 devnull * acomp(s, t) returns:
212 c8af1ab1 2004-04-19 devnull * -2 if s strictly precedes t
213 c8af1ab1 2004-04-19 devnull * -1 if s is a prefix of t
214 c8af1ab1 2004-04-19 devnull * 0 if s is the same as t
215 c8af1ab1 2004-04-19 devnull * 1 if t is a prefix of s
216 c8af1ab1 2004-04-19 devnull * 2 if t strictly precedes s
217 c8af1ab1 2004-04-19 devnull */
218 c8af1ab1 2004-04-19 devnull
219 c8af1ab1 2004-04-19 devnull int
220 c8af1ab1 2004-04-19 devnull acomp(Rune *s, Rune *t)
221 c8af1ab1 2004-04-19 devnull {
222 c8af1ab1 2004-04-19 devnull int cs, ct;
223 c8af1ab1 2004-04-19 devnull
224 c8af1ab1 2004-04-19 devnull for(;;) {
225 c8af1ab1 2004-04-19 devnull cs = *s;
226 c8af1ab1 2004-04-19 devnull ct = *t;
227 c8af1ab1 2004-04-19 devnull if(cs != ct)
228 c8af1ab1 2004-04-19 devnull break;
229 c8af1ab1 2004-04-19 devnull if(cs == 0)
230 c8af1ab1 2004-04-19 devnull return 0;
231 c8af1ab1 2004-04-19 devnull s++;
232 c8af1ab1 2004-04-19 devnull t++;
233 c8af1ab1 2004-04-19 devnull }
234 c8af1ab1 2004-04-19 devnull if(cs == 0)
235 c8af1ab1 2004-04-19 devnull return -1;
236 c8af1ab1 2004-04-19 devnull if(ct == 0)
237 c8af1ab1 2004-04-19 devnull return 1;
238 c8af1ab1 2004-04-19 devnull if(cs < ct)
239 c8af1ab1 2004-04-19 devnull return -2;
240 c8af1ab1 2004-04-19 devnull return 2;
241 c8af1ab1 2004-04-19 devnull }
242 c8af1ab1 2004-04-19 devnull
243 c8af1ab1 2004-04-19 devnull void
244 c8af1ab1 2004-04-19 devnull torune(char *old, Rune *new)
245 c8af1ab1 2004-04-19 devnull {
246 c8af1ab1 2004-04-19 devnull do old += chartorune(new, old);
247 c8af1ab1 2004-04-19 devnull while(*new++);
248 c8af1ab1 2004-04-19 devnull }
249 c8af1ab1 2004-04-19 devnull
250 c8af1ab1 2004-04-19 devnull void
251 c8af1ab1 2004-04-19 devnull rcanon(Rune *old, Rune *new)
252 c8af1ab1 2004-04-19 devnull {
253 c8af1ab1 2004-04-19 devnull Rune r;
254 c8af1ab1 2004-04-19 devnull
255 c8af1ab1 2004-04-19 devnull while((r = *old++) && r != tab) {
256 c8af1ab1 2004-04-19 devnull if (islatin1(r) && latin_fold_tab[r-0xc0])
257 c8af1ab1 2004-04-19 devnull r = latin_fold_tab[r-0xc0];
258 c8af1ab1 2004-04-19 devnull if(direc)
259 c8af1ab1 2004-04-19 devnull if(!(isalnum(r) || r == L' ' || r == L'\t'))
260 c8af1ab1 2004-04-19 devnull continue;
261 c8af1ab1 2004-04-19 devnull if(fold)
262 c8af1ab1 2004-04-19 devnull if(isupper(r))
263 c8af1ab1 2004-04-19 devnull r = tolower(r);
264 c8af1ab1 2004-04-19 devnull *new++ = r;
265 c8af1ab1 2004-04-19 devnull }
266 c8af1ab1 2004-04-19 devnull *new = 0;
267 c8af1ab1 2004-04-19 devnull }
268 c8af1ab1 2004-04-19 devnull
269 c8af1ab1 2004-04-19 devnull int
270 c8af1ab1 2004-04-19 devnull ncomp(Rune *s, Rune *t)
271 c8af1ab1 2004-04-19 devnull {
272 c8af1ab1 2004-04-19 devnull Rune *is, *it, *js, *jt;
273 c8af1ab1 2004-04-19 devnull int a, b;
274 c8af1ab1 2004-04-19 devnull int ssgn, tsgn;
275 c8af1ab1 2004-04-19 devnull
276 c8af1ab1 2004-04-19 devnull while(isspace(*s))
277 c8af1ab1 2004-04-19 devnull s++;
278 c8af1ab1 2004-04-19 devnull while(isspace(*t))
279 c8af1ab1 2004-04-19 devnull t++;
280 c8af1ab1 2004-04-19 devnull ssgn = tsgn = -2*rev;
281 c8af1ab1 2004-04-19 devnull if(*s == '-') {
282 c8af1ab1 2004-04-19 devnull s++;
283 c8af1ab1 2004-04-19 devnull ssgn = -ssgn;
284 c8af1ab1 2004-04-19 devnull }
285 c8af1ab1 2004-04-19 devnull if(*t == '-') {
286 c8af1ab1 2004-04-19 devnull t++;
287 c8af1ab1 2004-04-19 devnull tsgn = -tsgn;
288 c8af1ab1 2004-04-19 devnull }
289 c8af1ab1 2004-04-19 devnull for(is = s; isdigit(*is); is++)
290 c8af1ab1 2004-04-19 devnull ;
291 c8af1ab1 2004-04-19 devnull for(it = t; isdigit(*it); it++)
292 c8af1ab1 2004-04-19 devnull ;
293 c8af1ab1 2004-04-19 devnull js = is;
294 c8af1ab1 2004-04-19 devnull jt = it;
295 c8af1ab1 2004-04-19 devnull a = 0;
296 c8af1ab1 2004-04-19 devnull if(ssgn == tsgn)
297 c8af1ab1 2004-04-19 devnull while(it>t && is>s)
298 c8af1ab1 2004-04-19 devnull if(b = *--it - *--is)
299 c8af1ab1 2004-04-19 devnull a = b;
300 c8af1ab1 2004-04-19 devnull while(is > s)
301 c8af1ab1 2004-04-19 devnull if(*--is != '0')
302 c8af1ab1 2004-04-19 devnull return -ssgn;
303 c8af1ab1 2004-04-19 devnull while(it > t)
304 c8af1ab1 2004-04-19 devnull if(*--it != '0')
305 c8af1ab1 2004-04-19 devnull return tsgn;
306 c8af1ab1 2004-04-19 devnull if(a)
307 c8af1ab1 2004-04-19 devnull return sgn(a)*ssgn;
308 c8af1ab1 2004-04-19 devnull if(*(s=js) == '.')
309 c8af1ab1 2004-04-19 devnull s++;
310 c8af1ab1 2004-04-19 devnull if(*(t=jt) == '.')
311 c8af1ab1 2004-04-19 devnull t++;
312 c8af1ab1 2004-04-19 devnull if(ssgn == tsgn)
313 c8af1ab1 2004-04-19 devnull while(isdigit(*s) && isdigit(*t))
314 c8af1ab1 2004-04-19 devnull if(a = *t++ - *s++)
315 c8af1ab1 2004-04-19 devnull return sgn(a)*ssgn;
316 c8af1ab1 2004-04-19 devnull while(isdigit(*s))
317 c8af1ab1 2004-04-19 devnull if(*s++ != '0')
318 c8af1ab1 2004-04-19 devnull return -ssgn;
319 c8af1ab1 2004-04-19 devnull while(isdigit(*t))
320 c8af1ab1 2004-04-19 devnull if(*t++ != '0')
321 c8af1ab1 2004-04-19 devnull return tsgn;
322 c8af1ab1 2004-04-19 devnull return 0;
323 c8af1ab1 2004-04-19 devnull }
324 c8af1ab1 2004-04-19 devnull
325 c8af1ab1 2004-04-19 devnull int
326 c8af1ab1 2004-04-19 devnull getword(Biobuf *f, Rune *rp, int n)
327 c8af1ab1 2004-04-19 devnull {
328 c8af1ab1 2004-04-19 devnull long c;
329 c8af1ab1 2004-04-19 devnull
330 c8af1ab1 2004-04-19 devnull while(n-- > 0) {
331 c8af1ab1 2004-04-19 devnull c = Bgetrune(f);
332 c8af1ab1 2004-04-19 devnull if(c < 0)
333 c8af1ab1 2004-04-19 devnull return 0;
334 c8af1ab1 2004-04-19 devnull if(c == '\n') {
335 c8af1ab1 2004-04-19 devnull *rp = L'\0';
336 c8af1ab1 2004-04-19 devnull return 1;
337 c8af1ab1 2004-04-19 devnull }
338 c8af1ab1 2004-04-19 devnull *rp++ = c;
339 c8af1ab1 2004-04-19 devnull }
340 c8af1ab1 2004-04-19 devnull fprint(2, "Look: word too long. Bailing out.\n");
341 c8af1ab1 2004-04-19 devnull return 0;
342 c8af1ab1 2004-04-19 devnull }