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

Defined functions

advance defined in line 355; used 6 times
compile defined in line 158; used 1 times
ecmp defined in line 510; used 2 times
errexit defined in line 519; used 4 times
execute defined in line 290; used 2 times
main defined in line 67; never used
succeed defined in line 484; used 2 times

Defined variables

bflag defined in line 39; used 2 times
bittab defined in line 56; used 4 times
blkno defined in line 51; used 1 times
braelist defined in line 55; used 5 times
braslist defined in line 54; used 3 times
cflag defined in line 42; used 3 times
circf defined in line 50; used 2 times
expbuf defined in line 35; used 5 times
hflag defined in line 45; used 2 times
lflag defined in line 40; used 3 times
linebuf defined in line 37; used 4 times
lnum defined in line 36; used 3 times
nfile defined in line 44; used 3 times
nflag defined in line 41; used 2 times
nsucc defined in line 53; used 2 times
retcode defined in line 49; used 3 times
sccsid defined in line 2; never used
sflag defined in line 46; used 2 times
tln defined in line 52; used 3 times
vflag defined in line 43; used 3 times
wflag defined in line 48; used 3 times
ybuf defined in line 38; used 3 times
yflag defined in line 47; used 2 times

Defined macros

CBACK defined in line 27; used 2 times
CBRA defined in line 17; used 2 times
CBRC defined in line 25; used 3 times
CCHR defined in line 18; used 4 times
CCL defined in line 20; used 2 times
CDOL defined in line 22; used 1 times
CDOT defined in line 19; used 2 times
CEOF defined in line 23; used 1 times
CKET defined in line 24; used 2 times
CLET defined in line 26; used 3 times
ESIZE defined in line 32; used 5 times
LBSIZE defined in line 31; used 2 times
NBRA defined in line 33; used 4 times
NCCL defined in line 21; never used
STAR defined in line 29; used 1 times
uletter defined in line 468; used 3 times
Last modified: 1987-02-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4253
Valid CSS Valid XHTML 1.0 Strict