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