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