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: }