Annotation of coherent/d/bin/egrep.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * egrep --  pattern matcher
        !             3:  *
        !             4:  *     Lines of input are searched for the user-supplied extended
        !             5:  * regular expression.  Command line options determine what "egrep"
        !             6:  * does on a match: usually the line is printed.  Lines over BUFSIZ
        !             7:  * chars in length may be fatal when read from pipes or raw devices.
        !             8:  *     The implementation goal is speed and, to this end, a DFA is
        !             9:  * employed.  Two key strategies reduce the time spent constructing
        !            10:  * the DFA by a factor of 100, in typical cases:  (1) the use of
        !            11:  * equivalence classes, (2) construction of the DFA dynamically.
        !            12:  * These strategies win because of the way "egrep" tends to be used.
        !            13:  * Most patterns use only 10-20 characters in the ASCII set of 128.
        !            14:  * Most input exercises only 10% of the total possible transitions
        !            15:  * (so why compute the remaining 90%?).  As a side benefit, these
        !            16:  * strategies reduce "egrep"'s gigantic appetite for memory to merely
        !            17:  * huge.  Strategy (2) has the important psychological effect of making
        !            18:  * "egrep" appear to start running instantly; the inevitable time spent
        !            19:  * constructing the DFA is amortized over the running time of the
        !            20:  * program.
        !            21:  */
        !            22: #include       <stdio.h>
        !            23: #include       <ctype.h>
        !            24: #ifdef COHERENT
        !            25: #include       <access.h>
        !            26: #else
        !            27: #define DOS 1
        !            28: #endif
        !            29: 
        !            30: /*
        !            31: ** rico.h
        !            32: */
        !            33: #define        bool    char
        !            34: #define        TRUE    1
        !            35: #define        FALSE   0
        !            36: 
        !            37: /*
        !            38: ** egrep.h
        !            39: */
        !            40: /*
        !            41:  * bit diddling
        !            42:  */
        !            43: #define        NCHARS  128             /* chars in ASCII set */
        !            44: #define        NBCHAR  8               /* bits per char */
        !            45: 
        !            46: #define        bitset(c, p)    ((p)[(c)>>3] |= bitmask[(c)&7])
        !            47: #define        bitclr(c, p)    ((p)[(c)>>3] &= ~bitmask[(c)&7])
        !            48: #define        bitcom(c, p)    ((p)[(c)>>3] ^= bitmask[(c)&7])
        !            49: #define        bittst(c, p)    ((p)[(c)>>3] & bitmask[(c)&7])
        !            50: 
        !            51: /*
        !            52:  * support for bitmaps
        !            53:  */
        !            54: readonly char bitmask[] = {
        !            55:        0001, 0002, 0004, 0010, 0020, 0040, 0100, 0200
        !            56: };
        !            57: 
        !            58: 
        !            59: extern char    *newbits();
        !            60: 
        !            61: /*
        !            62: ** dragon.h
        !            63: */
        !            64: /*
        !            65:  * DFA state
        !            66:  *     The egrep DFA is composed of these structs.  Operation of the DFA
        !            67:  * requires the use of d_success and d_p, only.
        !            68:  */
        !            69: struct dragon {
        !            70:        bool            d_success;      /* this is an accepting state */
        !            71:        struct newt     **d_s;          /* set of NFA states (newts) */
        !            72:        char            *d_b;           /* bitmap of d_s */
        !            73:        int             d_hash;         /* hash of d_s */
        !            74:        struct dragon   *d_next;        /* next dragon (or 0) */
        !            75:        struct dragon   *d_last;        /* previous dragon (or 0) */
        !            76:        struct dragon   **d_p;          /* transition vector */
        !            77: };
        !            78: 
        !            79: /*
        !            80: ** newt.h
        !            81: */
        !            82: /*
        !            83:  * NFA state
        !            84:  *     The rex is converted into an NFA composed of these structs.
        !            85:  */
        !            86: struct newt {
        !            87:        char            n_c;            /* label for transition n_cp */
        !            88:        char            n_flags;        /* [see below] */
        !            89:        int             n_uniq;         /* unique # */
        !            90:        int             n_id;           /* ID # of this newt */
        !            91:        char            *n_b;           /* alternative label (char class) */
        !            92:        struct newt     *n_cp;          /* transition labeled n_c */
        !            93:        struct newt     *n_ep;          /* transition labeled EPSILON */
        !            94:        struct newt     *n_fp;          /* final newt in this sub-goal */
        !            95: };
        !            96: 
        !            97: /* n_c
        !            98:  */
        !            99: #define        EPSILON (-1)                    /* n_cp is an epsilon transition */
        !           100: 
        !           101: /* n_flags
        !           102:  */
        !           103: #define        N_BOL   01              /* beginning-of-line */
        !           104: #define        N_EOL   02              /* end-of-line */
        !           105: 
        !           106: /*
        !           107: ** equiv.c
        !           108: */
        !           109: /*
        !           110:  * equivalence class
        !           111:  *     The set of ASCII chars is refined by the sets of chars used by
        !           112:  * the regular expression.  The result is a set of equivalence classes:
        !           113:  * disjoint sets of chars, whose union is the ASCII set.
        !           114:  *     An eclass struct describes one equivalence class.  The structs
        !           115:  * are linked, and headed by `eclasses'.
        !           116:  */
        !           117: struct eclass {
        !           118:        char            e_c;            /* used if only one char in set */
        !           119:        char            e_class;        /* ID # of this eclass */
        !           120:        char            *e_b;           /* used if many chars in set */
        !           121:        struct eclass   *e_next;        /* next eclass (or 0) */
        !           122: };
        !           123: 
        !           124: bool   aflag;          /* use emacs after file with hit */
        !           125: bool   eflag;          /* next arg is regular expression */
        !           126: bool   fflag;          /* next arg is file containing rex */
        !           127: bool   vflag;          /* line matches if rex NOT found */
        !           128: bool   cflag;          /* only print # matches */
        !           129: bool   lflag;          /* only print name of files that match */
        !           130: bool   nflag;          /* also print line # */
        !           131: bool   bflag;          /* also print block # */
        !           132: bool   sflag;          /* only provide exit status */
        !           133: bool   hflag;          /* do not print file names */
        !           134: bool   yflag;          /* lower case also matches upper case input */
        !           135: 
        !           136: int    uniq,   n_id,   n_ec;
        !           137: 
        !           138: FILE   *ifp;           /* input */
        !           139: FILE   *tmpFile;       /* tmp file for use with emacs */
        !           140: char   *tmpFn = NULL;  /* tmp file name */
        !           141: /*
        !           142:  * egrep
        !           143:  *     Return 0 if any matches found in the input files, else 1.
        !           144:  */
        !           145: main(argc, argv)
        !           146: char   **argv;
        !           147: {
        !           148:        register struct newt    *np;
        !           149:        register struct dragon  *dp;
        !           150:        struct newt             *makenfa();
        !           151:        struct newt             *npolish();
        !           152:        struct dragon           *initdfa();
        !           153:        int     status;
        !           154:        char    **init();
        !           155:        bool    search();
        !           156: 
        !           157: #ifdef MSDOS
        !           158:        msdoscvt("egrep", &argc, &argv);
        !           159: #endif
        !           160:        argv = init(argc, argv );
        !           161: #ifdef MSDOS
        !           162:        /*
        !           163:         * On systems which distinguish between ASCII and binary streams,
        !           164:         * egrep reads its input as a binary stream, so it can be used to
        !           165:         * look for a string in an object file (for example).  It also
        !           166:         * writes its output as a binary stream in most cases, so for ASCII
        !           167:         * input files newline mapping happens neither on input nor on output.
        !           168:         * However, "-c" and "-l" require ASCII output for newline mapping.
        !           169:         * Kludgy; one alternative is to have it read and write ASCII streams,
        !           170:         * forget about egrep'ing object files, and futz the seek count when
        !           171:         * it sees a newline in the input.
        !           172:         */
        !           173:        if (!cflag && !lflag)
        !           174:                _setbinary(stdout);
        !           175: #endif
        !           176: 
        !           177:        np = makenfa();
        !           178:        ncheck(initdfa(np)->d_s);
        !           179:        np = npolish(np);
        !           180:        dp = initdfa(np);
        !           181: 
        !           182:        status = 1;
        !           183: 
        !           184:        if (*argv)
        !           185:                do {
        !           186:                        if ((ifp = fopen(*argv, "rb")) == NULL) {
        !           187:                                fprintf(stderr, 
        !           188:                                   "egrep: can't open %s\n", *argv);
        !           189:                                continue;
        !           190:                        }
        !           191:                        if (search(*argv, dp, np))
        !           192:                                status = 0;
        !           193:                        fclose(ifp);
        !           194:                        if (aflag && (NULL != tmpFn))
        !           195:                                emacs(*argv);
        !           196:                } while (*++argv);
        !           197:        else {
        !           198:                ifp = stdin;
        !           199: #ifdef MSDOS
        !           200:                _setbinary(ifp);
        !           201: #endif
        !           202:                if (search("(stdin)", dp, np))
        !           203:                        status = 0;
        !           204:        }
        !           205: 
        !           206:        return (status);
        !           207: }
        !           208: 
        !           209: /*
        !           210:  * initialization
        !           211:  *     Process command line.  Return `argv' pointing to first file arg.
        !           212:  */
        !           213: static char    **
        !           214: init(argc, argv)
        !           215: char   **argv;
        !           216: {
        !           217:        register char   **av;
        !           218:        register char   *a;
        !           219:        register bool   gotrex;
        !           220:        extern char     *regexp;
        !           221:        extern FILE     *rexf;
        !           222: 
        !           223:        gotrex = FALSE;
        !           224:        av = &argv[1];
        !           225: 
        !           226:        while (a = *av++) {
        !           227:                if (*a != '-') {
        !           228:                        if (! gotrex) {
        !           229:                                gotrex = TRUE;
        !           230:                                regexp = a;
        !           231:                                a = *av++;
        !           232:                        }
        !           233:                        break;
        !           234:                }
        !           235:                while (*++a)
        !           236:                        switch (*a) {
        !           237:                        case 'A':
        !           238:                                aflag = TRUE;
        !           239:                                break;
        !           240:                        case 'e':
        !           241:                                if (gotrex)
        !           242:                                        onlyone();
        !           243:                                if (*av == NULL)
        !           244:                                        fatal("missing arg to -e");
        !           245:                                regexp = *av++;
        !           246:                                gotrex = TRUE;
        !           247:                                break;
        !           248:                        case 'f':
        !           249:                                if (gotrex)
        !           250:                                        onlyone();
        !           251:                                if (*av == NULL)
        !           252:                                        fatal("missing arg to -f");
        !           253:                                rexf = fopen(*av, "r");
        !           254:                                if (rexf == NULL)
        !           255:                                        fatal("can't open %s", *av);
        !           256:                                ++av;
        !           257:                                gotrex = TRUE;
        !           258:                                break;
        !           259:                        case 'v':
        !           260:                                vflag = TRUE;
        !           261:                                break;
        !           262:                        case 'c':
        !           263:                                cflag = TRUE;
        !           264:                                break;
        !           265:                        case 'l':
        !           266:                                lflag = TRUE;
        !           267:                                break;
        !           268:                        case 'n':
        !           269:                                nflag = TRUE;
        !           270:                                break;
        !           271:                        case 'b':
        !           272:                                bflag = TRUE;
        !           273:                                break;
        !           274:                        case 's':
        !           275:                                sflag = TRUE;
        !           276:                                break;
        !           277:                        case 'h':
        !           278:                                hflag = TRUE;
        !           279:                                break;
        !           280:                        case 'y':
        !           281:                        case 'i':
        !           282:                                yflag = TRUE;
        !           283:                                break;
        !           284:                        default:
        !           285:                                fatal("no such flag -%c", *a);
        !           286:                        }
        !           287:        }
        !           288: 
        !           289:        if (! gotrex) {
        !           290:                fprintf(stderr,
        !           291:                    "Usage: egrep [ -bcefhlnsvy ] pattern [ file ...]\n");
        !           292:                exit(2);
        !           293:        }
        !           294: 
        !           295:        --av;
        !           296:        if (argc-(av-argv) <= 1)
        !           297:                hflag = TRUE;
        !           298:        return (av);
        !           299: }
        !           300: 
        !           301: /*
        !           302:  * call emacs with tmpfile.
        !           303:  */
        !           304: emacs(arg)
        !           305: char *arg;
        !           306: {
        !           307: #ifdef GEMDOS
        !           308: #include <path.h>
        !           309:        extern  char *path(), *getenv();
        !           310:        extern char **environ;
        !           311:        static char* cmda[5] = { NULL, "-e", NULL, NULL, NULL };
        !           312: #endif
        !           313: #ifdef MSDOS
        !           314:        char line[BUFSIZ];
        !           315: #endif
        !           316: #ifdef COHERENT
        !           317:        char line[BUFSIZ];
        !           318: #endif
        !           319:        int quit;
        !           320: 
        !           321:        fclose(tmpFile);
        !           322: #ifdef MSDOS
        !           323:        sprintf(line, "-e %s %s", tmpFn, arg);
        !           324:        if (0x7f == (quit = execall("me", line)))
        !           325: #endif
        !           326: #ifdef COHERENT
        !           327:        sprintf(line, "me -e %s %s ", tmpFn, arg);
        !           328:        if (0x7f == (quit = system(line)))
        !           329: #endif
        !           330: #ifdef GEMDOS
        !           331:        cmda[2] = tmpFn;
        !           332:        cmda[3] = arg;
        !           333:        if ((NULL == cmda[0]) &&
        !           334:           (NULL == (cmda[0] = path(getenv("PATH"), "me.tos", 1)))) {
        !           335:                fprintf(stderr, "egrep: Cannot locate me.tos\n");
        !           336:                quit = 1;
        !           337:        }
        !           338:        else if ((quit = execve(cmda[0], cmda, environ)) < 0)
        !           339: #endif
        !           340:                fprintf(stderr, "egrep: cannot execute 'me'");
        !           341:        unlink(tmpFn);
        !           342:        free(tmpFn);
        !           343:        tmpFn = NULL;
        !           344:        if (quit)
        !           345:                exit(0);
        !           346: }
        !           347: 
        !           348: static
        !           349: onlyone()
        !           350: {
        !           351:        fatal("exactly one pattern required");
        !           352: }
        !           353: 
        !           354: 
        !           355: nomem()
        !           356: {
        !           357: 
        !           358:        fatal("out of mem");
        !           359: }
        !           360: 
        !           361: 
        !           362: /*
        !           363:  * fatal error
        !           364:  */
        !           365: fatal(arg0)
        !           366: char   *arg0;
        !           367: {
        !           368:        fflush(stdout);
        !           369:        fprintf(stderr, "egrep: %r\n", &arg0);
        !           370:        exit(2);
        !           371: }
        !           372: 
        !           373: /*
        !           374: ** nfa.c
        !           375: */
        !           376: 
        !           377: 
        !           378: /*
        !           379:  * creation of the NFA
        !           380:  */
        !           381: 
        !           382: 
        !           383: /* only one is set by init()
        !           384:  */
        !           385: char   *regexp;                /* user's regular expression */
        !           386: FILE   *rexf;                  /* file containing user's rex */
        !           387: 
        !           388: 
        !           389: static curc;                   /* current char from rex */
        !           390: 
        !           391: struct newt    *getrex();
        !           392: struct newt    *getterm();
        !           393: struct newt    *getfac();
        !           394: struct newt    *getatom();
        !           395: struct newt    *newnewt();
        !           396: 
        !           397: 
        !           398: /*
        !           399:  * create NFA from rex
        !           400:  *     A pointer to the NFA is returned.
        !           401:  */
        !           402: struct newt    *makenfa()
        !           403: {
        !           404:        register struct newt    *p;
        !           405: 
        !           406:        advance();
        !           407:        p = getrex();
        !           408:        if (curc)
        !           409:                misplaced(curc);
        !           410:        if (p == NULL)
        !           411:                fatal("empty pattern");
        !           412:        return (p);
        !           413: }
        !           414: 
        !           415: 
        !           416: /*
        !           417:  * check NFA semantics
        !           418:  *     Ensure correct usage of '^' and '$'.
        !           419:  */
        !           420: ncheck(npp)
        !           421: register struct newt   **npp;
        !           422: {
        !           423:        register struct newt    *np;
        !           424: 
        !           425:        ++uniq;
        !           426: 
        !           427:        while (np = *npp++)
        !           428:                if (np->n_cp && np->n_c!=EPSILON) {
        !           429:                        if (np->n_flags & N_EOL)
        !           430:                                nbeeline(np);
        !           431:                        nwalk(np->n_cp);
        !           432:                }
        !           433: }
        !           434: 
        !           435: 
        !           436: /*
        !           437:  * add finishing touch to NFA
        !           438:  *     Prepend a sort of ".*" to the front of the NFA.
        !           439:  */
        !           440: struct newt    *npolish(np)
        !           441: register struct newt   *np;
        !           442: {
        !           443:        register struct newt    *p;
        !           444: 
        !           445:        p = newnewt();
        !           446:        p->n_b = newbits(TRUE);
        !           447:        p->n_cp = newnewt();
        !           448:        p->n_cp->n_c = EPSILON;
        !           449:        p->n_cp->n_cp = p;
        !           450:        p->n_ep = np;
        !           451:        p->n_fp = np->n_fp;
        !           452:        return (p);
        !           453: }
        !           454: 
        !           455: 
        !           456: /*
        !           457:  * get regular expression
        !           458:  *     A trailing '\n' is tolerated, to accommodate the "-f" option.
        !           459:  */
        !           460: static struct newt     *getrex()
        !           461: {
        !           462:        register struct newt    *p;
        !           463:        register struct newt    *q;
        !           464:        register struct newt    *start;
        !           465:        struct newt *final;
        !           466: 
        !           467:        start = getterm();
        !           468:        if (start == NULL)
        !           469:                return (start);
        !           470:        final = newnewt();
        !           471:        start->n_fp->n_c = EPSILON;
        !           472:        start->n_fp->n_cp = final;
        !           473:        start->n_fp = final;
        !           474: 
        !           475:        for (; ; ) {
        !           476:                switch (curc) {
        !           477:                case '|':
        !           478:                        advance();
        !           479:                        if (p = getterm())
        !           480:                                break;
        !           481:                        misplaced('|');
        !           482:                case '\n':
        !           483:                        advance();
        !           484:                        if (p = getterm())
        !           485:                                break;
        !           486:                        if (curc != '\0')
        !           487:                                misplaced('\n');
        !           488:                default:
        !           489:                        return (start);
        !           490:                }
        !           491:                p->n_fp->n_c = EPSILON;
        !           492:                p->n_fp->n_cp = final;
        !           493:                q = newnewt();
        !           494:                q->n_c = EPSILON;
        !           495:                q->n_cp = p;
        !           496:                q->n_ep = start;
        !           497:                q->n_fp = final;
        !           498:                start = q;
        !           499:        }
        !           500: }
        !           501: 
        !           502: 
        !           503: /*
        !           504:  * get term
        !           505:  */
        !           506: static struct newt     *
        !           507: getterm()
        !           508: {
        !           509:        register struct newt    *start;
        !           510:        register struct newt    *p;
        !           511: 
        !           512:        start = getfac();
        !           513:        if (start == NULL)
        !           514:                return (start);
        !           515: 
        !           516:        while (p = getfac()) {
        !           517:                start->n_fp->n_c = EPSILON;
        !           518:                start->n_fp->n_cp = p;
        !           519:                start->n_fp = p->n_fp;
        !           520:        }
        !           521: 
        !           522:        return (start);
        !           523: }
        !           524: 
        !           525: 
        !           526: /*
        !           527:  * get factor
        !           528:  */
        !           529: static struct newt *getfac()
        !           530: {
        !           531:        register struct newt    *p;
        !           532:        register struct newt    *q;
        !           533:        register struct newt    *start;
        !           534: 
        !           535:        start = getatom();
        !           536:        if (start == NULL)
        !           537:                return (start);
        !           538:        p = start;
        !           539: 
        !           540:        if (curc == '*') {
        !           541:                advance();
        !           542:                start = newnewt();
        !           543:                q = newnewt();
        !           544:                start->n_c = EPSILON;
        !           545:                start->n_cp = p;
        !           546:                start->n_ep = q;
        !           547:                p->n_fp->n_c = EPSILON;
        !           548:                p->n_fp->n_cp = q;
        !           549:                p->n_fp->n_ep = p;
        !           550:                start->n_fp = q;
        !           551:        }
        !           552:        else if (curc == '+') {
        !           553:                advance();
        !           554:                q = newnewt();
        !           555:                p->n_fp->n_c = EPSILON;
        !           556:                p->n_fp->n_cp = q;
        !           557:                p->n_fp->n_ep = p;
        !           558:                start->n_fp = q;
        !           559:        }
        !           560:        else if (curc == '?') {
        !           561:                advance();
        !           562:                start = newnewt();
        !           563:                start->n_c = EPSILON;
        !           564:                start->n_cp = p;
        !           565:                start->n_ep = p->n_fp;
        !           566:                start->n_fp = p->n_fp;
        !           567:        }
        !           568:        return (start);
        !           569: }
        !           570: 
        !           571: 
        !           572: /*
        !           573:  * get atom
        !           574:  *     The interpretation of the "-y" option is given by this example:
        !           575:  *             egrep -y 'R\i\c\o H[a-z]* Tudor'
        !           576:  * means
        !           577:  *             egrep 'Rico H[A-Za-z]* T[Uu][Dd][Oo][Rr]'
        !           578:  */
        !           579: static struct newt *getatom()
        !           580: {
        !           581:        register struct newt    *start;
        !           582:        char                    *charclass();
        !           583: 
        !           584:        start = newnewt();
        !           585:        start->n_cp = newnewt();
        !           586:        start->n_fp = start->n_cp;
        !           587: 
        !           588:        switch (curc) {
        !           589:        case '\0':
        !           590:        case '\n':
        !           591:        case '|':
        !           592:        case '*':
        !           593:        case ')':
        !           594:        case ']':
        !           595:        case '+':
        !           596:        case '?':
        !           597:                nonewts(start);
        !           598:                return (0);
        !           599:        case '.':
        !           600:                start->n_b = newbits(TRUE);
        !           601:                bitclr('\n', start->n_b);
        !           602:                equiv(start);
        !           603:                break;
        !           604:        case '^':
        !           605:                start->n_flags |= N_BOL;
        !           606:                start->n_c = '\n';
        !           607:                equiv(start);
        !           608:                break;
        !           609:        case '$':
        !           610:                start->n_flags |= N_EOL;
        !           611: #if DOS
        !           612:                start->n_c = '\r';
        !           613: #else
        !           614:                start->n_c = '\n';
        !           615: #endif
        !           616:                equiv(start);
        !           617:                break;
        !           618:        case '[':
        !           619:                advance();
        !           620:                start->n_b = charclass();
        !           621:                equiv(start);
        !           622:                break;
        !           623:        case '(':
        !           624:                advance();
        !           625:                nonewts(start);
        !           626:                start = getrex();
        !           627:                if (curc == '\0')
        !           628:                        fatal("missing ')'");
        !           629:                if ((start == NULL) || curc!=')')
        !           630:                        misplaced(curc);
        !           631:                break;
        !           632:        case '\\':
        !           633:                advance();
        !           634:                if (curc=='\0' || curc=='\n')
        !           635:                        misplaced('\\');
        !           636:                start->n_c = curc;
        !           637:                equiv(start);
        !           638:                break;
        !           639:        default:
        !           640:                if (yflag && islower(curc)) {
        !           641:                        start->n_b = newbits(FALSE);
        !           642:                        bitset(curc, start->n_b);
        !           643:                        bitset(toupper(curc), start->n_b);
        !           644:                }
        !           645:                else
        !           646:                        start->n_c = curc;
        !           647:                equiv(start);
        !           648:        }
        !           649:        advance();
        !           650: 
        !           651:        return (start);
        !           652: }
        !           653: 
        !           654: 
        !           655: static char *charclass()
        !           656: {
        !           657:        register char   *p;
        !           658:        register        c;
        !           659:        register bool   compl;
        !           660: 
        !           661:        compl = FALSE;
        !           662:        p = newbits(FALSE);
        !           663:        if (curc == '^') {
        !           664:                compl = TRUE;
        !           665:                advance();
        !           666:        }
        !           667:        if (curc == '\0')
        !           668:                badclass();
        !           669: 
        !           670:        do {
        !           671:                c = curc;
        !           672:                advance();
        !           673:                if (c == '\0')
        !           674:                        badclass();
        !           675:                if (curc == '-') {
        !           676:                        advance();
        !           677:                        if (curc == '\0')
        !           678:                                badclass();
        !           679:                        if (curc == ']') {
        !           680:                                bitset('-', p);
        !           681:                                bitset(c, p);
        !           682:                        }
        !           683:                        else if (c > curc)
        !           684:                                fatal("bad char class range %c-%c", c, curc);
        !           685:                        else {
        !           686:                                do {
        !           687:                                        bitset(c, p);
        !           688:                                } while (++c <= curc);
        !           689:                                advance();
        !           690:                        }
        !           691:                }
        !           692:                else
        !           693:                        bitset(c, p);
        !           694:        } while (curc != ']');
        !           695: 
        !           696:        if (bittst('\n', p))
        !           697:                misplaced('\n');
        !           698:        if (yflag)
        !           699:                for (c='a'; c<='z'; ++c)
        !           700:                        if (bittst(c, p))
        !           701:                                bitset(toupper(c), p);
        !           702:        if (compl) {
        !           703:                for (c=0; c<NCHARS; ++c)
        !           704:                        bitcom(c, p);
        !           705:                bitclr('\n', p);
        !           706:        }
        !           707:        return (p);
        !           708: }
        !           709: 
        !           710: 
        !           711: /*
        !           712:  * allocate new newt struct
        !           713:  */
        !           714: static struct newt *newnewt()
        !           715: {
        !           716:        register struct newt    *p;
        !           717: 
        !           718:        p = malloc(sizeof *p);
        !           719:        if (p == NULL)
        !           720:                nomem();
        !           721:        p->n_c = 0;
        !           722:        p->n_flags = 0;
        !           723:        p->n_b = NULL;
        !           724:        p->n_cp = NULL;
        !           725:        p->n_ep = NULL;
        !           726:        p->n_fp = NULL;
        !           727:        p->n_uniq = 0;
        !           728:        p->n_id = n_id++;
        !           729: 
        !           730:        return (p);
        !           731: }
        !           732: 
        !           733: 
        !           734: /*
        !           735:  * free newt structs
        !           736:  *     Used to free unused atoms.
        !           737:  */
        !           738: static nonewts(np)
        !           739: struct newt    *np;
        !           740: {
        !           741: 
        !           742:        free((char *)np->n_cp);
        !           743:        free((char *)np);
        !           744:        n_id -= 2;
        !           745: }
        !           746: 
        !           747: 
        !           748: /*
        !           749:  * get next char from rex
        !           750:  *     The next char from the file or the string is placed in `curc'.
        !           751:  */
        !           752: static advance()
        !           753: {
        !           754:        register        c;
        !           755: 
        !           756:        if (regexp)
        !           757:                c = *regexp++;
        !           758:        else {
        !           759:                c = getc(rexf);
        !           760:                if (c == EOF)
        !           761:                        c = '\0';
        !           762:        }
        !           763:        curc = c & 0177;
        !           764: }
        !           765: 
        !           766: 
        !           767: /*
        !           768:  * report misplaced '^'
        !           769:  */
        !           770: static nwalk(np)
        !           771: register struct newt   *np;
        !           772: {
        !           773: 
        !           774:        while (np->n_cp) {
        !           775:                if (np->n_uniq == uniq)
        !           776:                        return;
        !           777:                np->n_uniq = uniq;
        !           778:                if (np->n_flags & N_EOL)
        !           779:                        nbeeline(np);
        !           780:                if (np->n_flags & N_BOL)
        !           781:                        misplaced('^');
        !           782:                if (np->n_ep)
        !           783:                        nwalk(np->n_ep);
        !           784:                np = np->n_cp;
        !           785:        }
        !           786: }
        !           787: 
        !           788: 
        !           789: /*
        !           790:  * report misplaced '$'
        !           791:  */
        !           792: static nbeeline(np)
        !           793: register struct newt   *np;
        !           794: {
        !           795: 
        !           796:        while (np = np->n_cp) {
        !           797:                if ((np->n_cp && np->n_c!=EPSILON)
        !           798:                || (np->n_ep))
        !           799:                        misplaced('$');
        !           800:        }
        !           801: }
        !           802: 
        !           803: 
        !           804: static misplaced(c)
        !           805: {
        !           806:        static char     s[]     = "`c'";
        !           807: 
        !           808:        s[1] = c;
        !           809:        fatal("misplaced %s in pattern", c=='\n'? "newline": s);
        !           810: }
        !           811: 
        !           812: 
        !           813: static badclass()
        !           814: {
        !           815: 
        !           816:        fatal("non-terminated char class");
        !           817: }
        !           818: /*
        !           819: ** equiv.c
        !           820: */
        !           821: 
        !           822: 
        !           823: /*
        !           824:  * equivalence classes
        !           825:  */
        !           826: 
        !           827: 
        !           828: char           etab[NCHARS];           /* map ASCII to eclass # */
        !           829: struct eclass  *eclasses;              /* head of eclass list */
        !           830: 
        !           831: bool           intersect();
        !           832: struct eclass  *neweclass();
        !           833: 
        !           834: 
        !           835: /*
        !           836:  * check equivalence
        !           837:  *     A set of eclasses must exist such that their union equals the
        !           838:  * chars in `np'.  If not, the equivalence relation must be "refined".
        !           839:  */
        !           840: equiv(np)
        !           841: register struct newt   *np;
        !           842: {
        !           843:        register struct eclass  *ep;
        !           844:        register struct eclass  *p;
        !           845:        struct eclass           e;
        !           846: 
        !           847:        if (eclasses == NULL) {
        !           848:                eclasses = neweclass();
        !           849:                eclasses->e_c = 0;
        !           850:                eclasses->e_b = newbits(TRUE);
        !           851:                eclasses->e_next = NULL;
        !           852:                eclasses->e_class = n_ec++;
        !           853:        }
        !           854: 
        !           855:        for (ep=eclasses; ep; ep=ep->e_next) {
        !           856:                if (! intersect(np, ep, &e))
        !           857:                        continue;
        !           858:                p = neweclass();
        !           859:                *p = e;
        !           860:                p->e_class = n_ec++;
        !           861:                p->e_next = eclasses;
        !           862:                eclasses = p;
        !           863:        }
        !           864: }
        !           865: 
        !           866: 
        !           867: /*
        !           868:  * is there a transition?
        !           869:  *     Return TRUE if there is a transition from `np' on the chars given
        !           870:  * by `ep'.
        !           871:  */
        !           872: bool eqtrans(ep, np)
        !           873: register struct eclass *ep;
        !           874: register struct newt   *np;
        !           875: {
        !           876:        register        i;
        !           877: 
        !           878:        if (ep->e_b) {
        !           879:                if (np->n_b) {
        !           880:                        for (i=0; i<NCHARS/NBCHAR; ++i)
        !           881:                                if (ep->e_b[i] & np->n_b[i])
        !           882:                                        return (TRUE);
        !           883:                }
        !           884:                else
        !           885:                        return (bittst(np->n_c, ep->e_b));
        !           886:        }
        !           887:        else {
        !           888:                if (np->n_b)
        !           889:                        return (bittst(ep->e_c, np->n_b));
        !           890:                else
        !           891:                        return (ep->e_c == np->n_c);
        !           892:        }
        !           893:        return (FALSE);
        !           894: }
        !           895: 
        !           896: 
        !           897: /*
        !           898:  * intersect char sets
        !           899:  *     If the intersection of `np' and `ep0' is a proper subset of `ep0',
        !           900:  * then store the intersection in `ep1', store the difference of
        !           901:  * `ep0' - `ep1' in `ep0' and return TRUE.
        !           902:  */
        !           903: static bool intersect(np, ep0, ep1)
        !           904: register struct newt   *np;
        !           905: register struct eclass *ep0;
        !           906: struct eclass          *ep1;
        !           907: {
        !           908:        register        i;
        !           909:        bool            classcheck();
        !           910: 
        !           911:        if (ep0->e_b == NULL)
        !           912:                return (FALSE);
        !           913: 
        !           914:        if (np->n_b == NULL) {
        !           915:                i = np->n_c;
        !           916:                if (! bittst(i, ep0->e_b))
        !           917:                        return (FALSE);
        !           918:                bitclr(i, ep0->e_b);
        !           919:                ep1->e_c = i;
        !           920:                etab[i] = n_ec;
        !           921:                ep1->e_b = NULL;
        !           922:        }
        !           923:        else {
        !           924:                if (! classcheck(np->n_b, ep0->e_b))
        !           925:                        return (FALSE);
        !           926:                ep1->e_b = newbits(FALSE);
        !           927:                for (i=0; i<NCHARS/NBCHAR; ++i) {
        !           928:                        ep1->e_b[i] = ep0->e_b[i] & np->n_b[i];
        !           929:                        ep0->e_b[i] &= ~np->n_b[i];
        !           930:                }
        !           931:                for (i=0; i<NCHARS; ++i)
        !           932:                        if (bittst(i, ep1->e_b))
        !           933:                                etab[i] = n_ec;
        !           934:                ep1->e_c = 0;
        !           935:        }
        !           936: 
        !           937:        return (TRUE);
        !           938: }
        !           939: 
        !           940: 
        !           941: /*
        !           942:  * check intersection
        !           943:  *     Specific check for char sets represented as bitmaps.  If the
        !           944:  * intersection of `p' and `q' is a proper subset of `q' return TRUE.
        !           945:  * Non-modifying nature of this routine is optimized for the "-y" option,
        !           946:  * where intersections of [Aa] and [Bb] are commonplace.
        !           947:  */
        !           948: static bool classcheck(p, q)
        !           949: register char  *p;
        !           950: register char  *q;
        !           951: {
        !           952:        register        i;
        !           953:        bool            k1;
        !           954:        bool            k2;
        !           955: 
        !           956:        k1 = FALSE;
        !           957:        k2 = FALSE;
        !           958: 
        !           959:        i = NCHARS / NBCHAR;
        !           960:        do {
        !           961:                if (*q & *p)
        !           962:                        k1 = TRUE;
        !           963:                if (*q++ & ~*p++)
        !           964:                        k2 = TRUE;
        !           965:        } while (--i);
        !           966: 
        !           967:        return (k1 && k2);
        !           968: }
        !           969: 
        !           970: 
        !           971: /*
        !           972:  * allocate new eclass
        !           973:  */
        !           974: static struct eclass *neweclass()
        !           975: {
        !           976:        register struct eclass  *ep;
        !           977: 
        !           978:        ep = malloc(sizeof *ep);
        !           979:        if (ep == NULL)
        !           980:                nomem();
        !           981:        return (ep);
        !           982: }
        !           983: 
        !           984: /*
        !           985: ** dfa.c
        !           986: */
        !           987: 
        !           988: 
        !           989: /*
        !           990:  * creation of the DFA
        !           991:  */
        !           992: 
        !           993: static                 bmsize;         /* size of bitmap `d_b' */
        !           994: static struct dragon   d;              /* prototype dragon */
        !           995: 
        !           996: static struct dragon   *dragons;       /* head of the dragon list */
        !           997: 
        !           998: struct dragon  *member();
        !           999: struct dragon  *enter();
        !          1000: 
        !          1001: 
        !          1002: /*
        !          1003:  * create the DFA start state
        !          1004:  */
        !          1005: struct dragon  *
        !          1006: initdfa(np)
        !          1007: struct newt    *np;
        !          1008: {
        !          1009: 
        !          1010:        if (d.d_s)
        !          1011:                free((char *)d.d_s);
        !          1012:        d.d_s = malloc((n_id+1)*sizeof(*d.d_s));
        !          1013:        if (d.d_s == NULL)
        !          1014:                nomem();
        !          1015:        d.d_s[0] = np;
        !          1016:        d.d_s[1] = NULL;
        !          1017:        bmsize = (n_id+NBCHAR-1) / NBCHAR;
        !          1018:        if (d.d_b)
        !          1019:                free((char *)d.d_b);
        !          1020:        d.d_b = malloc(bmsize);
        !          1021:        if (d.d_b == NULL)
        !          1022:                nomem();
        !          1023:        dragons = NULL;
        !          1024:        ++uniq;
        !          1025:        e_closure();
        !          1026:        return (enter(np->n_fp));
        !          1027: }
        !          1028: 
        !          1029: 
        !          1030: /*
        !          1031:  * construct the DFA
        !          1032:  *     This task is done incrementally, after searching has started.
        !          1033:  * The current dragon `dp' needs a transition on the input `ec' given
        !          1034:  * the NFA `np'.  The new dragon is determined, entered into `dp->d_p',
        !          1035:  * and returned.  If the new dragon has never been encountered, it is
        !          1036:  * remembered.  A special case arises if the current dragon is an accept
        !          1037:  * state: all transitions loop to itself.
        !          1038:  *     Note that `ec' is an equivalence class, not a char.
        !          1039:  */
        !          1040: struct dragon  *
        !          1041: makedfa(dp, ec, np)
        !          1042: struct dragon  *dp;
        !          1043: struct newt    *np;
        !          1044: {
        !          1045:        register struct eclass  *ep;
        !          1046:        register struct dragon  *p;
        !          1047:        extern struct eclass    *eclasses;
        !          1048: 
        !          1049:        if (dp->d_success) {
        !          1050:                dp->d_p[ec] = dp;
        !          1051:                return (dp);
        !          1052:        }
        !          1053:        for (ep=eclasses; ep->e_class!=ec; ep=ep->e_next)
        !          1054:                ;
        !          1055:        ++uniq;
        !          1056:        gettrans(dp, ep);
        !          1057:        e_closure();
        !          1058:        p = member();
        !          1059:        if (p == NULL)
        !          1060:                p = enter(np->n_fp);
        !          1061:        dp->d_p[ec] = p;
        !          1062:        return (p);
        !          1063: }
        !          1064: 
        !          1065: 
        !          1066: /*
        !          1067:  * get transitions
        !          1068:  *     Construct in `d.d_s' the set of newts to which there is a
        !          1069:  * transition on `ep' from some newt in `dp->d_s'.
        !          1070:  */
        !          1071: static gettrans(dp, ep)
        !          1072: struct dragon  *dp;
        !          1073: struct eclass  *ep;
        !          1074: {
        !          1075:        register struct newt    **pp;
        !          1076:        register struct newt    *np;
        !          1077:        register struct newt    *p;
        !          1078:        struct newt     **npp;
        !          1079:        bool                    eqtrans();
        !          1080: 
        !          1081:        npp = d.d_s;
        !          1082: 
        !          1083:        pp = dp->d_s;
        !          1084:        while (np = *pp++)
        !          1085:                if ((p = np->n_cp)
        !          1086:                && (np->n_c != EPSILON)
        !          1087:                && (eqtrans(ep, np))) {
        !          1088:                        *npp++ = p;
        !          1089:                        p->n_uniq = uniq;
        !          1090:                }
        !          1091:        *npp = NULL;
        !          1092: }
        !          1093: 
        !          1094: 
        !          1095: /*
        !          1096:  * locate a dragon
        !          1097:  *     The set of newts given by `d.d_s' are sought in the DFA.  The
        !          1098:  * appropriate dragon is returned, else 0.  The use of bitmap `d_b' allows
        !          1099:  * comparing (unsorted) `d_s' sets in time O(N).  Hashing of `d_s' and
        !          1100:  * "self-organizing" the DFA also help to keep things fast.
        !          1101:  */
        !          1102: static struct dragon *member()
        !          1103: {
        !          1104:        register struct dragon  *dp;
        !          1105:        register char   *p;
        !          1106:        register char   *q;
        !          1107:        int             i;
        !          1108: 
        !          1109:        dp = dragons;
        !          1110: 
        !          1111:        do {
        !          1112:                if (dp->d_hash == d.d_hash) {
        !          1113:                        p = dp->d_b;
        !          1114:                        q = d.d_b;
        !          1115:                        i = bmsize; do {
        !          1116:                                if (*p++ != *q++)
        !          1117:                                        break;
        !          1118:                        } while (--i);
        !          1119:                        if (i == 0) {
        !          1120:                                if (dp == dragons)
        !          1121:                                        break;
        !          1122:                                if (dp->d_next)
        !          1123:                                        dp->d_next->d_last = dp->d_last;
        !          1124:                                dp->d_last->d_next = dp->d_next;
        !          1125:                                dragons->d_last = dp;
        !          1126:                                dp->d_next = dragons;
        !          1127:                                dp->d_last = NULL;
        !          1128:                                dragons = dp;
        !          1129:                                break;
        !          1130:                        }
        !          1131:                }
        !          1132:        } while (dp = dp->d_next);
        !          1133: 
        !          1134:        return (dp);
        !          1135: }
        !          1136: 
        !          1137: 
        !          1138: /*
        !          1139:  * enter the dragon
        !          1140:  *     The prototype dragon `d' is used to create a dragon, which is
        !          1141:  * entered in the DFA.
        !          1142:  */
        !          1143: static struct dragon   *
        !          1144: enter(finalnp)
        !          1145: struct newt    *finalnp;
        !          1146: {
        !          1147:        register struct dragon  *p;
        !          1148:        register                i;
        !          1149: 
        !          1150:        p = malloc(sizeof *p);
        !          1151:        if (p == NULL)
        !          1152:                nomem();
        !          1153:        p->d_success = FALSE;
        !          1154:        p->d_hash = d.d_hash;
        !          1155:        for (i=0; d.d_s[i]; ++i)
        !          1156:                if (d.d_s[i] == finalnp)
        !          1157:                        p->d_success = TRUE;
        !          1158:        p->d_s = malloc((i+1)*sizeof(*p->d_s));
        !          1159:        if (p->d_s == NULL)
        !          1160:                nomem();
        !          1161:        for (i=0; p->d_s[i]=d.d_s[i]; ++i)
        !          1162:                ;
        !          1163:        p->d_b = malloc(bmsize);
        !          1164:        if (p->d_b == NULL)
        !          1165:                nomem();
        !          1166:        for (i=0; i<bmsize; ++i)
        !          1167:                p->d_b[i] = d.d_b[i];
        !          1168:        p->d_p = malloc(n_ec*sizeof(*p->d_p));
        !          1169:        if (p->d_p == NULL)
        !          1170:                nomem();
        !          1171:        for (i=0; i<n_ec; ++i)
        !          1172:                p->d_p[i] = NULL;
        !          1173:        if (dragons)
        !          1174:                dragons->d_last = p;
        !          1175:        p->d_next = dragons;
        !          1176:        dragons = p;
        !          1177:        p->d_last = NULL;
        !          1178:        return (p);
        !          1179: }
        !          1180: 
        !          1181: 
        !          1182: /*
        !          1183:  * perform epsilon-closure
        !          1184:  *     Epsilon-transition `d.d_s' is computed and the result placed
        !          1185:  * in `d.d_s'.  Ensuring a newt is not already on the list requires
        !          1186:  * time O(N), thanks to `uniq'.
        !          1187:  */
        !          1188: static
        !          1189: e_closure()
        !          1190: {
        !          1191:        register struct newt    **nqq;
        !          1192:        register struct newt    *np;
        !          1193:        register struct newt    *p;
        !          1194:        struct newt             **npp;
        !          1195: 
        !          1196:        d.d_hash = 0;
        !          1197:        for (nqq=d.d_s; *nqq++; )
        !          1198:                ;
        !          1199:        --nqq;
        !          1200: 
        !          1201:        for (npp=d.d_s; npp<nqq; ) {
        !          1202:                np = *npp++;
        !          1203:                d.d_hash += (int)np;
        !          1204:                if ((p = np->n_cp)
        !          1205:                && (np->n_c == EPSILON)
        !          1206:                && (p->n_uniq != uniq)) {
        !          1207:                        *nqq++ = p;
        !          1208:                        p->n_uniq = uniq;
        !          1209:                }
        !          1210:                if ((p = np->n_ep)
        !          1211:                && (p->n_uniq != uniq)) {
        !          1212:                        *nqq++ = p;
        !          1213:                        p->n_uniq = uniq;
        !          1214:                }
        !          1215:        }
        !          1216:        *nqq = NULL;
        !          1217: 
        !          1218:        bmbuild();
        !          1219: }
        !          1220: 
        !          1221: 
        !          1222: /*
        !          1223:  * build bitmap
        !          1224:  *     A bitmap of `d.d_s' is built in `d.d_b'.
        !          1225:  */
        !          1226: static
        !          1227: bmbuild()
        !          1228: {
        !          1229:        register struct newt    *np;
        !          1230:        register char           *p;
        !          1231:        register                i;
        !          1232: 
        !          1233:        p = d.d_b;
        !          1234:        i = bmsize; do {
        !          1235:                *p++ = 0;
        !          1236:        } while (--i);
        !          1237:        i = 0;
        !          1238:        while (np = d.d_s[i++])
        !          1239:                bitset(np->n_id, d.d_b);
        !          1240: }
        !          1241: /*
        !          1242: ** search.c
        !          1243: */
        !          1244: /*
        !          1245:  * execution of the DFA
        !          1246:  */
        !          1247: 
        !          1248: 
        !          1249: static bool            status;         /* set TRUE if any matches */
        !          1250: static char            cbuf[BUFSIZ];   /* first BUFSIZ chars of input line */
        !          1251: static char            *file;          /* input file name */
        !          1252: static long            nlines;         /* input line count */
        !          1253: static long            seekpos;        /* start of current line in file */
        !          1254: static long            matches;        /* # matches */
        !          1255: static struct dragon   *dfa;           /* DFA start state */
        !          1256: static struct newt     *nfa;           /* NFA */
        !          1257: 
        !          1258: 
        !          1259: /*
        !          1260:  * search a file
        !          1261:  *     Return TRUE if any matches.
        !          1262:  */
        !          1263: bool
        !          1264: search(fn, dp, np)
        !          1265: char           *fn;
        !          1266: struct dragon  *dp;
        !          1267: struct newt    *np;
        !          1268: {
        !          1269:        bool    match();
        !          1270: 
        !          1271:        file = fn;
        !          1272:        dfa = dp;
        !          1273:        nfa = np;
        !          1274:        nlines = 0;
        !          1275:        seekpos = 0;
        !          1276:        matches = 0;
        !          1277:        status = FALSE;
        !          1278: 
        !          1279:        while (match())
        !          1280:                ;
        !          1281: 
        !          1282:        if (! sflag && ! lflag && cflag) {
        !          1283:                printfile();
        !          1284:                printf("%ld\n", matches);
        !          1285:        }
        !          1286:        return (status);
        !          1287: }
        !          1288: 
        !          1289: 
        !          1290: /*
        !          1291:  * look for a match
        !          1292:  */
        !          1293: bool
        !          1294: match()
        !          1295: {
        !          1296:        register struct dragon  *dp;
        !          1297:        register                c;
        !          1298:        register char           *p;
        !          1299:        long                    nchars;
        !          1300:        struct dragon           *dp2;
        !          1301:        extern char             etab[];
        !          1302:        bool                    success();
        !          1303: 
        !          1304:        if ((dp=dfa->d_p[etab['\n']]) == NULL)
        !          1305:                dp = makedfa(dfa, etab['\n'], nfa);
        !          1306:        nchars = 0;
        !          1307:        p = cbuf;
        !          1308: 
        !          1309:        while ((c=getc(ifp)) != EOF) {
        !          1310:                ++nchars;
        !          1311:                c &= 0177;
        !          1312:                if (p < &cbuf[BUFSIZ])
        !          1313:                        *p++ = c;
        !          1314:                dp2 = dp;
        !          1315:                if ((dp=dp->d_p[etab[c]]) == NULL)
        !          1316:                        dp = makedfa(dp2, etab[c], nfa);
        !          1317:                if (c == '\n') {
        !          1318:                        ++nlines;
        !          1319:                        if (vflag!=dp->d_success && ! success(file, p))
        !          1320:                                break;
        !          1321:                        seekpos += nchars;
        !          1322:                        if (dp->d_success)
        !          1323:                                return (TRUE);
        !          1324:                        nchars = 0;
        !          1325:                        p = cbuf;
        !          1326:                }
        !          1327:        }
        !          1328: 
        !          1329:        return (FALSE);
        !          1330: }
        !          1331: 
        !          1332: 
        !          1333: /*
        !          1334:  * report a match
        !          1335:  *     If the line is to be printed, and it is over BUFSIZ chars, the
        !          1336:  * input file better be seekable.
        !          1337:  */
        !          1338: bool
        !          1339: success(file, p)
        !          1340: char   *file;
        !          1341: char   *p;
        !          1342: {
        !          1343:        extern char *tempnam();
        !          1344:        register char   *q;
        !          1345:        register        c;
        !          1346:        register        n;
        !          1347: 
        !          1348:        ++matches;
        !          1349:        status = TRUE;
        !          1350:        if (sflag)
        !          1351:                return (FALSE);
        !          1352:        if (lflag) {
        !          1353:                printf("%s\n", file);
        !          1354:                return (FALSE);
        !          1355:        }
        !          1356:        if (aflag) {
        !          1357:                if ((NULL == tmpFn) &&
        !          1358:                   ((NULL == (tmpFn = tempnam(NULL, "egr"))) ||
        !          1359:                    (NULL == (tmpFile = fopen(tmpFn, "w"))))) {
        !          1360:                        fprintf(stderr, "egrep: cant open tmp file");
        !          1361:                        exit(1);
        !          1362:                }
        !          1363:                fprintf(tmpFile, "%ld:%s: egrep\n", nlines, file);
        !          1364:                return (TRUE);
        !          1365:        }
        !          1366:        if (cflag)
        !          1367:                return (TRUE);
        !          1368:        printfile();
        !          1369:        if (nflag)
        !          1370:                printf("%ld:", nlines);
        !          1371:        if (bflag)
        !          1372:                printf("%ld:", seekpos/BUFSIZ);
        !          1373:        q = cbuf;
        !          1374:        n = p - q;
        !          1375:        while (q < p)
        !          1376:                putchar(*q++);
        !          1377:        if (*--q != '\n') {
        !          1378:                if (fseek(ifp, seekpos+n, 0) == EOF) {
        !          1379:                        putchar('\n');
        !          1380:                        fatal("line too long");
        !          1381:                }
        !          1382:                do {
        !          1383:                        c = getc(ifp);
        !          1384:                        if (c == EOF)
        !          1385:                                return (FALSE);
        !          1386:                        putchar(c);
        !          1387:                } while (c != '\n');
        !          1388:        }
        !          1389:        return (TRUE);
        !          1390: }
        !          1391: 
        !          1392: 
        !          1393: static
        !          1394: printfile()
        !          1395: {
        !          1396: 
        !          1397:        if (! hflag)
        !          1398:                printf("%s:", file);
        !          1399: }
        !          1400: 
        !          1401: /*
        !          1402: ** bits.c
        !          1403: */
        !          1404: 
        !          1405: 
        !          1406: /*
        !          1407:  * allocate bitmap for character class
        !          1408:  *     If `setbits'==TRUE then the map is initialized to ones, else zeros.
        !          1409:  */
        !          1410: char   *
        !          1411: newbits(setbits)
        !          1412: bool   setbits;
        !          1413: {
        !          1414:        register        i;
        !          1415:        register        c;
        !          1416:        register char   *p;
        !          1417:        register char   *q;
        !          1418: 
        !          1419:        p = malloc(NCHARS/NBCHAR);
        !          1420:        if (p == NULL)
        !          1421:                nomem();
        !          1422:        c = 0;
        !          1423:        if (setbits)
        !          1424:                c = ~0;
        !          1425:        q = p;
        !          1426:        i = NCHARS / NBCHAR;
        !          1427:        do {
        !          1428:                *p++ = c;
        !          1429:        } while (--i);
        !          1430:        return (q);
        !          1431: }

unix.superglobalmegacorp.com

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