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