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