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