Annotation of researchv10no/cmd/grep.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * grep -- print lines matching (or not matching) a pattern
                      3:  *
                      4:  *     status returns:
                      5:  *             0 - ok, and some matches
                      6:  *             1 - ok, but no matches
                      7:  *             2 - some error
                      8:  */
                      9: /*#define      DOSTATS         /* define this to gather stats */
                     10: #ifdef DOSTATS
                     11: char *statsexpr;
                     12: long nlines, nbytes, ndepth, nmaxdepth;
                     13: char statsflags[1024], *statsfptr = statsflags;
                     14: dostats();
                     15: #endif
                     16: 
                     17: #include <ctype.h>
                     18: #include       <stdio.h>
                     19: #include       <fio.h>
                     20: 
                     21: #define        CBRA    1
                     22: #define        CCHR    2
                     23: #define        CDOT    4
                     24: #define        CCL     6
                     25: #define        NCCL    8
                     26: #define        CDOL    10
                     27: #define        CEOF    11
                     28: #define        CKET    12
                     29: #define        CBACK   18
                     30: 
                     31: #define        STAR    01
                     32: 
                     33: #define        LBSIZE  512
                     34: #define        ESIZE   256
                     35: #define        NBRA    9
                     36: 
                     37: char   expbuf[ESIZE];
                     38: long   lnum;
                     39: char   stdbuf[BUFSIZ];
                     40: char   *linebuf = stdbuf;
                     41: char   ybuf[5000];
                     42: int    bflag;
                     43: int    lflag;
                     44: int    nflag;
                     45: int    cflag;
                     46: int    vflag;
                     47: int    nfile;
                     48: int    hflag   = 1;
                     49: int    sflag;
                     50: int    scanexit;
                     51: int    iflag;
                     52: int    retcode = 0;
                     53: int    circf;
                     54: long   tln;
                     55: int    nsucc;
                     56: char   *braslist[NBRA];
                     57: char   *braelist[NBRA];
                     58: char   bittab[] = {
                     59:        1,
                     60:        2,
                     61:        4,
                     62:        8,
                     63:        16,
                     64:        32,
                     65:        64,
                     66:        128
                     67: };
                     68: 
                     69: main(argc, argv)
                     70: char **argv;
                     71: {
                     72:        extern etext();
                     73: 
                     74:        while (--argc > 0 && (++argv)[0][0]=='-'){
                     75: #ifdef DOSTATS
                     76:                *statsfptr++ = argv[0][1];
                     77: #endif
                     78:                switch (argv[0][1]) {
                     79: 
                     80:                case 'i':
                     81:                        iflag++;
                     82:                        continue;
                     83: 
                     84:                case 'h':
                     85:                        hflag = 0;
                     86:                        continue;
                     87: 
                     88:                case 's':
                     89:                        sflag++;
                     90:                        continue;
                     91: 
                     92:                case 'v':
                     93:                        vflag++;
                     94:                        continue;
                     95: 
                     96:                case 'b':
                     97:                        bflag++;
                     98:                        continue;
                     99: 
                    100:                case 'l':
                    101:                        lflag++;
                    102:                        continue;
                    103: 
                    104:                case 'c':
                    105:                        cflag++;
                    106:                        continue;
                    107: 
                    108:                case 'n':
                    109:                        nflag++;
                    110:                        continue;
                    111: 
                    112:                case 'e':
                    113:                        --argc;
                    114:                        ++argv;
                    115:                        goto out;
                    116: 
                    117:                default:
                    118:                        errexit("grep: unknown flag %c\n", argv[0][1]);
                    119:                        continue;
                    120:                }
                    121:        }
                    122: out:
                    123:        if (argc<=0)
                    124:                exit(2);
                    125:        if (iflag) {
                    126:                register char *p;
                    127:                for ( p = *argv; *p; p++ )
                    128:                        *p = tolower(*p);
                    129:        }
                    130:        
                    131: #ifdef DOSTATS
                    132:        statsexpr = (char *)strdup(*argv);
                    133:        onexit(dostats);
                    134: #endif
                    135:        compile(*argv);
                    136:        nfile = --argc;
                    137:        if (argc<=0) {
                    138:                scanexit = 1;
                    139:                execute("/dev/stdin");
                    140:        } else while (--argc >= 0) {
                    141:                argv++;
                    142:                scanexit = argc == 0;
                    143:                execute(*argv);
                    144:        }
                    145:        exit (retcode != 0 ? retcode : nsucc == 0);
                    146: }
                    147: 
                    148: compile(astr)
                    149: char *astr;
                    150: {
                    151:        register c;
                    152:        register char *ep, *sp;
                    153:        char *cstart;
                    154:        char *lastep;
                    155:        int cclcnt;
                    156:        char bracket[NBRA], *bracketp;
                    157:        char numbra;
                    158:        char neg;
                    159: 
                    160:        ep = expbuf;
                    161:        sp = astr;
                    162:        lastep = 0;
                    163:        bracketp = bracket;
                    164:        numbra = 0;
                    165:        if (*sp == '^') {
                    166:                circf++;
                    167:                sp++;
                    168:        }
                    169:        for (;;) {
                    170:                if (ep >= &expbuf[ESIZE])
                    171:                        goto cerror;
                    172:                if ((c = *sp++) != '*')
                    173:                        lastep = ep;
                    174:                switch (c) {
                    175: 
                    176:                case '\0':
                    177:                        *ep++ = CEOF;
                    178:                        return;
                    179: 
                    180:                case '.':
                    181:                        *ep++ = CDOT;
                    182:                        continue;
                    183: 
                    184:                case '*':
                    185:                        if (lastep==0 || *lastep==CBRA || *lastep==CKET)
                    186:                                goto defchar;
                    187:                        *lastep |= STAR;
                    188:                        continue;
                    189: 
                    190:                case '$':
                    191:                        if (*sp != '\0')
                    192:                                goto defchar;
                    193:                        *ep++ = CDOL;
                    194:                        continue;
                    195: 
                    196:                case '[':
                    197:                        if(&ep[17] >= &expbuf[ESIZE])
                    198:                                goto cerror;
                    199:                        *ep++ = CCL;
                    200:                        neg = 0;
                    201:                        if((c = *sp++) == '^') {
                    202:                                neg = 1;
                    203:                                c = *sp++;
                    204:                        }
                    205:                        cstart = sp;
                    206:                        do {
                    207:                                if (c=='\0')
                    208:                                        goto cerror;
                    209:                                if (c=='-' && sp>cstart && *sp!=']') {
                    210:                                        for (c = sp[-2]; c<*sp; c++)
                    211:                                                ep[c>>3] |= bittab[c&07];
                    212:                                        sp++;
                    213:                                }
                    214:                                ep[c>>3] |= bittab[c&07];
                    215:                        } while((c = *sp++) != ']');
                    216:                        if(neg) {
                    217:                                for(cclcnt = 0; cclcnt < 16; cclcnt++)
                    218:                                        ep[cclcnt] ^= -1;
                    219:                                ep[0] &= 0376;
                    220:                        }
                    221: 
                    222:                        ep += 16;
                    223: 
                    224:                        continue;
                    225: 
                    226:                case '\\':
                    227:                        if((c = *sp++) == '(') {
                    228:                                if(numbra >= NBRA) {
                    229:                                        goto cerror;
                    230:                                }
                    231:                                *bracketp++ = numbra;
                    232:                                *ep++ = CBRA;
                    233:                                *ep++ = numbra++;
                    234:                                continue;
                    235:                        }
                    236:                        if(c == ')') {
                    237:                                if(bracketp <= bracket) {
                    238:                                        goto cerror;
                    239:                                }
                    240:                                *ep++ = CKET;
                    241:                                *ep++ = *--bracketp;
                    242:                                continue;
                    243:                        }
                    244: 
                    245:                        if(c >= '1' && c <= '9') {
                    246:                                char *bp;
                    247:                                c -= '1';
                    248:                                if(c >= numbra)
                    249:                                        goto cerror;
                    250:                                for(bp=bracket; bp<bracketp; bp++)
                    251:                                        if(c == *bp)
                    252:                                                goto cerror;    
                    253:                                *ep++ = CBACK;
                    254:                                *ep++ = c;
                    255:                                continue;
                    256:                        }
                    257: 
                    258:                defchar:
                    259:                default:
                    260:                        *ep++ = CCHR;
                    261:                        *ep++ = c;
                    262:                }
                    263:        }
                    264:     cerror:
                    265:        errexit("grep: RE error\n", (char *)0);
                    266: }
                    267: 
                    268: execute(file)
                    269: char *file;
                    270: {
                    271:        register char *p1, *p2;
                    272:        register c;
                    273:        register fd;
                    274: 
                    275:        if ((fd = open(file, 0)) < 0) {
                    276:                Fprint(2, "grep: can't open %s\n", file);
                    277:                retcode = 2;
                    278:                return;
                    279:        }
                    280:        Finit(fd, (char *)0);
                    281:        Ftie(fd, 1);
                    282:        lnum = 0;
                    283:        tln = 0;
                    284:        for (;;) {
                    285:                if (tln && lflag) {
                    286:                        close(fd);
                    287:                        return;
                    288:                }
                    289:                lnum++;
                    290:                if((p1 = linebuf = Frdline(fd)) == 0) {
                    291:                        if (cflag) {
                    292:                                if (nfile>1)
                    293:                                        Fprint(1, "%s:", file);
                    294:                                Fprint(1, "%ld\n", tln);
                    295:                        }
                    296: #ifdef DOSTATS
                    297:                        nbytes += FIOSEEK(fd);
                    298:                        nlines += lnum-1;
                    299: #endif
                    300:                        close(fd);
                    301:                        return;
                    302:                }
                    303:                if (iflag) {
                    304:                        char *s = p1;
                    305:                        char *t = ybuf;
                    306:                        do {
                    307:                                *t++ = tolower(*s);
                    308:                        } while (*s++);
                    309:                        p1 = ybuf;
                    310:                }
                    311:                p2 = expbuf;
                    312:                if (circf) {
                    313:                        if (advance(p1, p2))
                    314:                                goto found;
                    315:                        goto nfound;
                    316:                }
                    317:                /* fast check for first character */
                    318:                if (*p2==CCHR) {
                    319:                        c = p2[1];
                    320:                        do {
                    321:                                if (*p1!=c)
                    322:                                        continue;
                    323:                                if (advance(p1, p2))
                    324:                                        goto found;
                    325:                        } while (*p1++);
                    326:                        goto nfound;
                    327:                }
                    328:                /* regular algorithm */
                    329:                do {
                    330:                        if (advance(p1, p2))
                    331:                                goto found;
                    332:                } while (*p1++);
                    333:        nfound:
                    334:                if (vflag)
                    335:                        succeed(file, fd);
                    336:                continue;
                    337:        found:
                    338:                if (vflag==0)
                    339:                        succeed(file, fd);
                    340:        }
                    341: }
                    342: 
                    343: advance(lp, ep)
                    344: register char *lp, *ep;
                    345: {
                    346:        register char *curlp;
                    347:        char c;
                    348:        char *bbeg;
                    349:        int ct;
                    350: 
                    351: #ifdef DOSTATS
                    352:        if(++ndepth > nmaxdepth) nmaxdepth = ndepth;
                    353: #endif
                    354:        for (;;) switch (*ep++) {
                    355: 
                    356:        case CCHR:
                    357:                if (*ep++ == *lp++)
                    358:                        continue;
                    359: #ifdef DOSTATS
                    360:                ndepth--;
                    361: #endif
                    362:                return(0);
                    363: 
                    364:        case CDOT:
                    365:                if (*lp++)
                    366:                        continue;
                    367: #ifdef DOSTATS
                    368:                ndepth--;
                    369: #endif
                    370:                return(0);
                    371: 
                    372:        case CDOL:
                    373:                if (*lp==0)
                    374:                        continue;
                    375: #ifdef DOSTATS
                    376:                ndepth--;
                    377: #endif
                    378:                return(0);
                    379: 
                    380:        case CEOF:
                    381: #ifdef DOSTATS
                    382:                ndepth--;
                    383: #endif
                    384:                return(1);
                    385: 
                    386:        case CCL:
                    387:                c = *lp++ & 0177;
                    388:                if(ep[c>>3] & bittab[c & 07]) {
                    389:                        ep += 16;
                    390:                        continue;
                    391:                }
                    392: #ifdef DOSTATS
                    393:                ndepth--;
                    394: #endif
                    395:                return(0);
                    396:        case CBRA:
                    397:                braslist[*ep++] = lp;
                    398:                continue;
                    399: 
                    400:        case CKET:
                    401:                braelist[*ep++] = lp;
                    402:                continue;
                    403: 
                    404:        case CBACK:
                    405:                bbeg = braslist[*ep];
                    406:                if (braelist[*ep]==0){
                    407: #ifdef DOSTATS
                    408:                        ndepth--;
                    409: #endif
                    410:                        return(0);
                    411:                }
                    412:                ct = braelist[*ep++] - bbeg;
                    413:                if(ecmp(bbeg, lp, ct)) {
                    414:                        lp += ct;
                    415:                        continue;
                    416:                }
                    417: #ifdef DOSTATS
                    418:                ndepth--;
                    419: #endif
                    420:                return(0);
                    421: 
                    422:        case CBACK|STAR:
                    423:                bbeg = braslist[*ep];
                    424:                if (braelist[*ep]==0){
                    425: #ifdef DOSTATS
                    426:                        ndepth--;
                    427: #endif
                    428:                        return(0);
                    429:                }
                    430:                ct = braelist[*ep++] - bbeg;
                    431:                curlp = lp;
                    432:                while(ecmp(bbeg, lp, ct))
                    433:                        lp += ct;
                    434:                while(lp >= curlp) {
                    435:                        if(advance(lp, ep)){
                    436: #ifdef DOSTATS
                    437:                                ndepth--;
                    438: #endif
                    439:                                return(1);
                    440:                        }
                    441:                        lp -= ct;
                    442:                }
                    443: #ifdef DOSTATS
                    444:                ndepth--;
                    445: #endif
                    446:                return(0);
                    447: 
                    448: 
                    449:        case CDOT|STAR:
                    450:                curlp = lp;
                    451:                while (*lp++);
                    452:                goto star;
                    453: 
                    454:        case CCHR|STAR:
                    455:                curlp = lp;
                    456:                while (*lp++ == *ep);
                    457:                ep++;
                    458:                goto star;
                    459: 
                    460:        case CCL|STAR:
                    461:                curlp = lp;
                    462:                do {
                    463:                        c = *lp++ & 0177;
                    464:                } while(ep[c>>3] & bittab[c & 07]);
                    465:                ep += 16;
                    466:                goto star;
                    467: 
                    468:        star:
                    469:                if(--lp == curlp) {
                    470:                        continue;
                    471:                }
                    472: 
                    473:                if(*ep == CCHR) {
                    474:                        c = ep[1];
                    475:                        do {
                    476:                                if(*lp != c)
                    477:                                        continue;
                    478:                                if(advance(lp, ep)){
                    479: #ifdef DOSTATS
                    480:                                        ndepth--;
                    481: #endif
                    482:                                        return(1);
                    483:                                }
                    484:                        } while(lp-- > curlp);
                    485: #ifdef DOSTATS
                    486:                        ndepth--;
                    487: #endif
                    488:                        return(0);
                    489:                }
                    490: 
                    491:                do {
                    492:                        if (advance(lp, ep)){
                    493: #ifdef DOSTATS
                    494:                                ndepth--;
                    495: #endif
                    496:                                return(1);
                    497:                        }
                    498:                } while (lp-- > curlp);
                    499: #ifdef DOSTATS
                    500:                ndepth--;
                    501: #endif
                    502:                return(0);
                    503: 
                    504:        default:
                    505:                errexit("grep RE botch\n", (char *)0);
                    506:        }
                    507: }
                    508: 
                    509: succeed(f, fd)
                    510: char *f;
                    511: int fd;
                    512: {
                    513: 
                    514:        nsucc = 1;
                    515:        if (sflag){
                    516:                if(scanexit) exit(0);
                    517:                return;
                    518:        }
                    519:        if (cflag) {
                    520:                tln++;
                    521:                return;
                    522:        }
                    523:        if (lflag) {
                    524:                Fprint(1, "%s\n", f);
                    525:                tln++;
                    526:                return;
                    527:        }
                    528:        if (nfile > 1 && hflag)
                    529:                Fprint(1, "%s:", f);
                    530:        if (bflag)
                    531:                Fprint(1, "%ld:", (FIOSEEK(fd)-FIOLINELEN(fd)-1)/1024);
                    532:        if (nflag)
                    533:                Fprint(1, "%ld:", lnum);
                    534:        {
                    535:                register x = FIOLINELEN(fd);
                    536:                linebuf[x] = '\n';
                    537:                Fwrite(1, linebuf, x+1);
                    538:        }
                    539: }
                    540: 
                    541: ecmp(a, b, count)
                    542: char   *a, *b;
                    543: {
                    544:        register cc = count;
                    545:        while(cc--)
                    546:                if(*a++ != *b++)        return(0);
                    547:        return(1);
                    548: }
                    549: 
                    550: errexit(s, f)
                    551: char *s, *f;
                    552: {
                    553:        Fprint(2, s, f);
                    554:        exit(2);
                    555: }
                    556: 
                    557: #ifdef DOSTATS
                    558: #include       <errno.h>
                    559: #define                NAME            "/tmp/grepdata"
                    560: dostats()
                    561: {
                    562:        int mailfd;
                    563: 
                    564:        umask(0);
                    565:        mailfd = open(NAME, 1);
                    566:        if((mailfd < 0) && (errno != ECONC)){
                    567:                umask(0);
                    568:                mailfd = creat(NAME, 03666);
                    569:        }
                    570:        if(mailfd >= 0){
                    571:                Finit(mailfd, (char *)0);
                    572:                Fseek(mailfd, 0L, 2);
                    573:                *statsfptr = 0;
                    574:                Fprint(mailfd, "\321grep:%s:%d:%d:%d: %s\n", statsflags, nlines, nbytes, nmaxdepth, statsexpr);
                    575:                Fflush(mailfd);
                    576:                close(mailfd);
                    577:        }
                    578: }
                    579: #endif

unix.superglobalmegacorp.com

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