Annotation of coherent/d/bin/look.c, revision 1.1.1.1

1.1       root        1: /*     look.c - look for matching lines of text in a sorted file.
                      2:  */
                      3: #include       <stdio.h>
                      4: #include       <ctype.h>
                      5: 
                      6: #define        TRUE    1
                      7: #define        FALSE   0
                      8: #define        EQ      1
                      9: #define        LESS    0
                     10: #define        GREATER 2
                     11: #define        TAB     '       '
                     12: #define        BSIZ    512
                     13: 
                     14: extern long    ftell() ;
                     15: 
                     16: /*     Globals
                     17:  */
                     18: 
                     19: int    d_mode, f_mode ;
                     20: long   top, bottom ;
                     21: long   fsiz ;
                     22: FILE   *fildes ;
                     23: char   stbuf[BSIZ], rbuf[BSIZ] ;
                     24: char   *rbufp ;
                     25: 
                     26: /*     getx -  Get the nex character from the character buffer.
                     27:  *             If the buffer is empty get the next block.
                     28:  */
                     29: 
                     30: /*  getx()
                     31:  *  {
                     32:  *     if (rbufp < &rbuf[BSIZ])
                     33:  *             return(*rbufp++) ;
                     34:  *     else {
                     35:  *             gnb() ;
                     36:  *             return(getx()) ;
                     37:  *     }
                     38:  *  }
                     39:  */
                     40: 
                     41: #ifdef FIXED /* Bug in 8086 compiler */
                     42: #define        getx()  ((rbuf < &rbuf[BSIZ]) ? *rbufp++ : (gnb(), *rbufp++))
                     43: #else
                     44: getx()
                     45: {
                     46:        if (rbufp >= &rbuf[BSIZ])
                     47:                gnb();
                     48:        return (*rbufp++);
                     49: }
                     50: #endif
                     51: 
                     52: /*     order - Order relation for characters. Returns GREATER, LESS or EQ.
                     53:  */
                     54: 
                     55: /*  order(a, b)
                     56:  *  {
                     57:  *     if (a > b)
                     58:  *             return(GREATER) ;
                     59:  *     else if (a < b)
                     60:  *             return(LESS) ;
                     61:  *     return(EQ) ;
                     62:  *  }
                     63:  */
                     64: 
                     65: #define        order(a, b)     ((a > b) ? GREATER : ((a < b) ? LESS : EQ))
                     66: 
                     67: /*     isdict - Test for a dictionary character. From the class :
                     68:  *              [a-zA-Z0-9 ].
                     69:  */
                     70: 
                     71: /* isdict(ch)
                     72:  * {
                     73:  *     if (isalnum(ch) || (ch == ' '))
                     74:  *             return(1) ;
                     75:  *     return(0) ;
                     76:  * }
                     77:  */
                     78: 
                     79: #define        isdict(ch)      ((isalnum(ch) || (ch == ' ')) ? 1 : 0)
                     80: 
                     81: /*     main    - Get args, set flags and get the ball rolling.
                     82:  */
                     83: 
                     84: main(argc, argv)
                     85: register char  *argv[] ;
                     86: {
                     87:        ++argv ;
                     88:        switch (argc) {
                     89: 
                     90:        case 4 :
                     91:        case 3 :
                     92:                        if (setop(argv[0])) {
                     93:                                ++argv ;
                     94:                                --argc ;
                     95:                        } else
                     96:                                if (argc == 4) {
                     97:                                        form() ;
                     98:                                        break ;
                     99:                                }
                    100:        case 2 :
                    101:                        if (argc == 3)
                    102:                                gfile(argv[1]) ;
                    103:                        else
                    104:                                gfile(NULL) ;
                    105:                        if (gstring(argv[0])) {
                    106:                                look() ;
                    107:                                exit(0) ;
                    108:                                break ;
                    109:                        }
                    110:        default :
                    111:                        form() ;
                    112:        }
                    113:        exit(1) ;
                    114: }
                    115: 
                    116: /*     setop - set option flags d_mode and f_mode. d_mode marks an occurance
                    117:  *             of -d[f] or -[f]d and f_mode marks an occurance of -f[d] or
                    118:  *             -[d]f.
                    119:  */
                    120: 
                    121: setop(fp)
                    122: register char  *fp ;
                    123: {
                    124:        register int    i ;
                    125: 
                    126:        d_mode = FALSE ;
                    127:        f_mode = FALSE ;
                    128: 
                    129:        if (*fp++ != '-')
                    130:                return(0) ;
                    131:        else {
                    132:                for (i = 0; i < 2; i++) {
                    133:                        switch (*fp++) {
                    134: 
                    135:                        case 'd' :
                    136:                                        d_mode = TRUE ;
                    137:                                        break ;
                    138:                        case 'f' :
                    139:                                        f_mode = TRUE ;
                    140:                                        break ;
                    141:                        case '\0' :
                    142:                                        --fp ;
                    143:                                        return(1) ;
                    144:                        default :
                    145:                                        return(0) ;
                    146:                        }
                    147:                }
                    148:                if (*fp != '\0')
                    149:                        return(0) ;
                    150:                return(1) ;
                    151:        }
                    152: }
                    153: 
                    154: /*     gstring - gets the match string <string> and places it in the 
                    155:  *               stbuf buffer after conforming it to the d_mode and
                    156:  *               f_mode options (That will make the compare routine 
                    157:  *               faster). Returns the number of characters in stbuf.
                    158:  */
                    159: 
                    160: gstring(fp)
                    161: register char  *fp ;
                    162: {
                    163:        register int    nc ;
                    164:        register char   *st ;
                    165: 
                    166:        nc = 0 ;
                    167:        st = stbuf ;
                    168:        while ((nc++ < BSIZ) && (*fp != '\0')) {
                    169:                if (d_mode && !isdict(*fp)) {
                    170:                        fp++ ;
                    171:                        nc-- ;
                    172:                        continue ;
                    173:                }
                    174:                if (f_mode && islower(*fp)) {
                    175:                        *st++ = toupper(*fp++) ;
                    176:                        continue ;
                    177:                }
                    178:                *st++ = *fp++ ;
                    179:        }
                    180:        if (nc >= BSIZ)
                    181:                return(0) ;
                    182:        return(nc) ;
                    183: }
                    184: 
                    185: 
                    186: /*     gfile - Gets the specified file and opens it for reading.
                    187:  *             If no file is specified /usr/dict/words is opened.
                    188:  */
                    189: 
                    190: gfile(fp)
                    191: register char  *fp ;
                    192: {
                    193:        register char   *file ;
                    194: 
                    195:        if (fp == NULL) {
                    196:                file = "/usr/dict/words" ;
                    197:                d_mode = TRUE ;
                    198:                f_mode = TRUE ;
                    199:        } else
                    200:                file = fp ;
                    201:        
                    202:        if ((fildes = fopen(file, "r")) == NULL) {
                    203:                aww("look : Cannot open file") ;
                    204:                exit(1) ;
                    205:        }
                    206: 
                    207:        bottom = 0 ;
                    208:        if (fseek(fildes, 0L, 2) == -1) {
                    209:                aww("look : Cannot seek on file") ;
                    210:                exit(1) ;
                    211:        }
                    212: 
                    213:        top = ftell(fildes) ;
                    214:        top -= 2 ;
                    215:        fsiz = top ;
                    216: 
                    217: 
                    218:        return(1) ;
                    219: }
                    220: 
                    221: /*     aww - Error condition. Prints out the passed string.
                    222:  */
                    223: 
                    224: aww(sp)
                    225: char   *sp ;
                    226: {
                    227:        fprintf(stderr, "%s\n", sp) ;
                    228: }
                    229: 
                    230: /*     form - Prints out a Usage message.
                    231:  */
                    232: 
                    233: form()
                    234: {
                    235:        fprintf(stderr, "Usage : look [-df] string [file]\n") ;
                    236: }
                    237: 
                    238: /*     look - Binary search looking for a string match. If a match
                    239:  *            is found (the EQ case) all the strings that match
                    240:  *            are printed and then we quit else the window is 
                    241:  *            decreased and the test goes on.
                    242:  */
                    243: 
                    244: look()
                    245: {
                    246:        register int    nmove ;
                    247:        long    mid1, mid2 ;
                    248:        long    gll() ;
                    249:        long    gteol() ;
                    250: 
                    251:        while (top != bottom) {
                    252:                mid1 = (top - bottom)/2 + bottom ;
                    253:                mid2 = gll(mid1) ;
                    254:                nmove = comstr() ;
                    255:                switch (nmove) {
                    256: 
                    257:                case EQ :
                    258:                                wstr(mid2) ;
                    259:                                return(1) ;
                    260:                case GREATER :
                    261:                                bottom = gteol(mid1) ;
                    262:                                break ;
                    263:                case LESS :
                    264:                                top = mid2 - 2 ;
                    265:                                break ;
                    266:                }
                    267:                if (top < bottom)
                    268:                        top = bottom ;
                    269:        }
                    270: }
                    271: 
                    272: 
                    273: /*     wstr -  We found a string that matches but we are not sure that
                    274:  *             this is the only occurance of a matched string and hence
                    275:  *             we must back up until we find a non match and print 
                    276:  *             forward till we find a non match in the other direction.
                    277:  */
                    278: 
                    279: wstr(seek)
                    280: long   seek ;
                    281: {
                    282:        long    temp1, temp2 ;
                    283:        long    gll() ;
                    284: 
                    285:        if (seek != 0) {
                    286:                temp2 = seek ;
                    287:                temp1 = gll(seek - 2) ;
                    288:                while (comstr() == EQ) {
                    289:                        temp2 = temp1 ;
                    290:                        if (temp1 == 0)
                    291:                                break ;
                    292:                        else
                    293:                                temp1 = gll(temp1 - 2) ;
                    294:                }
                    295:        } else
                    296:                temp2 = 0 ;
                    297:        fseek(fildes, temp2, 0) ;
                    298:        while (ftell(fildes) <= seek) {
                    299:                fgets(rbuf, BSIZ, fildes) ;
                    300:                fputs(rbuf, stdout) ;
                    301:        }
                    302:        fgets(rbuf, BSIZ, fildes) ;
                    303:        rbufp = rbuf ;
                    304:        while (comstr() == EQ) {
                    305:                fputs(rbuf, stdout) ;
                    306:                fgets(rbuf, BSIZ, fildes) ;
                    307:                rbufp = rbuf ;
                    308:        }
                    309:        return(1) ;
                    310: }
                    311: 
                    312: /*     comstr - Compare the base string to the input line.
                    313:  *              Returns a stat telling what the difference between the
                    314:  *              two strings is. EQ is equal, GREATER implies the base string
                    315:  *              is greater then the input string and LESS is vice versa.
                    316:  */
                    317: 
                    318: comstr()
                    319: {
                    320:        register int    state ;
                    321:        register int    ch ;
                    322:        register char   *sp ;
                    323: 
                    324:        sp = stbuf ;
                    325:        while (*sp != '\0') {
                    326:                ch = getx() ;
                    327:                if (ch == '\n')
                    328:                        return(GREATER) ;
                    329:                if (d_mode && !isdict(ch)) {
                    330:                        continue ;
                    331:                }
                    332:                if (f_mode && islower(ch))
                    333:                        ch = toupper(ch) ;
                    334:                if ((state = order(*sp, ch)) != EQ) {
                    335:                        return(state) ;
                    336:                }
                    337:                ++sp ;
                    338:        }
                    339:        return(EQ) ;
                    340: }
                    341: 
                    342: /*     gll -   Get last line. Using the seek variable, returns a pointer to
                    343:  *             the beginning of the last line of text. If neccesary
                    344:  *             gll will wind back seek a block at a time looking for
                    345:  *             the last line.
                    346:  */
                    347: 
                    348: long
                    349: gll(seek)
                    350: long   seek ;
                    351: {
                    352:        register char   *cp ;
                    353:        register int    tmp ;
                    354: 
                    355:        if (seek == 0) {
                    356:                rbufp = rbuf ;
                    357:                return(0) ;
                    358:        }
                    359: 
                    360:        if (seek < BSIZ) {
                    361:                cp = &rbuf[(int) seek] ;
                    362:                seek = 0 ;
                    363:                fseek(fildes, 0L, 0) ;
                    364:        } else {
                    365:                cp = &rbuf[BSIZ - 1] ;
                    366:                seek -= BSIZ ;
                    367:                fseek(fildes, seek, 0) ;
                    368:        }
                    369:        fread(rbuf, sizeof(*cp), BSIZ, fildes) ;
                    370: 
                    371:        while (cp >= rbuf) {
                    372:                if (*cp == '\n')
                    373:                        break ;
                    374:                --cp ;
                    375:        }
                    376: 
                    377:        if (*cp == '\n') {
                    378:                rbufp = ++cp ;
                    379:                tmp = cp - rbuf ;
                    380:                seek += (long) tmp ;
                    381:                if (seek > fsiz)
                    382:                        return(-1) ;
                    383:                fseek(fildes, seek, 0) ;
                    384:                fread(rbuf, sizeof(*rbufp), BSIZ, fildes) ;
                    385:                rbufp = rbuf ;
                    386:                return(seek) ;
                    387:        } else
                    388:                return(gll(seek)) ;
                    389: }
                    390: 
                    391: /*     gnb -   Get the next block from the file and adjust the 
                    392:  *             character buffer pointer.
                    393:  */
                    394: 
                    395: gnb()
                    396: {
                    397:        fseek(fildes, 512L, 1) ;
                    398:        fread(rbuf, sizeof(*rbufp), BSIZ, fildes) ;
                    399:        rbufp = rbuf ;
                    400:        return(1) ;
                    401: }
                    402: 
                    403: /*     gteol - Go to end of line. Returns the seek adress of the end of line.
                    404:  */
                    405: 
                    406: long
                    407: gteol(seek)
                    408: long   seek ;
                    409: {
                    410:        if (seek >= fsiz)
                    411:                return(fsiz) ;
                    412:        fseek(fildes, seek, 0) ;
                    413:        while (fgetc(fildes) != '\n')
                    414:                ;
                    415:        return(ftell(fildes)) ;
                    416: }
                    417: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.