|
|
1.1 ! root 1: /* ! 2: * Grep - search a file for a pattern ! 3: * This code uses the regexp.c code which is ! 4: * also used by AWK. ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <ctype.h> ! 9: #include "grep.h" ! 10: ! 11: #define MAXLINE 400 /* Maximum input line length */ ! 12: #define NEXP 50 /* Maximum number of regular expressions */ ! 13: #define BSIZE BUFSIZ /* Assume block size if buffer size */ ! 14: ! 15: char line[MAXLINE]; ! 16: struct exps { ! 17: union { ! 18: char *u_cp; ! 19: RE *u_re; ! 20: } e_un; ! 21: int (*e_mfun)(); ! 22: } exps[NEXP+1]; ! 23: char usage[] = ! 24: "Usage: grep [-abchlnsvxy] [-e exp] [-f efile] [expression] [file ...]"; ! 25: char mre[] = "Missing regular expression"; ! 26: char nospace[] = "Out of space for regular expressions"; ! 27: char *fname; /* Current filename */ ! 28: ! 29: int vflag; /* Reverse sense of match */ ! 30: int cflag; /* Print only count of lines */ ! 31: int lflag; /* Only filenames with matching lines */ ! 32: int nflag; /* precede lines by line number in file */ ! 33: int bflag; /* print block number of match */ ! 34: int sflag; /* No output, only status */ ! 35: int hflag; /* Never print filenames */ ! 36: int xflag; /* Exact match only */ ! 37: int some; /* non-zero if some matches */ ! 38: int outfile; /* Output filename if match flag */ ! 39: int lineno; /* Input line # */ ! 40: unsigned blkno; /* Block number for `-b' */ ! 41: long lmatch; /* Lines matching */ ! 42: int yflag; /* Dual case comparisons */ ! 43: ! 44: int (*mfun)(); /* Match function */ ! 45: int rematch(); ! 46: int dirmatch(); ! 47: int reinterp(); ! 48: int ematch(); ! 49: int yematch(); ! 50: ! 51: main(argc, argv) ! 52: char *argv[]; ! 53: { ! 54: register RE *rp; ! 55: register char *cp; ! 56: register i; ! 57: struct exps *epp; ! 58: FILE *fp; ! 59: ! 60: mfun = rematch; ! 61: while (argc>1 && *argv[1]=='-') { ! 62: for (cp = &argv[1][1]; *cp; cp++) ! 63: switch (*cp) { ! 64: case 'a': ! 65: refull = 1; ! 66: break; ! 67: ! 68: case 'b': ! 69: bflag = 1; ! 70: break; ! 71: ! 72: case 'c': ! 73: cflag = 1; ! 74: break; ! 75: ! 76: case 'e': ! 77: if (argc < 3) ! 78: err(mre); ! 79: expsave(argv[2]); ! 80: argc--; ! 81: argv++; ! 82: break; ! 83: ! 84: case 'f': ! 85: if (argc < 3) ! 86: err("Missing expression filename"); ! 87: if ((fp = fopen(argv[2], "r")) == NULL) ! 88: err("Cannot open %s", argv[2]); ! 89: argv++; ! 90: argc--; ! 91: while (fgets(line, MAXLINE, fp) != NULL) { ! 92: i = strlen(line); ! 93: line[i-1] = '\0'; ! 94: expsave(line); ! 95: } ! 96: fclose(fp); ! 97: break; ! 98: ! 99: case 'h': ! 100: hflag = 1; ! 101: break; ! 102: ! 103: case 'l': ! 104: lflag = 1; ! 105: break; ! 106: ! 107: case 'n': ! 108: nflag = 1; ! 109: break; ! 110: ! 111: case 's': ! 112: sflag = 1; ! 113: break; ! 114: ! 115: case 'v': ! 116: vflag = 1; ! 117: break; ! 118: ! 119: case 'x': ! 120: xflag = 1; ! 121: mfun = dirmatch; ! 122: break; ! 123: ! 124: case 'i': ! 125: case 'y': ! 126: redual = 1; ! 127: yflag = 1; ! 128: break; ! 129: ! 130: default: ! 131: err(usage); ! 132: } ! 133: argv++; ! 134: argc--; ! 135: } ! 136: if (exps[0].e_un.u_cp == NULL) { ! 137: if (argc-- < 2) ! 138: err(usage); ! 139: expsave(argv[1]); ! 140: argv++; ! 141: } ! 142: expsave(NULL); ! 143: if (!xflag) ! 144: for (epp = &exps[0]; (cp = epp->e_un.u_cp) != NULL; epp++) { ! 145: rp = epp->e_un.u_re = reparse(cp, '\0'); ! 146: if (reerror != NULL) ! 147: err(reerror); ! 148: for (; rp != NULL; rp = rp->r_next) ! 149: if (rp->r_op != CONC) ! 150: break; ! 151: if (rp != NULL) { /* hard RE */ ! 152: free(cp); ! 153: epp->e_mfun = reinterp; ! 154: } else { ! 155: rp = epp->e_un.u_re; ! 156: epp->e_un.u_cp = cp; ! 157: epp->e_mfun = yflag ? yematch : ematch; ! 158: for ( ; rp!=NULL; rp = rp->r_next) { ! 159: *cp = rp->r_left.u_ival; ! 160: cp++; ! 161: } ! 162: *cp = '\0'; ! 163: } ! 164: } ! 165: if (argc < 3) /* Fewer than 2 files? */ ! 166: hflag = 1; ! 167: if (argc == 1) { ! 168: fname = "(stdin)"; ! 169: grep(stdin); ! 170: } else ! 171: for (i=1; i<argc; i++) { ! 172: if ((fp = fopen(argv[i], "r")) == NULL) ! 173: err("Cannot open %s", argv[i]); ! 174: fname = argv[i]; ! 175: grep(fp); ! 176: fclose(fp); ! 177: } ! 178: if (cflag) ! 179: printf("%ld\n", lmatch); ! 180: exit(!some); ! 181: } ! 182: ! 183: /* ! 184: * Save regular expression. ! 185: */ ! 186: expsave(s) ! 187: register char *s; ! 188: { ! 189: static struct exps *epp; ! 190: ! 191: if (epp == NULL) ! 192: epp = &exps[0]; ! 193: if (epp >= &exps[NEXP-1]) ! 194: err("Too many regular expressions"); ! 195: if (s == NULL) ! 196: epp->e_un.u_cp = NULL; ! 197: else { ! 198: if ((epp->e_un.u_cp = malloc(strlen(s)+1)) == NULL) ! 199: err(nospace); ! 200: strcpy(epp->e_un.u_cp, s); ! 201: } ! 202: epp++; ! 203: } ! 204: ! 205: /* ! 206: * Called for each input file ! 207: * to drive the pattern matches. ! 208: */ ! 209: grep(ifp) ! 210: FILE *ifp; ! 211: { ! 212: register unsigned n; ! 213: register c; ! 214: register char *cp; ! 215: ! 216: outfile = 0; ! 217: blkno = 0; ! 218: n = BSIZE; ! 219: lineno = 0; ! 220: for (cp = line; (c = getc(ifp)) != EOF; ) { ! 221: if (n-- == 0) { ! 222: n = BSIZE; ! 223: blkno++; ! 224: } ! 225: if (c=='\n' || cp>=&line[MAXLINE-1]) { ! 226: *cp = '\0'; ! 227: lineno++; ! 228: (*mfun)(cp = line); ! 229: } else ! 230: *cp++ = c; ! 231: } ! 232: if (outfile) ! 233: printf("%s\n", fname); ! 234: } ! 235: ! 236: /* ! 237: * Called when a match occurred in input ! 238: */ ! 239: amatch(s) ! 240: char *s; ! 241: { ! 242: some = 1; ! 243: if (sflag) ! 244: return; ! 245: if (!lflag && !cflag) { ! 246: if (!hflag) ! 247: printf("%s:", fname); ! 248: if (bflag) ! 249: printf("%d:", blkno); ! 250: else if (nflag) ! 251: printf("%d:", lineno); ! 252: printf("%s\n", s); ! 253: } else if (lflag) ! 254: outfile = 1; ! 255: else if (cflag) ! 256: lmatch++; ! 257: } ! 258: ! 259: /* ! 260: * try to match each line with all the ! 261: * regular expressions. ! 262: * An attempt is made to make expressions ! 263: * with no metacharacters run faster. ! 264: */ ! 265: rematch(s) ! 266: char *s; ! 267: { ! 268: register struct exps *epp; ! 269: register int m; ! 270: ! 271: m = 0; ! 272: for (epp = &exps[0]; epp->e_un.u_re!=NULL && m==0; epp++) ! 273: if ((*epp->e_mfun)(epp->e_un.u_re, s) != 0) ! 274: m = 1; ! 275: if (vflag) ! 276: m = !m; ! 277: if (m) ! 278: amatch(s); ! 279: return (m); ! 280: } ! 281: ! 282: /* ! 283: * Direct match function (for `-x' option) ! 284: */ ! 285: dirmatch(s) ! 286: char *s; ! 287: { ! 288: register struct exps *epp; ! 289: register m; ! 290: ! 291: m = 0; ! 292: for (epp = &exps[0]; epp->e_un.u_cp!=NULL && !m; epp++) ! 293: m = yflag ? yseq(epp->e_un.u_cp, s) : seq(epp->e_un.u_cp, s); ! 294: if (vflag) ! 295: m = !m; ! 296: if (m) ! 297: amatch(s); ! 298: return (m); ! 299: } ! 300: ! 301: /* ! 302: * Easy match ! 303: * For non -y grep. ! 304: */ ! 305: ematch(p, s) ! 306: char *p; ! 307: register char *s; ! 308: { ! 309: register char *xp, *xs; ! 310: ! 311: do { ! 312: xp = p; ! 313: xs = s; ! 314: while (*xp != '\0') { ! 315: if (*xs == '\0') ! 316: return (0); ! 317: if (*xp != *xs++) ! 318: break; ! 319: xp++; ! 320: } ! 321: if (*xp == '\0') ! 322: return (1); ! 323: } while (*s++ != '\0'); ! 324: return (0); ! 325: } ! 326: ! 327: /* ! 328: * Version of `ematch' for `-y' option ! 329: * of grep. ! 330: */ ! 331: yematch(p, s) ! 332: char *p; ! 333: register char *s; ! 334: { ! 335: register char *xp, *xs; ! 336: register int c; ! 337: ! 338: do { ! 339: xp = p; ! 340: xs = s; ! 341: while (*xp != '\0') { ! 342: if (*xs == '\0') ! 343: return (0); ! 344: if (islower(*xp) && isupper(*xs)) ! 345: c = tolower(*xs++); else ! 346: c = *xs++; ! 347: if (*xp != c) ! 348: break; ! 349: xp++; ! 350: } ! 351: if (*xp == '\0') ! 352: return (1); ! 353: } while (*s++ != '\0'); ! 354: return (0); ! 355: } ! 356: ! 357: /* ! 358: * String comparison for `-x' option ! 359: * without `-y' (dual) flag. ! 360: */ ! 361: seq(p, s) ! 362: register char *p; ! 363: register char *s; ! 364: { ! 365: while (*s == *p++) ! 366: if (*s++ == '\0') ! 367: return (1); ! 368: return (0); ! 369: } ! 370: ! 371: /* ! 372: * Version of `seq' for the `-y' option. ! 373: * First argument is the pattern, the second ! 374: * is the input string. ! 375: */ ! 376: yseq(p, s) ! 377: register char *p; ! 378: register char *s; ! 379: { ! 380: register int c; ! 381: ! 382: while ((c = *s++) != '\0') { ! 383: if (islower(*p) && isupper(c)) ! 384: c = tolower(c); ! 385: if (c != *p++) ! 386: return (0); ! 387: } ! 388: if (*p != '\0') ! 389: return (0); ! 390: return (1); ! 391: } ! 392: ! 393: err(s) ! 394: { ! 395: if (!sflag) ! 396: fprintf(stderr, "grep: %r\n", &s); ! 397: exit(2); ! 398: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.