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