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