1 #ifndef lint 2 static char sccsid[] = "@(#)old.ucb.grep.c 4.5 (Berkeley) 05/30/85"; 3 #endif 4 5 #include <stdio.h> 6 #include <sys/types.h> 7 #include <sys/stat.h> 8 /* 9 * grep -- print lines matching (or not matching) a pattern 10 */ 11 12 #define BLKSIZE 8192 13 #define CCHR 2 14 #define CDOT 4 15 #define CCL 6 16 #define NCCL 8 17 #define CDOL 10 18 #define CEOF 11 19 20 #define CBRC 14 21 #define CLET 15 22 #define STAR 01 23 24 #define ESIZE 256 25 26 char expbuf[ESIZE]; 27 long lnum; 28 char linebuf[BUFSIZ+1]; 29 int bflag; 30 int nflag; 31 int cflag; 32 int vflag; 33 int nfile; 34 int iflag; 35 int lflag; 36 int wflag; 37 int sflag; 38 int nsucc; 39 int circf; 40 int blkno; 41 long tln; 42 43 main(argc, argv) 44 char **argv; 45 { 46 47 while (--argc > 0 && (++argv)[0][0]=='-') { 48 char *cp = argv[0] + 1; 49 while (*cp) switch (*cp++) { 50 51 case 'v': 52 vflag++; 53 continue; 54 55 case 'b': 56 bflag++; 57 continue; 58 59 case 'i': 60 case 'y': /* -y for compatibility with btl grep */ 61 iflag++; 62 continue; 63 64 case 'l': 65 lflag++; 66 case 'c': 67 cflag++; 68 continue; 69 70 case 'w': 71 wflag++; 72 continue; 73 74 case 's': 75 sflag++; 76 continue; 77 78 case 'n': 79 nflag++; 80 continue; 81 82 case 'e': 83 --argc; 84 ++argv; 85 goto out; 86 87 default: 88 fprintf(stderr, "Unknown flag\n"); 89 continue; 90 } 91 } 92 out: 93 if (argc<=0) 94 exit(2); 95 compile(*argv); 96 nfile = --argc; 97 if (argc<=0) { 98 if (lflag) 99 exit(1); 100 execute(0); 101 } 102 else while (--argc >= 0) { 103 argv++; 104 execute(*argv); 105 } 106 exit(nsucc == 0); 107 } 108 109 compile(astr) 110 char *astr; 111 { 112 register c; 113 register char *ep, *sp; 114 char *lastep; 115 int cclcnt; 116 117 ep = expbuf; 118 sp = astr; 119 if (*sp == '^') { 120 circf++; 121 sp++; 122 } 123 if (wflag) 124 *ep++ = CBRC; 125 for (;;) { 126 if (ep >= &expbuf[ESIZE]) 127 goto cerror; 128 if ((c = *sp++) != '*') 129 lastep = ep; 130 switch (c) { 131 132 case '\0': 133 if (wflag) 134 *ep++ = CLET; 135 *ep++ = CEOF; 136 return; 137 138 case '.': 139 *ep++ = CDOT; 140 continue; 141 142 case '*': 143 if (lastep==0) 144 goto defchar; 145 *lastep |= STAR; 146 continue; 147 148 case '$': 149 if (*sp != '\0') 150 goto defchar; 151 *ep++ = CDOL; 152 continue; 153 154 case '[': 155 *ep++ = CCL; 156 *ep++ = 0; 157 cclcnt = 1; 158 if ((c = *sp++) == '^') { 159 c = *sp++; 160 ep[-2] = NCCL; 161 } 162 do { 163 *ep++ = c; 164 cclcnt++; 165 if (c=='\0' || ep >= &expbuf[ESIZE]) 166 goto cerror; 167 } while ((c = *sp++) != ']'); 168 lastep[1] = cclcnt; 169 continue; 170 171 case '\\': 172 if ((c = *sp++) == '\0') 173 goto cerror; 174 if (c == '<') { 175 *ep++ = CBRC; 176 continue; 177 } 178 if (c == '>') { 179 *ep++ = CLET; 180 continue; 181 } 182 defchar: 183 default: 184 *ep++ = CCHR; 185 *ep++ = c; 186 } 187 } 188 cerror: 189 fprintf(stderr, "RE error\n"); 190 } 191 192 same(a, b) 193 register int a, b; 194 { 195 196 return (a == b || iflag && (a ^ b) == ' ' && letter(a) == letter(b)); 197 } 198 199 letter(c) 200 register int c; 201 { 202 203 if (c >= 'a' && c <= 'z') 204 return (c); 205 if (c >= 'A' && c <= 'Z') 206 return (c + 'a' - 'A'); 207 return (0); 208 } 209 210 execute(file) 211 { 212 register char *p1, *p2; 213 register c; 214 int f; 215 char *ebp, *cbp; 216 static char *buf; 217 static int blksize; 218 struct stat stb; 219 220 if (file) { 221 if ((f = open(file, 0)) < 0) { 222 perror(file); 223 } 224 } else 225 f = 0; 226 if (buf == NULL) { 227 if (fstat(f, &stb) > 0 && stb.st_blksize > 0) 228 blksize = stb.st_blksize; 229 else 230 blksize = BLKSIZE; 231 buf = (char *)malloc(blksize); 232 if (buf == NULL) { 233 fprintf(stderr, "egrep: no memory for %s\n", file); 234 return; 235 } 236 } 237 ebp = buf; 238 cbp = buf; 239 lnum = 0; 240 tln = 0; 241 blkno = -1; 242 for (;;) { 243 lnum++; 244 if((lnum&0377) == 0) 245 fflush(stdout); 246 p1 = linebuf; 247 p2 = cbp; 248 for (;;) { 249 if (p2 >= ebp) { 250 if ((c = read(f, buf, blksize)) <= 0) { 251 close(f); 252 if (cflag) { 253 if (lflag) { 254 if (tln) 255 printf("%s\n", file); 256 } else { 257 if (nfile > 1) 258 printf("%s:", file); 259 printf("%ld\n", tln); 260 } 261 } 262 return; 263 } 264 blkno++; 265 p2 = buf; 266 ebp = buf+c; 267 } 268 if ((c = *p2++) == '\n') 269 break; 270 if(c) 271 if (p1 < &linebuf[BUFSIZ-1]) 272 *p1++ = c; 273 } 274 *p1++ = 0; 275 cbp = p2; 276 p1 = linebuf; 277 p2 = expbuf; 278 if (circf) { 279 if (advance(p1, p2)) 280 goto found; 281 goto nfound; 282 } 283 /* fast check for first character */ 284 if (*p2==CCHR) { 285 c = p2[1]; 286 do { 287 if (*p1!=c && (!iflag || (c ^ *p1) != ' ' 288 || letter(c) != letter(*p1))) 289 continue; 290 if (advance(p1, p2)) 291 goto found; 292 } while (*p1++); 293 goto nfound; 294 } 295 /* regular algorithm */ 296 do { 297 if (advance(p1, p2)) 298 goto found; 299 } while (*p1++); 300 nfound: 301 if (vflag) 302 succeed(file); 303 continue; 304 found: 305 if (vflag==0) 306 succeed(file); 307 } 308 } 309 310 advance(alp, aep) 311 char *alp, *aep; 312 { 313 register char *lp, *ep, *curlp; 314 char *nextep; 315 316 lp = alp; 317 ep = aep; 318 for (;;) switch (*ep++) { 319 320 case CCHR: 321 if (!same(*ep, *lp)) 322 return (0); 323 ep++, lp++; 324 continue; 325 326 case CDOT: 327 if (*lp++) 328 continue; 329 return(0); 330 331 case CDOL: 332 if (*lp==0) 333 continue; 334 return(0); 335 336 case CEOF: 337 return(1); 338 339 case CCL: 340 if (cclass(ep, *lp++, 1)) { 341 ep += *ep; 342 continue; 343 } 344 return(0); 345 346 case NCCL: 347 if (cclass(ep, *lp++, 0)) { 348 ep += *ep; 349 continue; 350 } 351 return(0); 352 353 case CDOT|STAR: 354 curlp = lp; 355 while (*lp++); 356 goto star; 357 358 case CCHR|STAR: 359 curlp = lp; 360 while (same(*lp, *ep)) 361 lp++; 362 lp++; 363 ep++; 364 goto star; 365 366 case CCL|STAR: 367 case NCCL|STAR: 368 curlp = lp; 369 while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); 370 ep += *ep; 371 goto star; 372 373 star: 374 do { 375 lp--; 376 if (advance(lp, ep)) 377 return(1); 378 } while (lp > curlp); 379 return(0); 380 381 case CBRC: 382 if (lp == expbuf) 383 continue; 384 #define uletter(c) (letter(c) || c == '_') 385 if ( ( uletter(*lp) || digit ( * lp ) ) && !uletter(lp[-1]) && !digit(lp[-1])) 386 continue; 387 return (0); 388 389 case CLET: 390 if (!uletter(*lp) && !digit(*lp)) 391 continue; 392 return (0); 393 394 default: 395 fprintf(stderr, "RE botch\n"); 396 } 397 } 398 399 cclass(aset, ac, af) 400 char *aset; 401 { 402 register char *set, c; 403 register n; 404 405 set = aset; 406 if ((c = ac) == 0) 407 return(0); 408 n = *set++; 409 while (--n) 410 if (n > 2 && set[1] == '-') { 411 if (c >= (set[0] & 0177) && c <= (set[2] & 0177)) 412 return (af); 413 set += 3; 414 n -= 2; 415 } else 416 if ((*set++ & 0177) == c) 417 return(af); 418 return(!af); 419 } 420 421 succeed(f) 422 { 423 nsucc = 1; 424 if (sflag) 425 return; 426 if (cflag) { 427 tln++; 428 return; 429 } 430 if (nfile > 1) 431 printf("%s:", f); 432 if (bflag) 433 printf("%d:", blkno); 434 if (nflag) 435 printf("%ld:", lnum); 436 printf("%s\n", linebuf); 437 } 438 439 digit(c) 440 char c; 441 { 442 return (c>='0' && c<='9'); 443 } 444