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.4 (Berkeley) 10/07/87"; 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 { 236 register char *p1, *p2; 237 register c; 238 int f; 239 char *ebp, *cbp; 240 static char *buf; 241 static int blksize; 242 struct stat stb; 243 244 if (file) { 245 if ((f = open(file, 0)) < 0) { 246 perror(file); 247 retcode = 2; 248 } 249 } else 250 f = 0; 251 if (buf == NULL) { 252 if (fstat(f, &stb) > 0 && stb.st_blksize > 0) 253 blksize = stb.st_blksize; 254 else 255 blksize = BLKSIZE; 256 buf = (char *)malloc(blksize); 257 if (buf == NULL) { 258 fprintf(stderr, "grep: no memory for %s\n", file); 259 retcode = 2; 260 return; 261 } 262 } 263 ebp = buf; 264 cbp = buf; 265 lnum = 0; 266 tln = 0; 267 blkno = -1; 268 for (;;) { 269 lnum++; 270 if((lnum&0377) == 0) 271 fflush(stdout); 272 p1 = linebuf; 273 p2 = cbp; 274 for (;;) { 275 if (p2 >= ebp) { 276 if ((c = read(f, buf, blksize)) <= 0) { 277 close(f); 278 if (cflag) { 279 if (lflag) { 280 if (tln) 281 printf("%s\n", file); 282 } else { 283 if (nfile > 1) 284 printf("%s:", file); 285 printf("%ld\n", tln); 286 } 287 } 288 return; 289 } 290 blkno++; 291 p2 = buf; 292 ebp = buf+c; 293 } 294 if ((c = *p2++) == '\n') 295 break; 296 if(c) 297 if (p1 < &linebuf[BUFSIZ-1]) 298 *p1++ = c; 299 } 300 *p1++ = 0; 301 cbp = p2; 302 p1 = linebuf; 303 p2 = expbuf; 304 if (circf) { 305 if (advance(p1, p2)) 306 goto found; 307 goto nfound; 308 } 309 /* fast check for first character */ 310 if (*p2==CCHR) { 311 c = p2[1]; 312 do { 313 if (*p1!=c && (!iflag || (c ^ *p1) != ' ' 314 || letter(c) != letter(*p1))) 315 continue; 316 if (advance(p1, p2)) 317 goto found; 318 } while (*p1++); 319 goto nfound; 320 } 321 /* regular algorithm */ 322 do { 323 if (advance(p1, p2)) 324 goto found; 325 } while (*p1++); 326 nfound: 327 if (vflag) 328 succeed(file); 329 continue; 330 found: 331 if (vflag==0) 332 succeed(file); 333 } 334 } 335 336 advance(alp, aep) 337 char *alp, *aep; 338 { 339 register char *lp, *ep, *curlp; 340 char *nextep; 341 342 lp = alp; 343 ep = aep; 344 for (;;) switch (*ep++) { 345 346 case CCHR: 347 if (!same(*ep, *lp)) 348 return (0); 349 ep++, lp++; 350 continue; 351 352 case CDOT: 353 if (*lp++) 354 continue; 355 return(0); 356 357 case CDOL: 358 if (*lp==0) 359 continue; 360 return(0); 361 362 case CEOF: 363 return(1); 364 365 case CCL: 366 if (cclass(ep, *lp++, 1)) { 367 ep += *ep; 368 continue; 369 } 370 return(0); 371 372 case NCCL: 373 if (cclass(ep, *lp++, 0)) { 374 ep += *ep; 375 continue; 376 } 377 return(0); 378 379 case CDOT|STAR: 380 curlp = lp; 381 while (*lp++); 382 goto star; 383 384 case CCHR|STAR: 385 curlp = lp; 386 while (same(*lp, *ep)) 387 lp++; 388 lp++; 389 ep++; 390 goto star; 391 392 case CCL|STAR: 393 case NCCL|STAR: 394 curlp = lp; 395 while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); 396 ep += *ep; 397 goto star; 398 399 star: 400 do { 401 lp--; 402 if (advance(lp, ep)) 403 return(1); 404 } while (lp > curlp); 405 return(0); 406 407 case CBRC: 408 if (lp == expbuf) 409 continue; 410 #define uletter(c) (letter(c) || c == '_') 411 if ( ( uletter(*lp) || digit ( * lp ) ) && !uletter(lp[-1]) && !digit(lp[-1])) 412 continue; 413 return (0); 414 415 case CLET: 416 if (!uletter(*lp) && !digit(*lp)) 417 continue; 418 return (0); 419 420 default: 421 fprintf(stderr, "grep: RE botch\n"); 422 exit(2); 423 } 424 } 425 426 cclass(aset, ac, af) 427 char *aset; 428 { 429 register char *set, c; 430 register n; 431 432 set = aset; 433 if ((c = ac) == 0) 434 return(0); 435 n = *set++; 436 while (--n) 437 if (n > 2 && set[1] == '-') { 438 if (c >= (set[0] & 0177) && c <= (set[2] & 0177)) 439 return (af); 440 set += 3; 441 n -= 2; 442 } else 443 if ((*set++ & 0177) == c) 444 return(af); 445 return(!af); 446 } 447 448 succeed(f) 449 { 450 nsucc = 1; 451 if (sflag) 452 return; 453 if (cflag) { 454 tln++; 455 return; 456 } 457 if (oflag || !hflag && nfile > 1) 458 printf("%s:", f); 459 if (bflag) 460 printf("%d:", blkno); 461 if (nflag) 462 printf("%ld:", lnum); 463 printf("%s\n", linebuf); 464 } 465 466 digit(c) 467 char c; 468 { 469 return (c>='0' && c<='9'); 470 } 471