home *** CD-ROM | disk | FTP | other *** search
- /*
- * look - search a sorted file for lines beginning with string
- * Roger Cornelius (rac@sherpa.uucp)
- * Fri Oct 26 13:13:54 EDT 1990
- * public domain
- */
-
- #define _USE_MACROS /* for SCO UNIX, see ctype.h */
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <string.h>
- #include <ctype.h>
- #define ERR 2
-
- extern void exit();
- int dstrncmp();
- off_t backup();
- FILE *fopen();
- int fold = 0;
- int dict = 0;
- int (*compare)();
-
- main(argc, argv)
- register int argc;
- register char **argv;
- {
- extern int optind;
- char *file = "/usr/dict/words";
- char *string;
- int ch;
-
- while ((ch = getopt(argc, argv, "df?")) != -1)
- switch(ch) {
- case 'd': dict = 1; break;
- case 'f': fold = 1; break;
- case '?': goto usage;
- }
- argc -= optind;
- argv += optind;
-
- if (argc < 1 || argc > 2) {
- usage: (void)fputs("Usage: look [-df] string [file]\n", stderr);
- exit(ERR);
- }
- string = *argv;
- if (*++argv)
- file = *argv;
- else
- fold = dict = 1;
-
- return search(string, file);
- }
-
- /*
- * search --
- * search a sorted file for lines beginning with string
- * adapted from binsearch(), K&R 2nd ed.
- */
- static
- search(string, file)
- char *string;
- char *file;
- {
- FILE *fp;
- char buf[BUFSIZ], save[BUFSIZ];
- off_t low, mid, high, savemid = -1;
- off_t found = -1;
- register char *t;
- struct stat sbuf;
- size_t slen = strlen(string);
- int n, res = 1; /* not found */
-
- if ((fp = freopen(file, "r", stdin)) == NULL
- || stat(file, &sbuf) != 0) {
- /* avoid the printf kitchen sink */
- (void) fputs("look: can't access ", stderr);
- (void) fputs(file, stderr);
- (void) fputs("\n", stderr);
- return ERR;
- }
- low = 0;
- high = sbuf.st_size;
- compare = dict ? dstrncmp : strncmp;
- if (fold)
- for (t=string; *t; *t = tolower(*t), t++)
- ;
-
- while (low < high) {
- mid = (low+high) / 2;
- if (backup(&low, &mid, &high) == -1 || mid == savemid)
- break;
- savemid = mid;
- if (fseek(fp, mid, 0) != 0 || gets(buf) == NULL)
- return ERR;
-
- if (fold)
- for (t=buf; *t; *t = tolower(*t), t++)
- ;
- n = (*compare)(string, buf, slen);
- if (n < 0)
- high = mid - 1;
- else if (n > 0)
- low = mid + 1;
- else {
- found = mid; /* save offset of found string */
- high = mid - 1;
- if (strlen(buf) == slen)
- break;
- }
- }
- if (found >= 0) {
- if (fseek(fp, found, 0) != 0)
- return ERR;
- while (gets(buf) != NULL) {
- if (fold) {
- (void)strcpy(save, buf);
- for (t=buf; *t; *t = tolower(*t), t++)
- ;
- }
- if ((*compare)(string, buf, slen) != 0)
- break;
- (void)puts(fold ? save : buf);
- }
- res = 0; /* found */
- }
- (void)fclose(fp);
- return res;
- }
-
- /*
- * backup --
- * search backwards for newline - if none found
- * then reverse direction and start over
- */
- static off_t
- backup(low, offset, high)
- register off_t *low, *offset, *high;
- {
- register int c;
- register int inc = -1;
- off_t save = *offset;
-
- if (*offset == 0)
- return(*offset);
-
- for (; *offset < *high && fseek(stdin, *offset, 0) == 0; *offset += inc) {
- c = getchar();
- if (c == '\n' || *offset == 0)
- return (*offset == 0) ? *offset : (*offset)++;
- else if (c == EOF) /* should never happen */
- break;
- if (*offset <= *low) { /* start over, reversing direction */
- *offset = save;
- inc = 1;
- }
- }
- return -1L;
- }
-
- /*
- * dstrncmp --
- * dictionary strncmp() - only alpha characters,
- * digits, blanks and tabs participate in comparisons
- */
- static
- dstrncmp(s1, s2, n)
- register char *s1, *s2;
- register size_t n;
- {
- for (; n--; s1++, s2++) {
- while (*s1 && !(isalpha(*s1) || isdigit(*s1) || isspace(*s1)))
- s1++;
- if (*s1 == '\0')
- break;
- while (*s2 && !(isalpha(*s2) || isdigit(*s2) || isspace(*s2)))
- s2++;
- if (*s1 != *s2)
- return *s1 - *s2;
- }
- return 0;
- }
-
- /* end of look.c */
-