rer@hpfcdc.HP.COM (Rob Robason) (07/20/90)
h> I notice that our HP9000/840 doesn't have the "look" command. h> Is the source for this pd and available somewhere for anon-ftp? To my knowledge, look in not pd. It is part of the BSD4.3 release and doesn't appear on the list of CONTRIBUTED utilities I have. Rob Robason
jewett@hpl-opus.HP.COM (Bob Jewett) (07/23/90)
> I notice that our HP9000/840 doesn't have the "look" command. > Is the source for this pd and available somewhere for anon-ftp? I hacked together a version of look (which has -f but lacks -d) to get the dictionary search command to work in ispell. The shar is 8 kbytes. If I get three e-mail requests, I'll post it, unless someone has a better version they can part with, or wants to add -d first. Bob
jewett@hpl-opus.HP.COM (Bob Jewett) (07/25/90)
> If I get three e-mail requests, I'll post it, unless someone has a better > version they can part with, or wants to add -d first. There were requests, but no offers of improved versions. If you add the -d option (which seems to be unnecessary since /usr/dict/words is -f?), please send me the context diffs. The binary search routine is by Alan Silverstein; I wrote the (now old and crufty) wrapper to turn it into "look". Bob Jewett # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by Bob Jewett <jewett@hpl-bill> on Wed Jul 25 08:51:05 1990 # # This archive contains: # look.1 Makefile look.c # LANG=""; export LANG PATH=/bin:/usr/bin:$PATH; export PATH echo x - look.1 cat >look.1 <<'@EOF' .TH LOOK 1 Local .AT 3 .SH NAME look \- find lines in a sorted list .SH SYNOPSIS .B look [ .B \-f ] string [ file ] .SH DESCRIPTION .I Look searches a sorted .I file and prints all lines that begin with .IR string . It uses binary search. .PP The option .B f says that upper and lower case characters are equal. .PP If no .I file is specified, .I /usr/dict/words is assumed with collating sequence .B \-f. .SH BUGS This is a quick and dirty version of the BSD .I look command to make ispell work. It lacks the .B -d option. .SH FILES /usr/dict/words .SH "SEE ALSO" sort(1), grep(1) @EOF chmod 644 look.1 echo x - Makefile cat >Makefile <<'@EOF' # Makefile for look # PROGNAME = look CFLAGS = -O SRC = ${PROGNAME}.c MANSECT=1 MAN = ${PROGNAME}.1 BINDIR = /usr/local/bin MANDIR = /usr/local/man $(PROGNAME): $(SRC) cc ${CFLAGS} ${SRC} mv a.out ${PROGNAME} strip ${PROGNAME} install: $(PROGNAME) cp $(PROGNAME) $(BINDIR)/${PROGNAME} cp $(MAN) ${MANDIR}/man${MANSECT}/${PROGNAME}.${MANSECT} /bin/rm -f ${MANDIR}/cat${MANSECT}/${PROGNAME}.${MANSECT} clean: /bin/rm -f $(PROGNAME) core *.o shar : Makefile ${SRC} ${MAN} shar ${MAN} Makefile ${SRC} > shar @EOF chmod 664 Makefile echo x - look.c cat >look.c <<'@EOF' #include <stdio.h> #include <ctype.h> #define chNull ('\0') #define cpNull ((char *) NULL) #define WORDLIST "/usr/dict/words" #ifndef TRUE #define TRUE 1 #define FALSE 0 #endif char *progname; char *ap_upstr(); /* * Usage: look [ -f ] string [ file ] * * -f means fold lower case to upper */ main (argc, argv) int argc; char **argv; { FILE *fp; char buf[BUFSIZ]; char upbuf[BUFSIZ]; int argpoint; int foldcase=FALSE; char instring[BUFSIZ]; char upinstring[BUFSIZ]; char *sortedfile=WORDLIST; instring[0]='\0'; progname=argv[0]; if(argc < 2 || argc > 4) Usage(); if(argv[1][0] == '-') { if(strcmp(argv[1],"-f")) Usage(); if(argc < 3) Usage(); foldcase=TRUE; strcpy(instring,argv[2]); if(argc == 4) sortedfile=argv[3]; } else { if(argc > 3) Usage(); strcpy(instring,argv[1]); if(argc == 2) foldcase=TRUE; if(argc == 3) sortedfile=argv[2]; } strcpy(upinstring,instring); ap_upstr(upinstring); if(foldcase) ap_upstr(instring); fp = fopen (sortedfile, "r"); if(fp == NULL) { fprintf(stderr,"%s: file %s not readable.\n",progname,sortedfile); exit(1); } if(bsearchstr (fp, upinstring, TRUE, FALSE) < 0L) { /* fprintf(stderr,"bsearchstr failed to find anything\n"); */ exit(0); } while ( fgets(buf,BUFSIZ,fp) != NULL && starts2(upinstring,ap_upstr(strcpy(upbuf,buf)))) if(foldcase || starts2(instring,buf)) printf ("%s", buf); /* no newline required ??? */ exit(0); } /*************************************************************************** * B S E A R C H S T R * * Binary search a stream consisting of sorted lines of data for the first * line that starts with the given pattern, or the next line if none and * tellnext == 1. Set the file location to the first byte of that line * and return the offset. * * When caseins is set, takes pains not to modify the memory pointed to by * pattern. Uses multi-statement macros for efficiency. * * See bsearchstr(3) for more information. * * Author: Alan Silverstein, Hewlett-Packard Fort Collins Systems Division */ #define LT 0 #define EQ 1 #define GT 2 #define RETURN(value) { if (caseins) free (pattern); return (value); } #define SETPOS { if (fseek (filep, pos, 0) < 0) RETURN (-2L); } long bsearchstr (filep, pattern, caseins, tellnext) FILE *filep; /* file to search */ char *pattern; /* start of line to match */ int caseins; /* case insensitive? */ int tellnext; /* tell next if not found? */ { /* start of first line not yet compared (lower limit) */ long min = 0; /* start of line after last line not yet compared (upper limit) */ long max; long pos; /* current offset in file */ char *patp; /* pattern pointer */ /* warning: this must be an int, not a char */ register int ch; /* current char to compare */ register int cmp; /* results of comparison */ int match = 0; /* true if match found */ char *malloc(); /* * PREPARE PATTERN FOR CASE-INSENSITIVE SEARCH: * * Use toupper(), not tolower(), to be compatible with the actual function * of sort -f. */ if (caseins) { int len = strlen (pattern) + 1; /* chars to uppercase */ char *cp; /* for copying data */ char *cpend; /* end of copy range */ if ((cp = patp = malloc (len)) == cpNull) return (-2L); /* now remember to free (pattern) before returning */ /* can use the RETURN() macro to accomplish this */ cpend = cp + len; while (cp < cpend) /* copy chNull also */ *cp++ = toupper (*pattern++); /* toupper() is not a macro! */ pattern = patp; /* "move" to new location */ } /* * SET MAX TO END OF FILE (byte past last) by seeking there: */ if ((fseek (filep, 0L, 2) < 0) || ((max = ftell (filep)) < 0)) RETURN (-2L); /* * SET NEXT STARTING POSITION (where to find string and compare): */ while (min < max) /* do until closure happens */ { pos = (min + max) / 2; SETPOS; #ifdef DEBUG printf ("%8ld %8ld %8ld ", min, max, pos); #endif /* * LOOK FOR THE NEXT END OF LINE IN THE FORWARD DIRECTION: */ while ((pos < max) && (getc (filep) != '\n')) pos++; pos++; /* skip newline */ /* * If we ran into max, we are nearly done, assuming the current last line is * not really huge compared to all the others (but this will work out OK too). * Simply reset pos = min and check the first current line. */ if (pos >= max) pos = min; /* * COMPARE THE CURRENT LINE TO THE PATTERN: * * If pattern[0] == chNull, never does the for loop, so it matches anything. */ SETPOS; for (cmp = EQ, patp = pattern; (*patp != chNull); patp++) { ch = caseins ? toupper (getc (filep)) : getc (filep); if ((ch < *patp) || (ch == '\n') || (ch == EOF)) { /* line < pattern */ cmp = LT; break; } else if (ch > *patp) /* line > pattern */ { cmp = GT; break; } } match += (cmp == EQ); /* note a match */ #ifdef DEBUG printf ("%8ld %c %5d\n", pos, ((cmp == LT) ? '<' : ((cmp == EQ) ? '=' : '>')), match); #endif /* * MOVE MIN OR MAX according to the results of comparison: * * If pattern[0] == chNull, cmp == EQ, which is "safe". */ if (cmp == LT) /* min => next line */ { min = pos + (patp - pattern); while ((ch != '\n') && (min < max)) /* find end */ { ch = getc (filep); min++; } min++; /* skip newline */ } else /* max => this line */ { max = pos; } } /* while */ /* * FINISH UP: * * Note that min could be one too large if the last line is unterminated * and less than pattern, so we use max instead. */ if (match || tellnext) /* success */ { pos = max; SETPOS; RETURN (pos); } else /* failure */ { RETURN (-1L); } } /* bsearchstr */ Usage() { fprintf(stderr,"Usage: %s [ -f ] string [ file ]\n",progname); exit(1); } char *ap_upstr(str) char *str; { int i; for(i=0;str[i] != '\0';i++) if(str[i] >= 'a' && str[i] <= 'z') str[i]=str[i]+'A'-'a'; return(str); } /* string 1 starts string 2. Must be followed by whitespace or nothing */ starts(s1,s2) char s1[], s2[]; { int i; for(i=0; s1[i] != 0; i++) if(s1[i] != s2[i]) return(0); if(s2[i] == '\0' || s2[i] == ' ' || s2[i] == '\011' ) return(1); return(0); } /* string 1 starts string 2. May be followed by printing characters */ starts2(s1,s2) char s1[], s2[]; { int i; for(i=0; s1[i] != 0; i++) if(s1[i] != s2[i]) return(0); return(1); } @EOF chmod 666 look.c exit 0