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