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

Defined functions

advance defined in line 324; used 6 times
compile defined in line 145; used 1 times
ecmp defined in line 464; used 2 times
errexit defined in line 473; used 5 times
execute defined in line 262; used 2 times
main defined in line 59; never used
succeed defined in line 439; used 2 times

Defined variables

bflag defined in line 34; used 2 times
bittab defined in line 48; used 4 times
braelist defined in line 47; used 5 times
braslist defined in line 46; used 3 times
cflag defined in line 37; used 3 times
circf defined in line 43; used 2 times
expbuf defined in line 30; used 4 times
hflag defined in line 40; used 2 times
lflag defined in line 35; used 3 times
linebuf defined in line 32; used 4 times
lnum defined in line 31; used 3 times
nfile defined in line 39; used 3 times
nflag defined in line 36; used 2 times
nsucc defined in line 45; used 2 times
sflag defined in line 41; used 2 times
tln defined in line 44; used 3 times
vflag defined in line 38; used 3 times
ybuf defined in line 33; used 3 times
yflag defined in line 42; used 2 times

Defined macros

CBACK defined in line 22; used 2 times
CBRA defined in line 14; used 2 times
CCHR defined in line 15; used 4 times
CCL defined in line 17; used 2 times
CDOL defined in line 19; used 1 times
CDOT defined in line 16; used 2 times
CEOF defined in line 20; used 1 times
CKET defined in line 21; used 2 times
ESIZE defined in line 27; used 5 times
LBSIZE defined in line 26; used 2 times
NBRA defined in line 28; used 4 times
NCCL defined in line 18; never used
STAR defined in line 24; used 1 times
Last modified: 1979-02-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1379
Valid CSS Valid XHTML 1.0 Strict