Annotation of coherent/b/bin/cgrep.c, revision 1.1.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:  * -R Replaces all occurances of the pattern with a new after the following
                     71:  *    substitutions. & is the whole pattern found. \1 is the first
                     72:  *    parenthesized subexpression, \2 the second etc.
                     73:  *
                     74:  * -d token. Take following string and comment. For documentation extraction.
                     75:  *    use the first char of the token as an output delimeter.
                     76:  *
                     77:  * -C token. Use token as delimeter -c option.
                     78:  */
                     79: #include <ctype.h>
                     80: #include <stdio.h>
                     81: #include <misc.h>
                     82: 
                     83: /*
                     84:  * Cgrep never runs out of room on lines or buffers until malloc fails
                     85:  * these are buffer expanders.
                     86:  */
                     87: #define TROOM(buf, has, needs) while ((needs) >= has) \
                     88:  if (NULL == (buf = realloc(buf, sizeof(*buf) * (has += 10)))) \
                     89:   fatal(outSpace)
                     90: 
                     91: #define ROOM(buf, has, needs)  while ((needs) >= has) \
                     92:  if (NULL == (buf = realloc(buf, has += 512))) \
                     93:   fatal(outSpace)
                     94: 
                     95: extern char *realloc();
                     96: static char outSpace[] = "cgrep: out of space";
                     97: 
                     98: struct token { /* collected token array */
                     99:        int start;      /* token index on buff */
                    100:        int atline;     /* line number where token spotted */
                    101: };
                    102: 
                    103: enum fstate {  /* lexical processing state */
                    104:        start,
                    105:        slash,          /* slash encountered in normal state */
                    106:        comment,        /* in comment */
                    107:        cppcom,         /* in cpp comment */
                    108:        star,           /* * in comment */
                    109:        bsl,            /* back slash */
                    110:        dquote,         /* double quote */
                    111:        squote,         /* single quote */
                    112:        token,          /* c word */
                    113:        minus           /* - maybe -> */
                    114: };
                    115: 
                    116: enum wstate { /* word processing states */
                    117:        word,   /* some c identifier */
                    118:        dot,    /* . or -> */
                    119:        other   /* anything else */
                    120: };
                    121: 
                    122: /* cgrep has no fixed size arrays only growable buffers */
                    123: static char *buff = NULL;      /* accumulate stuff */
                    124: static int buffLen;            /* buffer length */
                    125: 
                    126: static struct token *tokens = NULL; /* token array */
                    127: static int tokenLen;           /* size of token array */
                    128: 
                    129: static char *line;             /* expandable input line */
                    130: static int  lineLen;           /* current length of input line */
                    131: 
                    132: static char lswitch;           /* list files found */
                    133: static char aswitch;           /* call emacs with line list */
                    134: static char dswitch;           /* special for docs */
                    135: static char dtoken[80];                /* token copy for dswitch */
                    136: static char nswitch;           /* print line number */
                    137: static char sswitch;           /* print all strings */
                    138: static char cswitch;           /* print all comments */
                    139: static char rswitch;           /* replace found pattern */
                    140: static char Rswitch;           /* do substition magic */
                    141: 
                    142: static regexp *pat;            /* a compiled regular expression */
                    143: 
                    144: static char *newstr;           /* The new string with rswitch */
                    145: 
                    146: static char *filen = NULL;     /* the file currently being processed */
                    147: static char *tname = NULL;     /* temp file name */
                    148: static FILE *tfp;              /* tmp file pointer */
                    149: 
                    150: static int lineno;             /* current line number */
                    151: static int marked;             /* 1 if pattern found on line. */
                    152: 
                    153: static int matched;            /* 1 if any match found. */
                    154: 
                    155: /*
                    156:  * Character types table
                    157:  * for the ASCII character set modified to see _ as alpha.
                    158:  * _ctype[0] is for EOF, the rest if indexed
                    159:  * by the ascii values of the characters.
                    160:  */
                    161: static unsigned char _ctype[] = {
                    162:        0,      /* EOF */
                    163:        _C, _C, _C, _C, _C, _C, _C, _C,
                    164:        _C, _S|_C, _S|_C, _S|_C, _S|_C, _S|_C, _C, _C,
                    165:        _C, _C, _C, _C, _C, _C, _C, _C,
                    166:        _C, _C, _C, _C, _C, _C, _C, _C,
                    167:        _S|_X, _P, _P, _P, _P, _P, _P, _P,
                    168:        _P, _P, _P, _P, _P, _P, _P, _P,
                    169:        _N, _N, _N, _N, _N, _N, _N, _N,
                    170:        _N, _N, _P, _P, _P, _P, _P, _P,
                    171:        _P, _U, _U, _U, _U, _U, _U, _U,
                    172:        _U, _U, _U, _U, _U, _U, _U, _U,
                    173:        _U, _U, _U, _U, _U, _U, _U, _U,
                    174:        _U, _U, _U, _P, _P, _P, _P, _L,
                    175:        _P, _L, _L, _L, _L, _L, _L, _L,
                    176:        _L, _L, _L, _L, _L, _L, _L, _L,
                    177:        _L, _L, _L, _L, _L, _L, _L, _L,
                    178:        _L, _L, _L, _P, _P, _P, _P, _C,
                    179:        _C, _C, _C, _C, _C, _C, _C, _C,
                    180:        _C, _C, _C, _C, _C, _C, _C, _C,
                    181:        _C, _C, _C, _C, _C, _C, _C, _C,
                    182:        _C, _C, _C, _C, _C, _C, _C, _C,
                    183:        _C, _C, _C, _C, _C, _C, _C, _C,
                    184:        _C, _C, _C, _C, _C, _C, _C, _C,
                    185:        _C, _C, _C, _C, _C, _C, _C, _C,
                    186:        _C, _C, _C, _C, _C, _C, _C, _C,
                    187:        _C, _C, _C, _C, _C, _C, _C, _C,
                    188:        _C, _C, _C, _C, _C, _C, _C, _C,
                    189:        _C, _C, _C, _C, _C, _C, _C, _C,
                    190:        _C, _C, _C, _C, _C, _C, _C, _C,
                    191:        _C, _C, _C, _C, _C, _C, _C, _C,
                    192:        _C, _C, _C, _C, _C, _C, _C, _C,
                    193:        _C, _C, _C, _C, _C, _C, _C, _C,
                    194:        _C, _C, _C, _C, _C, _C, _C, _C
                    195: };
                    196: 
                    197: /*
                    198:  * Report errors for public domain regexp package.
                    199:  */
                    200: void
                    201: regerror(s)
                    202: char *s;
                    203: {
                    204:        fatal("cgrep: pattern error %s\n", s);
                    205: }
                    206: 
                    207: /*
                    208:  * Pattern found with -A mode. It is assumed that users of
                    209:  * this mode will want to know about all hits on a line.
                    210:  */
                    211: static void
                    212: emacsLine(found, atline)
                    213: char *found;
                    214: {
                    215:        extern char *tempnam();
                    216: 
                    217:        /* if tmp file not opened open it. */
                    218:        if ((NULL == tname) &&
                    219:            ((NULL == (tname = tempnam(NULL, "cgr"))) ||
                    220:              (NULL == (tfp = fopen(tname, "w")))))
                    221:                fatal("cgrep: Cannot open tmp file");
                    222:        fprintf(tfp, "%d: %s: found '%s'\n", atline, filen, found);
                    223: }
                    224: 
                    225: /*
                    226:  * When we get a word, dot, arrow or other we come here.
                    227:  *
                    228:  * cgrep accumulates things like ptr->memb.x in buff.
                    229:  * as these are accumulated it is nessisary to match buff
                    230:  * against the regular expression one slice at a time
                    231:  * that is when the x in ptr->memb.x was found cgrep would check
                    232:  * ptr->memb.x then memb.x then x
                    233:  * against the pattern. Thus memb.x matches ptr->memb.x
                    234:  */
                    235: static void
                    236: gota(got, what)
                    237: register enum wstate got;      /* what we have */
                    238: char *what;            /* the string we have or NULL */
                    239: {
                    240:        static int tokenCt;         /* number of tokens */
                    241:        static enum wstate state;   /* current word processing state */
                    242:        static int wlen, blen;      /* strlen(what) and strlen(buff) + 1 */
                    243:        int i;
                    244: 
                    245:        if (sswitch || cswitch)
                    246:                return;
                    247: 
                    248:        if (rswitch) {  /* replace mode works on tokens only */
                    249:                marked = (word == got) && regexec(pat, what);
                    250:                matched |= marked;
                    251:                return;
                    252:        }
                    253: 
                    254:        switch (got) {
                    255:        case word:
                    256:                wlen = strlen(what);
                    257:                switch (state) {
                    258:                case other:
                    259:                case word:
                    260:                        /* store start and line number of token */
                    261:                        tokenCt = 1;
                    262:                        TROOM(tokens, tokenLen, tokenCt);
                    263:                        tokens[0].start = 0;
                    264:                        tokens[0].atline = lineno;
                    265: 
                    266:                        /* store token */
                    267:                        blen = wlen;
                    268:                        ROOM(buff, buffLen, blen);
                    269:                        strcpy(buff, what);
                    270:                        break;
                    271:                case dot:
                    272:                        /* store start and line number of token */
                    273:                        TROOM(tokens, tokenLen, tokenCt);
                    274:                        tokens[tokenCt].start = blen;
                    275:                        tokens[tokenCt++].atline = lineno;
                    276: 
                    277:                        /* store token */
                    278:                        blen += wlen;
                    279:                        ROOM(buff, buffLen, blen);
                    280:                        strcat(buff, what);
                    281:                }
                    282: 
                    283:                /* Check the accumulated token for matches */
                    284:                for (i = 0; i < tokenCt; i++) {
                    285:                        char *p;
                    286: 
                    287:                        if (regexec(pat, p = buff + tokens[i].start)) {
                    288:                                if (aswitch)
                    289:                                        emacsLine(p, tokens[i].atline);
                    290:                                else {
                    291:                                        marked = 1;
                    292:                                        matched = 1;
                    293:                                        if (dswitch) {
                    294:                                                strcpy(dtoken, p);
                    295:                                                cswitch = sswitch = 1;
                    296:                                        }
                    297:                                        break;
                    298:                                }
                    299:                        }
                    300:                }
                    301: 
                    302:                state = got;
                    303:                break;
                    304: 
                    305:        case dot:
                    306:                if (word == state) {
                    307:                        blen += strlen(what);
                    308:                        ROOM(buff, buffLen, blen);
                    309:                        strcat(buff, what);
                    310:                        state = got;
                    311:                        break;
                    312:                }
                    313:        case other:
                    314:                state = other;
                    315:        }
                    316: }
                    317: 
                    318: /*
                    319:  * call emacs with file and tmpfile.
                    320:  */
                    321: static void
                    322: callEmacs()
                    323: {
                    324: #ifdef GEMDOS
                    325: #include <path.h>
                    326:        extern  char *path(), *getenv();
                    327:        extern char **environ;
                    328:        static char* cmda[5] = { NULL, "-e", NULL, NULL, NULL };
                    329: #endif
                    330:        int quit;
                    331: 
                    332:        fclose(tfp);
                    333: #ifdef MSDOS
                    334:        sprintf(line, "-e %s %s", tname, filen);
                    335:        if (0x7f == (quit = execall("me", line)))
                    336: #endif
                    337: #ifdef COHERENT
                    338:        sprintf(line, "me -e %s %s ", tname, filen);
                    339:        if (0x7f == (quit = system(line)))
                    340: #endif
                    341: #ifdef GEMDOS
                    342:        cmda[2] = tname;
                    343:        cmda[3] = filen;
                    344:        if ((NULL == cmda[0]) &&
                    345:           (NULL == (cmda[0] = path(getenv("PATH"), "me.tos", 1))))
                    346:                fatal("cgrep: Cannot locate me.tos\n");
                    347:        else if ((quit = execve(cmda[0], cmda, environ)) < 0)
                    348: #endif
                    349:                fatal("cgrep: cannot execute 'me'");
                    350:        unlink(tname);
                    351:        free(tname);
                    352:        tname = NULL;
                    353:        if (quit)
                    354:                exit(0);
                    355: }
                    356: 
                    357: /*
                    358:  * find first word in a string excluding printf % constructs.
                    359:  * make it lower case and return it.
                    360:  */
                    361: static char *
                    362: firstWord(p)
                    363: char *p;
                    364: {
                    365:        static char buf[80];
                    366:        char *out, c;
                    367:        enum state { start, pct, name } state;
                    368: 
                    369:        out = NULL;
                    370:        for (state = start; c = *p++;) {
                    371:                switch(state) {
                    372:                case start:
                    373:                        if (isalpha(c)) {
                    374:                                state = name;
                    375:                                out = buf;
                    376:                                *out++ = tolower(c);
                    377:                                continue;
                    378:                        }
                    379:                        if ('%' == c)
                    380:                                state = pct;
                    381:                        continue;
                    382: 
                    383:                case pct:
                    384:                        if (isalpha(c) && 'l' != c)
                    385:                                state = start;
                    386:                        continue;
                    387: 
                    388:                case name:
                    389:                        if (isalnum(c)) {
                    390:                                *out++ = tolower(c);
                    391:                                continue;
                    392:                        }
                    393:                        *out = '\0'; 
                    394:                        return (buf);
                    395:                }
                    396:        }                       
                    397:        if (NULL == out)
                    398:                return ("???");
                    399:        *out = '\0';
                    400:        return (buf);
                    401: }
                    402: 
                    403: /*
                    404:  * print a hit for options -s or -c. Option -d creates -s and -c.
                    405:  */
                    406: static void
                    407: printx(s, sw)
                    408: register char *s;
                    409: {
                    410:        register char c, *p;
                    411: 
                    412:        if (aswitch)
                    413:                emacsLine(s, lineno);
                    414:        else if (cswitch > 1) {
                    415:                for (p = s; (c = *p) && isspace(c); p++)
                    416:                        ;
                    417:                if ('*' == c)
                    418:                        s = p + 1;
                    419: 
                    420:                printf("%s", s);
                    421:                putchar(sw ? cswitch : '\n');
                    422:        }
                    423:        else if (dswitch) {
                    424:                for (p = s; (c = *p) && isspace(c); p++)
                    425:                        ;
                    426:                if ('*' == c)
                    427:                        s = p + 1;
                    428: 
                    429:                if (dtoken[0]) {
                    430:                        printf("%s%c%s%c%s",
                    431:                                firstWord(s), dswitch, s, dswitch, dtoken);
                    432:                        dtoken[0] = '\0';
                    433:                }
                    434:                else
                    435:                        printf("%s", s);
                    436:                putchar(cswitch ? dswitch : '\n');
                    437:        }
                    438:        else {
                    439:                if (NULL != filen)
                    440:                        printf("%s: ", filen);
                    441:                if (nswitch)
                    442:                        printf("%4d: ", lineno);
                    443:                printf("%s\n", s);
                    444:        }
                    445: }
                    446: 
                    447: /*
                    448:  * Lexically process a file.
                    449:  */
                    450: static void
                    451: lex()
                    452: {
                    453:        int  c, i;
                    454:        enum fstate state, pstate;
                    455:        char *w, changed;
                    456:        FILE *ifp, *tfp;
                    457: 
                    458:        if (NULL == filen)
                    459:                ifp = stdin;
                    460:        else if (NULL == (ifp = fopen(filen, "r"))) {
                    461:                fprintf(stderr, "cgrep: warning cannot open %s\n", filen);
                    462:                return;
                    463:        }
                    464: 
                    465:        if (rswitch) {
                    466:                changed = 0;    /* no changes so far */
                    467: 
                    468:                if (NULL == filen)
                    469:                        tfp = stdout;
                    470:                else if ((NULL == (tname = tempnam(NULL, "cse"))) ||
                    471:                         (NULL == (tfp = fopen(tname, "w"))))
                    472:                        fatal("cgrep: Cannot open tmp file");
                    473:        }
                    474: 
                    475:        lineno = 1;
                    476:        i = marked = 0;
                    477:        gota(other, NULL);      /* initialize word machine */
                    478: 
                    479:        for (state = start; ; ) {
                    480:                line[i] = '\0';
                    481:                c = fgetc(ifp);
                    482: 
                    483:                switch (state) {
                    484:                case minus:
                    485:                        if ('>' == c) {
                    486:                                gota(dot, "->");
                    487:                                state = start;
                    488:                                break;
                    489:                        }
                    490:                        goto isstart;
                    491:                case token:
                    492:                        if (isalnum(c))
                    493:                                break;
                    494:                        gota(word, w);
                    495: 
                    496:                        /* we have a word to replace */
                    497:                        if (rswitch && marked) {
                    498:                                if(Rswitch) {
                    499:                                        char buf[80];
                    500: 
                    501:                                        regsub(pat, newstr, buf);
                    502:                                        i += strlen(buf) - strlen(w);
                    503:                                        ROOM(line, lineLen, i);
                    504:                                        strcpy(w, buf);
                    505:                                } else {
                    506:                                        i += strlen(newstr) - strlen(w);
                    507:                                        ROOM(line, lineLen, i);
                    508:                                        strcpy(w, newstr);
                    509:                                }
                    510:                                changed = 1;
                    511:                        }
                    512: isstart:               state = start;
                    513:                case start:
                    514:                        switch (c) {
                    515:                        case '.':
                    516:                                gota(dot, ".");
                    517:                                break;
                    518:                        case '-':
                    519:                                state = minus;
                    520:                                break;
                    521:                        case '/':
                    522:                                state = slash;
                    523:                                break;
                    524:                        case '\\':
                    525:                                pstate = state;
                    526:                                state = bsl;
                    527:                                break;
                    528:                        case '"':
                    529:                                w = line + i;
                    530:                                state = dquote;
                    531:                                break;
                    532:                        case '\'':
                    533:                                state = squote;
                    534:                                break;
                    535:                        default:
                    536:                                if (isalpha(c)) {
                    537:                                        w = line + i;
                    538:                                        state = token;
                    539:                                }
                    540:                                else if (!isspace(c))
                    541:                                        gota(other, NULL);
                    542:                        }
                    543:                        break;
                    544: 
                    545:                case slash:
                    546:                        switch (c) {
                    547:                        case '*':
                    548:                                state = comment;
                    549:                                w = line + i + 1;
                    550:                                break;
                    551:                        case '/':
                    552:                                state = cppcom;
                    553:                                w = line + i + 1;
                    554:                                break;
                    555:                        default:
                    556:                                goto isstart;
                    557:                        }
                    558:                        break;
                    559: 
                    560:                case cppcom:
                    561:                        if ('\n' == c) {
                    562:                                if (cswitch) { /* report comment */
                    563:                                        if (dswitch)
                    564:                                                cswitch = 0;
                    565:                                        line[i] = '\0';
                    566:                                        printx(w, 0);
                    567:                                        line[i] = '\n';
                    568:                                }
                    569:                                state = start;
                    570:                        }                               
                    571:                        break;
                    572: 
                    573:                case star:
                    574:                        if ('/' == c) {
                    575:                                if (cswitch) { /* report comment */
                    576:                                        if (dswitch)
                    577:                                                cswitch = 0;
                    578:                                        line[i - 1] = '\0';
                    579:                                        printx(w, 0);
                    580:                                        line[i - 1] = '*';
                    581:                                }
                    582:                                state = start;
                    583:                                break;
                    584:                        }
                    585:                        state = comment;
                    586:                case comment:
                    587:                        if ('*' == c)
                    588:                                state = star;
                    589:                        break;
                    590:                case bsl:
                    591:                        state = pstate;
                    592:                        break;
                    593:                case dquote:
                    594:                        switch (c) {
                    595:                        case '"':
                    596:                        case '\n':
                    597:                                state = start;
                    598:                                if (sswitch) {
                    599:                                        if (dswitch)
                    600:                                                sswitch = 0;
                    601:                                        printx(w + 1, 0);
                    602:                                }
                    603:                                else
                    604:                                        gota(other, NULL);
                    605:                                break;
                    606:                        case '\\':
                    607:                                pstate = state;
                    608:                                state  = bsl;
                    609:                                break;
                    610:                        }
                    611:                        break;
                    612:                case squote:
                    613:                        switch (c) {
                    614:                        case '\'':
                    615:                        case '\n':
                    616:                                gota(other, NULL);
                    617:                                state = start;
                    618:                                break;
                    619:                        case '\\':
                    620:                                pstate = state;
                    621:                                state  = bsl;
                    622:                                break;
                    623:                        }
                    624:                        break;
                    625:                }
                    626:                if (('\n' != c) && (EOF != c)) {
                    627:                        line[i++] = c;
                    628:                        ROOM(line, lineLen, i);
                    629:                }
                    630:                else {  /* end of line */
                    631:                        if (rswitch) {
                    632:                                if (EOF == c) {
                    633:                                        if (!i) /* null line */
                    634:                                                break;
                    635:                                }
                    636:                                else
                    637:                                        line[i++] = c;
                    638:                                ROOM(line, lineLen, i);
                    639:                                line[i] = 0;
                    640:                                fputs(line, tfp);
                    641:                                marked = 0;
                    642:                        }
                    643: 
                    644:                        if (cswitch && (comment == state)) {
                    645:                                printx(w, 1);
                    646:                                w = line;
                    647:                        }
                    648: 
                    649:                        if (marked && !dswitch) {
                    650:                                if (lswitch) {
                    651:                                        printf("%s\n", filen);
                    652:                                        break;
                    653:                                }
                    654:                                printx(line, 0);
                    655:                        }
                    656: 
                    657:                        lineno++;
                    658:                        marked = i = 0;
                    659:                        if (EOF == c)
                    660:                                break;
                    661:                }
                    662:        }
                    663: 
                    664:        fclose(ifp);
                    665: 
                    666:        if (rswitch) {
                    667:                fclose(tfp);
                    668: 
                    669:                if (NULL != filen) {    /* tmp file used */
                    670:                        if (changed) {
                    671:                                unlink(filen);
                    672:                                sprintf(line, "mv %s %s", tname, filen);
                    673:                                system(line);
                    674:                        }
                    675:                        else
                    676:                                unlink(tname);
                    677:                }
                    678:        }
                    679: 
                    680:        if (aswitch && (NULL != tname)) /* tmp file opened for -A option */
                    681:                callEmacs();
                    682: }
                    683: 
                    684: main(argc, argv)
                    685: int argc;
                    686: register char **argv;
                    687: {
                    688:        register char c;
                    689:        int errsw = 0;
                    690:        static char msg[] = 
                    691:                "cgrep [-[rR] newStr] [-clnsA] [pattern] filename ...";
                    692:        char *p, *q;
                    693:        extern int optind;
                    694:        extern char *optarg;
                    695: 
                    696:        if (1 == argc)
                    697:                usage(msg);
                    698: 
                    699:        while (EOF != (c = getopt(argc, argv, "cC:d:slnA?r:R:V"))) {
                    700:                switch (c) {
                    701:                case 'V':
                    702:                        printf("cgrep version 1.2\n");
                    703:                        exit(0);
                    704:                case 'C':
                    705:                        cswitch = *optarg;      /* get delimiter */
                    706:                        break;
                    707:                case 'c':
                    708:                        cswitch = 1;    /* comments only */
                    709:                        break;
                    710:                case 'd': /* report following string & comment */
                    711:                        dswitch = *optarg;
                    712:                        break;
                    713:                case 's':
                    714:                        sswitch = 1;    /* strings only */
                    715:                        break;
                    716:                case 'l':
                    717:                        lswitch = 1;    /* print filenames only */
                    718:                        break;
                    719:                case 'n':
                    720:                        nswitch = 1;    /* print line numbers */
                    721:                        break;
                    722:                case 'A':
                    723:                        aswitch = 1;    /* interact with emacs */
                    724:                        break;
                    725:                case 'R':
                    726:                        Rswitch = 1;    /* do substitution magic */
                    727:                        for (p = optarg; *p; p++)
                    728:                                if('\\' == *p && (p[1] <= '8') && (p[1] > '0'))
                    729:                                        p[1]++;
                    730:                case 'r':
                    731:                        rswitch = 1;    /* replace hits */
                    732:                        newstr = optarg;
                    733:                        break;
                    734:                default:
                    735:                        errsw = 1;
                    736:                }
                    737:        }
                    738: 
                    739:        /* check unknown switches and rswitch goes with no other switches */
                    740:        if (errsw || 
                    741:            (rswitch && (aswitch | nswitch | lswitch | cswitch | sswitch)))
                    742:                usage(msg);
                    743: 
                    744:        if (!sswitch && !cswitch) {     /* process pattern */
                    745:                if (optind == argc)             /* no pattern */
                    746:                        usage(msg);
                    747: 
                    748:                /* inclose pattern in ^(  )$ to force full match */
                    749:                p = alloc(5 + strlen(q = argv[optind++]));
                    750:                sprintf(p, "^(%s)$", q);
                    751:                if (NULL == (pat = regcomp(p)))
                    752:                        fatal("cgrep: Illegal pattern\n");
                    753:        }
                    754: 
                    755:        ROOM(line, lineLen, 1); /* get input line started */
                    756: 
                    757:        if (optind == argc) {
                    758:                if (aswitch | lswitch)
                    759:                        fatal("cgrep: -A and -l require a filename");
                    760:                lex();
                    761:        }
                    762:        else {
                    763:                while (optind < argc) {
                    764:                        filen = argv[optind++];
                    765:                        lex();
                    766:                }
                    767:        }
                    768:        exit(! matched);
                    769: }

unix.superglobalmegacorp.com

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