1*433d6423SLionel Sambuc /* look 1.3 - Find lines in a sorted list. Author: Kees J. Bot
2*433d6423SLionel Sambuc */
3*433d6423SLionel Sambuc #define nil 0
4*433d6423SLionel Sambuc #include <sys/types.h>
5*433d6423SLionel Sambuc #include <stdio.h>
6*433d6423SLionel Sambuc #include <ctype.h>
7*433d6423SLionel Sambuc #include <stdlib.h>
8*433d6423SLionel Sambuc #include <string.h>
9*433d6423SLionel Sambuc
10*433d6423SLionel Sambuc char DEFAULT[] = "/usr/lib/dict/words";
11*433d6423SLionel Sambuc
12*433d6423SLionel Sambuc char *string, *wordlist= DEFAULT;
13*433d6423SLionel Sambuc
14*433d6423SLionel Sambuc #define MAXLEN 1024 /* Maximum word length. */
15*433d6423SLionel Sambuc
16*433d6423SLionel Sambuc int dflg= 0, fflg= 0;
17*433d6423SLionel Sambuc
nonascii(char * what)18*433d6423SLionel Sambuc void nonascii(char *what)
19*433d6423SLionel Sambuc {
20*433d6423SLionel Sambuc fprintf(stderr, "look: %s contains non-ASCII characters.\n", what);
21*433d6423SLionel Sambuc exit(1);
22*433d6423SLionel Sambuc }
23*433d6423SLionel Sambuc
compare(char * prefix,char * word)24*433d6423SLionel Sambuc int compare(char *prefix, char *word)
25*433d6423SLionel Sambuc {
26*433d6423SLionel Sambuc char *p= prefix, *w= word;
27*433d6423SLionel Sambuc int cp, cw;
28*433d6423SLionel Sambuc
29*433d6423SLionel Sambuc do {
30*433d6423SLionel Sambuc do {
31*433d6423SLionel Sambuc if ((cp= *p++) == 0) return 0;
32*433d6423SLionel Sambuc if (!isascii(cp)) nonascii("prefix string");
33*433d6423SLionel Sambuc } while (dflg && !isspace(cp) && !isalnum(cp));
34*433d6423SLionel Sambuc
35*433d6423SLionel Sambuc if (dflg) {
36*433d6423SLionel Sambuc if (isspace(cp)) {
37*433d6423SLionel Sambuc while (isspace(*p)) p++;
38*433d6423SLionel Sambuc cp= ' ';
39*433d6423SLionel Sambuc }
40*433d6423SLionel Sambuc }
41*433d6423SLionel Sambuc if (fflg && isupper(cp)) cp= tolower(cp);
42*433d6423SLionel Sambuc
43*433d6423SLionel Sambuc do {
44*433d6423SLionel Sambuc if ((cw= *w++) == 0) return 1;
45*433d6423SLionel Sambuc if (!isascii(cw)) nonascii(wordlist);
46*433d6423SLionel Sambuc } while (dflg && !isspace(cw) && !isalnum(cw));
47*433d6423SLionel Sambuc
48*433d6423SLionel Sambuc if (dflg) {
49*433d6423SLionel Sambuc if (isspace(cw)) {
50*433d6423SLionel Sambuc while (isspace(*w)) w++;
51*433d6423SLionel Sambuc cw= ' ';
52*433d6423SLionel Sambuc }
53*433d6423SLionel Sambuc }
54*433d6423SLionel Sambuc if (fflg && isupper(cw)) cw= tolower(cw);
55*433d6423SLionel Sambuc } while (cp == cw);
56*433d6423SLionel Sambuc
57*433d6423SLionel Sambuc return cp - cw;
58*433d6423SLionel Sambuc }
59*433d6423SLionel Sambuc
readword(FILE * f)60*433d6423SLionel Sambuc char *readword(FILE *f)
61*433d6423SLionel Sambuc {
62*433d6423SLionel Sambuc static char word[MAXLEN + 2];
63*433d6423SLionel Sambuc int n;
64*433d6423SLionel Sambuc
65*433d6423SLionel Sambuc if (fgets(word, sizeof(word), f) == nil) {
66*433d6423SLionel Sambuc if (ferror(f)) {
67*433d6423SLionel Sambuc fprintf(stderr, "look: read error on %s",
68*433d6423SLionel Sambuc wordlist);
69*433d6423SLionel Sambuc exit(1);
70*433d6423SLionel Sambuc }
71*433d6423SLionel Sambuc return nil;
72*433d6423SLionel Sambuc }
73*433d6423SLionel Sambuc
74*433d6423SLionel Sambuc n= strlen(word);
75*433d6423SLionel Sambuc
76*433d6423SLionel Sambuc if (word[n-1] != '\n') {
77*433d6423SLionel Sambuc fprintf(stderr, "look: word from %s is too long\n", wordlist);
78*433d6423SLionel Sambuc exit(1);
79*433d6423SLionel Sambuc }
80*433d6423SLionel Sambuc word[n-1] = 0;
81*433d6423SLionel Sambuc
82*433d6423SLionel Sambuc return word;
83*433d6423SLionel Sambuc }
84*433d6423SLionel Sambuc
look(void)85*433d6423SLionel Sambuc void look(void)
86*433d6423SLionel Sambuc {
87*433d6423SLionel Sambuc off_t low, mid, high;
88*433d6423SLionel Sambuc FILE *f;
89*433d6423SLionel Sambuc char *word;
90*433d6423SLionel Sambuc int c;
91*433d6423SLionel Sambuc
92*433d6423SLionel Sambuc if ((f= fopen(wordlist, "r")) == nil) {
93*433d6423SLionel Sambuc fprintf(stderr, "look: Can't open %s\n", wordlist);
94*433d6423SLionel Sambuc exit(1);
95*433d6423SLionel Sambuc }
96*433d6423SLionel Sambuc
97*433d6423SLionel Sambuc low= 0;
98*433d6423SLionel Sambuc
99*433d6423SLionel Sambuc fseek(f, (off_t) 0, 2);
100*433d6423SLionel Sambuc
101*433d6423SLionel Sambuc high= ftell(f);
102*433d6423SLionel Sambuc
103*433d6423SLionel Sambuc while (low <= high) {
104*433d6423SLionel Sambuc mid= (low + high) / 2;
105*433d6423SLionel Sambuc
106*433d6423SLionel Sambuc fseek(f, mid, 0);
107*433d6423SLionel Sambuc
108*433d6423SLionel Sambuc if (mid != 0) readword(f);
109*433d6423SLionel Sambuc
110*433d6423SLionel Sambuc if ((word= readword(f)) == nil)
111*433d6423SLionel Sambuc c= -1;
112*433d6423SLionel Sambuc else
113*433d6423SLionel Sambuc c= compare(string, word);
114*433d6423SLionel Sambuc
115*433d6423SLionel Sambuc if (c <= 0) high= mid - 1; else low= mid + 1;
116*433d6423SLionel Sambuc }
117*433d6423SLionel Sambuc fseek(f, low, 0);
118*433d6423SLionel Sambuc if (low != 0) readword(f);
119*433d6423SLionel Sambuc
120*433d6423SLionel Sambuc c=0;
121*433d6423SLionel Sambuc while (c >= 0 && (word= readword(f)) != nil) {
122*433d6423SLionel Sambuc c= compare(string, word);
123*433d6423SLionel Sambuc
124*433d6423SLionel Sambuc if (c == 0) puts(word);
125*433d6423SLionel Sambuc }
126*433d6423SLionel Sambuc }
127*433d6423SLionel Sambuc
main(int argc,char ** argv)128*433d6423SLionel Sambuc int main(int argc, char **argv)
129*433d6423SLionel Sambuc {
130*433d6423SLionel Sambuc if (argc == 2) dflg= fflg= 1;
131*433d6423SLionel Sambuc
132*433d6423SLionel Sambuc while (argc > 1 && argv[1][0] == '-') {
133*433d6423SLionel Sambuc char *p= argv[1] + 1;
134*433d6423SLionel Sambuc
135*433d6423SLionel Sambuc while (*p != 0) {
136*433d6423SLionel Sambuc switch (*p++) {
137*433d6423SLionel Sambuc case 'd': dflg= 1; break;
138*433d6423SLionel Sambuc case 'f': fflg= 1; break;
139*433d6423SLionel Sambuc default:
140*433d6423SLionel Sambuc fprintf(stderr, "look: Bad flag: %c\n", p[-1]);
141*433d6423SLionel Sambuc exit(1);
142*433d6423SLionel Sambuc }
143*433d6423SLionel Sambuc }
144*433d6423SLionel Sambuc argc--;
145*433d6423SLionel Sambuc argv++;
146*433d6423SLionel Sambuc }
147*433d6423SLionel Sambuc if (argc == 3)
148*433d6423SLionel Sambuc wordlist= argv[2];
149*433d6423SLionel Sambuc else
150*433d6423SLionel Sambuc if (argc != 2) {
151*433d6423SLionel Sambuc fprintf(stderr, "Usage: look [-df] string [file]\n");
152*433d6423SLionel Sambuc exit(1);
153*433d6423SLionel Sambuc }
154*433d6423SLionel Sambuc string= argv[1];
155*433d6423SLionel Sambuc look();
156*433d6423SLionel Sambuc exit(0);
157*433d6423SLionel Sambuc }
158*433d6423SLionel Sambuc /* Kees J. Bot 24-5-89. */
159