|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 7052 (0x1b8c)
Types: TextFile
Notes: UNIX file
Names: »look.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/look.c«
/* look.c - look for matching lines of text in a sorted file.
*/
#include <stdio.h>
#include <ctype.h>
#define TRUE 1
#define FALSE 0
#define EQ 1
#define LESS 0
#define GREATER 2
#define TAB ' '
#define BSIZ 512
extern long ftell() ;
/* Globals
*/
int d_mode, f_mode ;
long top, bottom ;
long fsiz ;
FILE *fildes ;
char stbuf[BSIZ], rbuf[BSIZ] ;
char *rbufp ;
/* getx - Get the nex character from the character buffer.
* If the buffer is empty get the next block.
*/
/* getx()
* {
* if (rbufp < &rbuf[BSIZ])
* return(*rbufp++) ;
* else {
* gnb() ;
* return(getx()) ;
* }
* }
*/
#ifdef FIXED /* Bug in 8086 compiler */
#define getx() ((rbuf < &rbuf[BSIZ]) ? *rbufp++ : (gnb(), *rbufp++))
#else
getx()
{
if (rbufp >= &rbuf[BSIZ])
gnb();
return (*rbufp++);
}
#endif
/* order - Order relation for characters. Returns GREATER, LESS or EQ.
*/
/* order(a, b)
* {
* if (a > b)
* return(GREATER) ;
* else if (a < b)
* return(LESS) ;
* return(EQ) ;
* }
*/
#define order(a, b) ((a > b) ? GREATER : ((a < b) ? LESS : EQ))
/* isdict - Test for a dictionary character. From the class :
* [a-zA-Z0-9 ].
*/
/* isdict(ch)
* {
* if (isalnum(ch) || (ch == ' '))
* return(1) ;
* return(0) ;
* }
*/
#define isdict(ch) ((isalnum(ch) || (ch == ' ')) ? 1 : 0)
/* main - Get args, set flags and get the ball rolling.
*/
main(argc, argv)
register char *argv[] ;
{
++argv ;
switch (argc) {
case 4 :
case 3 :
if (setop(argv[0])) {
++argv ;
--argc ;
} else
if (argc == 4) {
form() ;
break ;
}
case 2 :
if (argc == 3)
gfile(argv[1]) ;
else
gfile(NULL) ;
if (gstring(argv[0])) {
look() ;
exit(0) ;
break ;
}
default :
form() ;
}
exit(1) ;
}
/* setop - set option flags d_mode and f_mode. d_mode marks an occurance
* of -d[f] or -[f]d and f_mode marks an occurance of -f[d] or
* -[d]f.
*/
setop(fp)
register char *fp ;
{
register int i ;
d_mode = FALSE ;
f_mode = FALSE ;
if (*fp++ != '-')
return(0) ;
else {
for (i = 0; i < 2; i++) {
switch (*fp++) {
case 'd' :
d_mode = TRUE ;
break ;
case 'f' :
f_mode = TRUE ;
break ;
case '\0' :
--fp ;
return(1) ;
default :
return(0) ;
}
}
if (*fp != '\0')
return(0) ;
return(1) ;
}
}
/* gstring - gets the match string <string> and places it in the
* stbuf buffer after conforming it to the d_mode and
* f_mode options (That will make the compare routine
* faster). Returns the number of characters in stbuf.
*/
gstring(fp)
register char *fp ;
{
register int nc ;
register char *st ;
nc = 0 ;
st = stbuf ;
while ((nc++ < BSIZ) && (*fp != '\0')) {
if (d_mode && !isdict(*fp)) {
fp++ ;
nc-- ;
continue ;
}
if (f_mode && islower(*fp)) {
*st++ = toupper(*fp++) ;
continue ;
}
*st++ = *fp++ ;
}
if (nc >= BSIZ)
return(0) ;
return(nc) ;
}
/* gfile - Gets the specified file and opens it for reading.
* If no file is specified /usr/dict/words is opened.
*/
gfile(fp)
register char *fp ;
{
register char *file ;
if (fp == NULL) {
file = "/usr/dict/words" ;
d_mode = TRUE ;
f_mode = TRUE ;
} else
file = fp ;
if ((fildes = fopen(file, "r")) == NULL) {
aww("look : Cannot open file") ;
exit(1) ;
}
bottom = 0 ;
if (fseek(fildes, 0L, 2) == -1) {
aww("look : Cannot seek on file") ;
exit(1) ;
}
top = ftell(fildes) ;
top -= 2 ;
fsiz = top ;
return(1) ;
}
/* aww - Error condition. Prints out the passed string.
*/
aww(sp)
char *sp ;
{
fprintf(stderr, "%s\n", sp) ;
}
/* form - Prints out a Usage message.
*/
form()
{
fprintf(stderr, "Usage : look [-df] string [file]\n") ;
}
/* look - Binary search looking for a string match. If a match
* is found (the EQ case) all the strings that match
* are printed and then we quit else the window is
* decreased and the test goes on.
*/
look()
{
register int nmove ;
long mid1, mid2 ;
long gll() ;
long gteol() ;
while (top != bottom) {
mid1 = (top - bottom)/2 + bottom ;
mid2 = gll(mid1) ;
nmove = comstr() ;
switch (nmove) {
case EQ :
wstr(mid2) ;
return(1) ;
case GREATER :
bottom = gteol(mid1) ;
break ;
case LESS :
top = mid2 - 2 ;
break ;
}
if (top < bottom)
top = bottom ;
}
}
/* wstr - We found a string that matches but we are not sure that
* this is the only occurance of a matched string and hence
* we must back up until we find a non match and print
* forward till we find a non match in the other direction.
*/
wstr(seek)
long seek ;
{
long temp1, temp2 ;
long gll() ;
if (seek != 0) {
temp2 = seek ;
temp1 = gll(seek - 2) ;
while (comstr() == EQ) {
temp2 = temp1 ;
if (temp1 == 0)
break ;
else
temp1 = gll(temp1 - 2) ;
}
} else
temp2 = 0 ;
fseek(fildes, temp2, 0) ;
while (ftell(fildes) <= seek) {
fgets(rbuf, BSIZ, fildes) ;
fputs(rbuf, stdout) ;
}
fgets(rbuf, BSIZ, fildes) ;
rbufp = rbuf ;
while (comstr() == EQ) {
fputs(rbuf, stdout) ;
fgets(rbuf, BSIZ, fildes) ;
rbufp = rbuf ;
}
return(1) ;
}
/* comstr - Compare the base string to the input line.
* Returns a stat telling what the difference between the
* two strings is. EQ is equal, GREATER implies the base string
* is greater then the input string and LESS is vice versa.
*/
comstr()
{
register int state ;
register int ch ;
register char *sp ;
sp = stbuf ;
while (*sp != '\0') {
ch = getx() ;
if (ch == '\n')
return(GREATER) ;
if (d_mode && !isdict(ch)) {
continue ;
}
if (f_mode && islower(ch))
ch = toupper(ch) ;
if ((state = order(*sp, ch)) != EQ) {
return(state) ;
}
++sp ;
}
return(EQ) ;
}
/* gll - Get last line. Using the seek variable, returns a pointer to
* the beginning of the last line of text. If neccesary
* gll will wind back seek a block at a time looking for
* the last line.
*/
long
gll(seek)
long seek ;
{
register char *cp ;
register int tmp ;
if (seek == 0) {
rbufp = rbuf ;
return(0) ;
}
if (seek < BSIZ) {
cp = &rbuf[(int) seek] ;
seek = 0 ;
fseek(fildes, 0L, 0) ;
} else {
cp = &rbuf[BSIZ - 1] ;
seek -= BSIZ ;
fseek(fildes, seek, 0) ;
}
fread(rbuf, sizeof(*cp), BSIZ, fildes) ;
while (cp >= rbuf) {
if (*cp == '\n')
break ;
--cp ;
}
if (*cp == '\n') {
rbufp = ++cp ;
tmp = cp - rbuf ;
seek += (long) tmp ;
if (seek > fsiz)
return(-1) ;
fseek(fildes, seek, 0) ;
fread(rbuf, sizeof(*rbufp), BSIZ, fildes) ;
rbufp = rbuf ;
return(seek) ;
} else
return(gll(seek)) ;
}
/* gnb - Get the next block from the file and adjust the
* character buffer pointer.
*/
gnb()
{
fseek(fildes, 512L, 1) ;
fread(rbuf, sizeof(*rbufp), BSIZ, fildes) ;
rbufp = rbuf ;
return(1) ;
}
/* gteol - Go to end of line. Returns the seek adress of the end of line.
*/
long
gteol(seek)
long seek ;
{
if (seek >= fsiz)
return(fsiz) ;
fseek(fildes, seek, 0) ;
while (fgetc(fildes) != '\n')
;
return(ftell(fildes)) ;
}