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

1.1     ! root        1: /*
        !             2:  * To compile use
        !             3:  * cc cgrep.c -lmisc
        !             4:  * This uses libmisc.a and the misc.h header from libmisc.a.Z
        !             5:  */
        !             6: 
        !             7: /*
        !             8:  * cgrep is egrep for c source programs.
        !             9:  *     cgrep [-r new] [-clnsA] [pattern] [file ...]
        !            10:  *
        !            11:  * cgrep checks all c identifiers (cgrep considers if, etc to be
        !            12:  * identifiers) against an egrep type pattern for a full match.
        !            13:  *
        !            14:  *     cgrep tmp *.c
        !            15:  * will find tmp as an identifier, but not tmpname, or tmp in a string or
        !            16:  * comment.
        !            17:  *     cgrep "x|abc|d" *.c
        !            18:  * will find x, ab, or d. Note these are egrep style patterns with a
        !            19:  * surrounding ^( )$ Thus "reg*" will not match register but "reg.*"
        !            20:  * will.
        !            21:  *
        !            22:  * cgrep accumulates names with included . and -> for testing against the
        !            23:  * egrep pattern. Thus you can look for ptr->val with
        !            24:  *     cgrep "ptr->val" x.c
        !            25:  * This will find ptr->val even if it contains spaces, comments or is
        !            26:  * spread across lines. If it is spread across lines it will be reported
        !            27:  * on the line containing the last token unless the -A option is used
        !            28:  * in which case it will be reported on the line containing the first
        !            29:  * token.
        !            30:  *
        !            31:  * For structure.member use
        !            32:  *     cgrep "structure\.member" x.c
        !            33:  * because . has the egrep meaning any character. Do not include spaces
        !            34:  * in any pattern. Only identifiers and . or -> between identifiers are
        !            35:  * included in the tokens checked for pattern match.
        !            36:  *
        !            37:  * Where no files are given cgrep will read stdin. Options -lA require
        !            38:  * a file name. Where stdin is used with option -r a new file is written
        !            39:  * out stdout.
        !            40:  *
        !            41:  * Options.
        !            42:  *
        !            43:  * -l lists the files with hits not the lines.
        !            44:  *
        !            45:  * -n puts a line number on found lines.
        !            46:  *
        !            47:  * -s List all strings. This form takes no pattern.
        !            48:  *
        !            49:  * -c List all comments. This form takes no pattern.
        !            50:  *
        !            51:  * -A builds a tmp file and calls 'me' to process the file with the tmp file
        !            52:  *    as an "error" list like the -A option of cc. Each line of this list
        !            53:  *    shows the found pattern and where multiple patterns are found on a
        !            54:  *    line there are multiple lines, just like cc -A showing multiple
        !            55:  *    errors on a line. This is to allow emacs scripts to make systematic
        !            56:  *    changes. Where a patttern is split across multiple lines -A causes
        !            57:  *    it to be reported on the line with the first token, also to
        !            58:  *    simplify emacs scripts.
        !            59:  *
        !            60:  *    If cgrep -A is used to process a number of files it will search each
        !            61:  *    file for patttern matches and call 'me' only if the file has a hit. To
        !            62:  *    stop the process exit 'me' with <ctl-u><ctl-x><ctl-c>. See the new emacs
        !            63:  *    initialization macro feature for a way to process these files
        !            64:  *    automatically.
        !            65:  *
        !            66:  * -r Replaces all occurances of the pattern with "new". This form only matches
        !            67:  *    simple tokens, not things like "ptr->val". -r is incompatible with all
        !            68:  *    other options.
        !            69:  */
        !            70: #include <ctype.h>
        !            71: #include <stdio.h>
        !            72: #include <misc.h>
        !            73: 
        !            74: /*
        !            75:  * Cgrep never runs out of room on lines or buffers until malloc fails
        !            76:  * these are buffer expanders.
        !            77:  */
        !            78: #define TROOM(buf, has, needs) while ((needs) >= has) \
        !            79:  if (NULL == (buf = realloc(buf, sizeof(*buf) * (has += 10)))) \
        !            80:   fatal(outSpace)
        !            81: 
        !            82: #define ROOM(buf, has, needs)  while ((needs) >= has) \
        !            83:  if (NULL == (buf = realloc(buf, has += 512))) \
        !            84:   fatal(outSpace)
        !            85: 
        !            86: extern char *realloc();
        !            87: static char outSpace[] = "cgrep: out of space";
        !            88: 
        !            89: struct token { /* collected token array */
        !            90:        int start;      /* token index on buff */
        !            91:        int atline;     /* line number where token spotted */
        !            92: };
        !            93: 
        !            94: enum fstate {  /* lexical processing state */
        !            95:        start,
        !            96:        slash,          /* slash encountered in normal state */
        !            97:        comment,        /* in comment */
        !            98:        star,           /* * in comment */
        !            99:        bsl,            /* back slash */
        !           100:        dquote,         /* double quote */
        !           101:        squote,         /* single quote */
        !           102:        token,          /* c word */
        !           103:        minus           /* - maybe -> */
        !           104: };
        !           105: 
        !           106: enum wstate { /* word processing states */
        !           107:        word,   /* some c identifier */
        !           108:        dot,    /* . or -> */
        !           109:        other   /* anything else */
        !           110: };
        !           111: 
        !           112: /* cgrep has no fixed size arrays only growable buffers */
        !           113: static char *buff = NULL;      /* accumulate stuff */
        !           114: static int buffLen;            /* buffer length */
        !           115: 
        !           116: static struct token *tokens = NULL; /* token array */
        !           117: static int tokenLen;           /* size of token array */
        !           118: 
        !           119: static char *line;             /* expandable input line */
        !           120: static int  lineLen;           /* current length of input line */
        !           121: 
        !           122: static char lswitch;           /* list files found */
        !           123: static char aswitch;           /* call emacs with line list */
        !           124: static char nswitch;           /* print line number */
        !           125: static char sswitch;           /* print all strings */
        !           126: static char cswitch;           /* print all comments */
        !           127: static char rswitch;           /* replace found pattern */
        !           128: 
        !           129: static regexp *pat;            /* a compiled regular expression */
        !           130: 
        !           131: static char *newstr;           /* The new string with rswitch */
        !           132: 
        !           133: static char *filen = NULL;     /* the file currently being processed */
        !           134: static char *tname = NULL;     /* temp file name */
        !           135: static FILE *tfp;              /* tmp file pointer */
        !           136: 
        !           137: static int lineno;             /* current line number */
        !           138: static int marked;             /* 1 if pattern found on line. */
        !           139: 
        !           140: /*
        !           141:  * Character types table
        !           142:  * for the ASCII character set modified to see _ as alpha.
        !           143:  * _ctype[0] is for EOF, the rest if indexed
        !           144:  * by the ascii values of the characters.
        !           145:  */
        !           146: static unsigned char _ctype[] = {
        !           147:        0,      /* EOF */
        !           148:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           149:        _C, _S|_C, _S|_C, _S|_C, _S|_C, _S|_C, _C, _C,
        !           150:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           151:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           152:        _S|_X, _P, _P, _P, _P, _P, _P, _P,
        !           153:        _P, _P, _P, _P, _P, _P, _P, _P,
        !           154:        _D, _D, _D, _D, _D, _D, _D, _D,
        !           155:        _D, _D, _P, _P, _P, _P, _P, _P,
        !           156:        _P, _U, _U, _U, _U, _U, _U, _U,
        !           157:        _U, _U, _U, _U, _U, _U, _U, _U,
        !           158:        _U, _U, _U, _U, _U, _U, _U, _U,
        !           159:        _U, _U, _U, _P, _P, _P, _P, _L,
        !           160:        _P, _L, _L, _L, _L, _L, _L, _L,
        !           161:        _L, _L, _L, _L, _L, _L, _L, _L,
        !           162:        _L, _L, _L, _L, _L, _L, _L, _L,
        !           163:        _L, _L, _L, _P, _P, _P, _P, _C,
        !           164:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           165:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           166:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           167:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           168:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           169:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           170:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           171:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           172:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           173:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           174:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           175:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           176:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           177:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           178:        _C, _C, _C, _C, _C, _C, _C, _C,
        !           179:        _C, _C, _C, _C, _C, _C, _C, _C
        !           180: };
        !           181: 
        !           182: /*
        !           183:  * Report errors for public domain regexp package.
        !           184:  */
        !           185: void
        !           186: regerror(s)
        !           187: char *s;
        !           188: {
        !           189:        fatal("cgrep: pattern error %s\n", s);
        !           190: }
        !           191: 
        !           192: /*
        !           193:  * Pattern found with -A mode. It is assumed that users of
        !           194:  * this mode will want to know about all hits on a line.
        !           195:  */
        !           196: static void
        !           197: emacsLine(found, atline)
        !           198: char *found;
        !           199: {
        !           200:        extern char *tempnam();
        !           201: 
        !           202:        /* if tmp file not opened open it. */
        !           203:        if ((NULL == tname) &&
        !           204:            ((NULL == (tname = tempnam(NULL, "cgr"))) ||
        !           205:              (NULL == (tfp = fopen(tname, "w")))))
        !           206:                fatal("cgrep: Cannot open tmp file");
        !           207:        fprintf(tfp, "%d: %s: found '%s'\n", atline, filen, found);
        !           208: }
        !           209: 
        !           210: /*
        !           211:  * When we get a word, dot, arrow or other we come here.
        !           212:  *
        !           213:  * cgrep accumulates things like ptr->memb.x in buff.
        !           214:  * as these are accumulated it is nessisary to match buff
        !           215:  * against the regular expression one slice at a time
        !           216:  * that is when the x in ptr->memb.x was found cgrep would check
        !           217:  * ptr->memb.x then memb.x then x
        !           218:  * against the pattern. Thus memb.x matches ptr->memb.x
        !           219:  */
        !           220: static void
        !           221: gota(got, what)
        !           222: register enum wstate got;      /* what we have */
        !           223: char *what;            /* the string we have or NULL */
        !           224: {
        !           225:        static int tokenCt;         /* number of tokens */
        !           226:        static enum wstate state;   /* current word processing state */
        !           227:        static int wlen, blen;      /* strlen(what) and strlen(buff) + 1 */
        !           228:        int i;
        !           229: 
        !           230:        if (sswitch || cswitch)
        !           231:                return;
        !           232: 
        !           233:        if (rswitch) {  /* replace mode works on tokens only */
        !           234:                marked = (word == got) && regexec(pat, what);
        !           235:                return;
        !           236:        }
        !           237: 
        !           238:        switch (got) {
        !           239:        case word:
        !           240:                wlen = strlen(what);
        !           241:                switch (state) {
        !           242:                case other:
        !           243:                case word:
        !           244:                        /* store start and line number of token */
        !           245:                        tokenCt = 1;
        !           246:                        TROOM(tokens, tokenLen, tokenCt);
        !           247:                        tokens[0].start = 0;
        !           248:                        tokens[0].atline = lineno;
        !           249: 
        !           250:                        /* store token */
        !           251:                        blen = wlen;
        !           252:                        ROOM(buff, buffLen, blen);
        !           253:                        strcpy(buff, what);
        !           254:                        break;
        !           255:                case dot:
        !           256:                        /* store start and line number of token */
        !           257:                        TROOM(tokens, tokenLen, tokenCt);
        !           258:                        tokens[tokenCt].start = blen;
        !           259:                        tokens[tokenCt++].atline = lineno;
        !           260: 
        !           261:                        /* store token */
        !           262:                        blen += wlen;
        !           263:                        ROOM(buff, buffLen, blen);
        !           264:                        strcat(buff, what);
        !           265:                }
        !           266: 
        !           267:                /* Check the accumulated token for matches */
        !           268:                for (i = 0; i < tokenCt; i++) {
        !           269:                        char *p;
        !           270: 
        !           271:                        if (regexec(pat, p = buff + tokens[i].start)) {
        !           272:                                if (aswitch)
        !           273:                                        emacsLine(p, tokens[i].atline);
        !           274:                                else {
        !           275:                                        marked = 1;
        !           276:                                        break;
        !           277:                                }
        !           278:                        }
        !           279:                }
        !           280: 
        !           281:                state = got;
        !           282:                break;
        !           283: 
        !           284:        case dot:
        !           285:                if (word == state) {
        !           286:                        blen += strlen(what);
        !           287:                        ROOM(buff, buffLen, blen);
        !           288:                        strcat(buff, what);
        !           289:                        state = got;
        !           290:                        break;
        !           291:                }
        !           292:        case other:
        !           293:                state = other;
        !           294:        }
        !           295: }
        !           296: 
        !           297: /*
        !           298:  * call emacs with file and tmpfile.
        !           299:  */
        !           300: static void
        !           301: callEmacs()
        !           302: {
        !           303: #ifdef GEMDOS
        !           304: #include <path.h>
        !           305:        extern  char *path(), *getenv();
        !           306:        extern char **environ;
        !           307:        static char* cmda[5] = { NULL, "-e", NULL, NULL, NULL };
        !           308: #endif
        !           309:        int quit;
        !           310: 
        !           311:        fclose(tfp);
        !           312: #ifdef MSDOS
        !           313:        sprintf(line, "-e %s %s", tname, filen);
        !           314:        if (0x7f == (quit = execall("me", line)))
        !           315: #endif
        !           316: #ifdef COHERENT
        !           317:        sprintf(line, "me -e %s %s ", tname, filen);
        !           318:        if (0x7f == (quit = system(line)))
        !           319: #endif
        !           320: #ifdef GEMDOS
        !           321:        cmda[2] = tname;
        !           322:        cmda[3] = filen;
        !           323:        if ((NULL == cmda[0]) &&
        !           324:           (NULL == (cmda[0] = path(getenv("PATH"), "me.tos", 1))))
        !           325:                fatal("cgrep: Cannot locate me.tos\n");
        !           326:        else if ((quit = execve(cmda[0], cmda, environ)) < 0)
        !           327: #endif
        !           328:                fatal("cgrep: cannot execute 'me'");
        !           329:        unlink(tname);
        !           330:        free(tname);
        !           331:        tname = NULL;
        !           332:        if (quit)
        !           333:                exit(0);
        !           334: }
        !           335: 
        !           336: /*
        !           337:  * print a hit for options -s or -c.
        !           338:  */
        !           339: static void
        !           340: printx(s)
        !           341: char *s;
        !           342: {
        !           343:        if (aswitch)
        !           344:                emacsLine(s, lineno);
        !           345:        else {
        !           346:                if (NULL != filen)
        !           347:                        printf("%s: ", filen);
        !           348:                if (nswitch)
        !           349:                        printf("%4d: ", lineno);
        !           350:                printf("%s\n", s);
        !           351:        }
        !           352: }
        !           353: 
        !           354: /*
        !           355:  * Lexically process a file.
        !           356:  */
        !           357: static void
        !           358: lex()
        !           359: {
        !           360:        int  c, i;
        !           361:        enum fstate state, pstate;
        !           362:        char *w, changed;
        !           363:        FILE *ifp, *tfp;
        !           364: 
        !           365:        if (NULL == filen)
        !           366:                ifp = stdin;
        !           367:        else if (NULL == (ifp = fopen(filen, "r"))) {
        !           368:                fprintf(stderr, "cgrep: warning cannot open %s\n", filen);
        !           369:                return;
        !           370:        }
        !           371: 
        !           372:        if (rswitch) {
        !           373:                changed = 0;    /* no changes so far */
        !           374: 
        !           375:                if (NULL == filen)
        !           376:                        tfp = stdout;
        !           377:                else if ((NULL == (tname = tempnam(NULL, "cse"))) ||
        !           378:                         (NULL == (tfp = fopen(tname, "w"))))
        !           379:                        fatal("csed: Cannot open tmp file");
        !           380:        }
        !           381: 
        !           382:        lineno = 1;
        !           383:        i = marked = 0;
        !           384:        gota(other, NULL);      /* initialize word machine */
        !           385:        for (state = start; ; ) {
        !           386:                line[i] = '\0';
        !           387:                c = fgetc(ifp);
        !           388: 
        !           389:                switch (state) {
        !           390:                case minus:
        !           391:                        if ('>' == c) {
        !           392:                                gota(dot, "->");
        !           393:                                state = start;
        !           394:                                break;
        !           395:                        }
        !           396:                        goto isstart;
        !           397:                case token:
        !           398:                        if (isalnum(c))
        !           399:                                break;
        !           400:                        gota(word, w);
        !           401: 
        !           402:                        /* we have a word to replace */
        !           403:                        if (rswitch && marked) {
        !           404:                                i += strlen(newstr) - strlen(w);
        !           405:                                ROOM(line, lineLen, i);
        !           406:                                strcpy(w, newstr);
        !           407:                                changed = 1;
        !           408:                        }
        !           409: isstart:               state = start;
        !           410:                case start:
        !           411:                        switch (c) {
        !           412:                        case '.':
        !           413:                                gota(dot, ".");
        !           414:                                break;
        !           415:                        case '-':
        !           416:                                state = minus;
        !           417:                                break;
        !           418:                        case '/':
        !           419:                                state = slash;
        !           420:                                break;
        !           421:                        case '\\':
        !           422:                                pstate = state;
        !           423:                                state = bsl;
        !           424:                                break;
        !           425:                        case '"':
        !           426:                                w = line + i;
        !           427:                                state = dquote;
        !           428:                                break;
        !           429:                        case '\'':
        !           430:                                state = squote;
        !           431:                                break;
        !           432:                        default:
        !           433:                                if (isalpha(c)) {
        !           434:                                        w = line + i;
        !           435:                                        state = token;
        !           436:                                }
        !           437:                                else if (!isspace(c))
        !           438:                                        gota(other, NULL);
        !           439:                        }
        !           440:                        break;
        !           441:                case slash:
        !           442:                        if ('*' != c)
        !           443:                                goto isstart;
        !           444:                        w = line + i + 1;
        !           445:                        state = comment;
        !           446:                        break;
        !           447:                case star:
        !           448:                        if ('/' == c) {
        !           449:                                if (cswitch) { /* report comment */
        !           450:                                        line[i - 1] = '\0';
        !           451:                                        printx(w);
        !           452:                                        line[i - 1] = '*';
        !           453:                                }
        !           454:                                state = start;
        !           455:                                break;
        !           456:                        }
        !           457:                        state = comment;
        !           458:                case comment:
        !           459:                        if ('*' == c)
        !           460:                                state = star;
        !           461:                        break;
        !           462:                case bsl:
        !           463:                        state = pstate;
        !           464:                        break;
        !           465:                case dquote:
        !           466:                        switch (c) {
        !           467:                        case '"':
        !           468:                        case '\n':
        !           469:                                state = start;
        !           470:                                if (sswitch)
        !           471:                                        printx(w + 1);
        !           472:                                else
        !           473:                                        gota(other, NULL);
        !           474:                                break;
        !           475:                        case '\\':
        !           476:                                pstate = state;
        !           477:                                state  = bsl;
        !           478:                                break;
        !           479:                        }
        !           480:                        break;
        !           481:                case squote:
        !           482:                        switch (c) {
        !           483:                        case '\'':
        !           484:                        case '\n':
        !           485:                                gota(other, NULL);
        !           486:                                state = start;
        !           487:                                break;
        !           488:                        case '\\':
        !           489:                                pstate = state;
        !           490:                                state  = bsl;
        !           491:                                break;
        !           492:                        }
        !           493:                        break;
        !           494:                }
        !           495:                if (('\n' != c) && (EOF != c)) {
        !           496:                        line[i++] = c;
        !           497:                        ROOM(line, lineLen, i);
        !           498:                }
        !           499:                else {  /* end of line */
        !           500:                        if (rswitch) {
        !           501:                                if (EOF == c) {
        !           502:                                        if (!i) /* null line */
        !           503:                                                break;
        !           504:                                }
        !           505:                                else
        !           506:                                        line[i++] = c;
        !           507:                                ROOM(line, lineLen, i);
        !           508:                                line[i] = 0;
        !           509:                                fputs(line, tfp);
        !           510:                                marked = 0;
        !           511:                        }
        !           512: 
        !           513:                        if (cswitch && (comment == state)) {
        !           514:                                printx(w);
        !           515:                                w = line;
        !           516:                        }
        !           517: 
        !           518:                        if (marked) {
        !           519:                                marked = 0;                     
        !           520:                                if (lswitch) {
        !           521:                                        printf("%s\n", filen);
        !           522:                                        break;
        !           523:                                }
        !           524:                                printx(line);
        !           525:                        }
        !           526: 
        !           527:                        lineno++;
        !           528:                        i = 0;
        !           529:                        if (EOF == c)
        !           530:                                break;
        !           531:                }
        !           532:        }
        !           533: 
        !           534:        fclose(ifp);
        !           535: 
        !           536:        if (rswitch) {
        !           537:                fclose(tfp);
        !           538: 
        !           539:                if (NULL == filen)
        !           540:                        ; /* do nothing file is already out */
        !           541:                else if (changed) {
        !           542:                        unlink(filen);
        !           543:                        sprintf(line, "mv %s %s", tname, filen);
        !           544:                        system(line);
        !           545:                }
        !           546:                else
        !           547:                        unlink(tname);
        !           548:        }
        !           549: 
        !           550:        if (aswitch && (NULL != tname)) /* tmp file opened for -A option */
        !           551:                callEmacs();
        !           552: }
        !           553: 
        !           554: main(argc, argv)
        !           555: int argc;
        !           556: register char **argv;
        !           557: {
        !           558:        register char c;
        !           559:        int errsw = 0;
        !           560:        static char msg[] = "cgrep [-r newStr] [-clnsA] [pattern] filename ...";
        !           561:        char *p, *q;
        !           562:        extern int optind;
        !           563:        extern char *optarg;
        !           564: 
        !           565:        if (1 == argc)
        !           566:                usage(msg);
        !           567: 
        !           568:        while (EOF != (c = getopt(argc, argv, "cslnA?r:V"))) {
        !           569:                switch (c) {
        !           570:                case 'V':
        !           571:                        printf("cgrep version 1.1\n");
        !           572:                        exit(0);
        !           573:                case 'c':
        !           574:                        cswitch = 1;    /* comments only */
        !           575:                        break;
        !           576:                case 's':
        !           577:                        sswitch = 1;    /* strings only */
        !           578:                        break;
        !           579:                case 'l':
        !           580:                        lswitch = 1;    /* print filenames only */
        !           581:                        break;
        !           582:                case 'n':
        !           583:                        nswitch = 1;    /* print line numbers */
        !           584:                        break;
        !           585:                case 'A':
        !           586:                        aswitch = 1;    /* interact with emacs */
        !           587:                        break;
        !           588:                case 'r':
        !           589:                        rswitch = 1;    /* replace hits */
        !           590:                        newstr = optarg;
        !           591:                        break;
        !           592:                default:
        !           593:                        errsw = 1;
        !           594:                }
        !           595:        }
        !           596: 
        !           597:        /* check unknown switches and rswitch goes with no other switches */
        !           598:        if (errsw || 
        !           599:            (rswitch && (aswitch | nswitch | lswitch | cswitch | sswitch)))
        !           600:                usage(msg);
        !           601: 
        !           602:        if (!sswitch && !cswitch) {     /* process pattern */
        !           603:                if (optind == argc)             /* no pattern */
        !           604:                        usage(msg);
        !           605: 
        !           606:                /* inclose pattern in ^(  )$ to force full match */
        !           607:                p = alloc(5 + strlen(q = argv[optind++]));
        !           608:                sprintf(p, "^(%s)$", q);
        !           609:                if (NULL == (pat = regcomp(p)))
        !           610:                        fatal("cgrep: Illegal pattern\n");
        !           611:        }
        !           612: 
        !           613:        ROOM(line, lineLen, 1); /* get input line started */
        !           614: 
        !           615:        if (optind == argc) {
        !           616:                if (aswitch | lswitch)
        !           617:                        fatal("cgrep: -A and -l require a filename");
        !           618:                lex();
        !           619:        }
        !           620:        else {
        !           621:                while (optind < argc) {
        !           622:                        filen = argv[optind++];
        !           623:                        lex();
        !           624:                }
        !           625:        }
        !           626:        exit(0);
        !           627: }

unix.superglobalmegacorp.com

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