#ifdef ournix #include "ournix.h" #endif char sccsID[] = "@(#) grep.c V0.0 Copyright Vector Systems Ltd(pjc) 1988\n" ; /* * grep for MS-DOS by Phil Cockcroft * Staceyfied */ #include #define CHAR 1 #define DOT 2 #define LSTART 3 #define EOL 4 #define CCL 5 #define NCCL 6 #define SRANGE 7 #define EOP 0 /* end of pattern */ #define STAR 040 #define QSTAR 0100 #define LSIZE 512 /* * flags */ int vflag; /* reverse the sense of the grep */ int nflag; int lflag; int cflag; char line[LSIZE]; char ex_p[LSIZE]; FILE *infile; int estatus = 0; char *curfile; char *eol; char *progname; char **ARGV ; main(argc, argv) char **argv; { ARGV = argv ; #ifdef VSL /* { */ #include "../../include/vsl.h" #endif /* } */ progname = *argv; while(--argc > 0){ argv++; if(**argv == '-'){ setflags(*argv + 1); continue; } break; } if(argc < 1){ fprintf(stderr, "Usage: %s pattern files....\n", progname); exit(100); } compile(*argv++); if(--argc <= 0){ infile = stdin; dofile(); } else for(;argc > 0; argc--, argv++){ if(**argv == '-'){ setflags(*argv + 1); continue; } infile = fopen(*argv, "r"); if(infile == NULL){ fprintf(stderr, "%s: Cannot open %s\n", progname, *argv); estatus |= 1; continue; } if(argc > 1 || curfile) curfile = *argv; dofile(); fclose(infile); } exit(estatus); } setflags(p) char *p; { while(*p) switch(*p++){ case 'l': lflag++; break; case 'v': vflag++; break; case 'n': nflag++; break; case 'c': cflag++; break; default: fprintf(stderr, "%s: Unknown flag -%c\n", progname, *(p-1)); exit(2); } } compile(pat) char *pat; { char *p; char *lastr = 0; char *sp; for(p = ex_p; *pat ; pat++){ if(p >= &ex_p[LSIZE-2]){ fprintf(stderr, "%s: RE overflow\n", progname); exit(2); } switch(*pat){ case '\\': if(*++pat == '\0') botch(); /* fall through */ default: lastr = p; *p++ = CHAR; *p++ = *pat; continue; case '*': if(lastr == 0) botch(); *lastr |= STAR; *lastr &= ~QSTAR; continue; case '?': if(lastr == 0) botch(); if((*lastr & STAR) == 0) *lastr |= QSTAR; continue; case '^': lastr = p; *p++ = LSTART; continue; case '.': lastr = p; *p++ = DOT; continue; case '$': lastr = p; *p++ = EOL; continue; case '[': lastr = p; if(pat[1] == '^'){ *p++ = NCCL; pat++; } else *p++ = CCL; sp = p; for(p++,pat++;;pat++){ switch(*pat){ case '\\': if(*++pat == '\0') botch(); /* fall through */ default: if(pat[1] == '-'){ /* a range */ *p++ = SRANGE; *p++ = *pat++; *p++ = *++pat; if(p[-1] < p[-2]) botch(); continue; } *p++ = CHAR; *p++ = *pat; continue; case '^': *p++ = LSTART; continue; case '$': *p++ = EOL; continue; case ']': *p++ = EOP; *sp = p - sp; break; case '\0': botch(); } break; } break; } } *p = EOP; } botch() { fprintf(stderr, "%s: Regular Expression Botch\n", progname); exit(3); } /* * do the file */ dofile() { char *p; int c; int nline = 0; int nmatch = 0; for(;;nline++){ for(p = line ; (c = getc(infile)) != EOF ;){ if(c == '\n'){ *p = '\0'; break; } if(p < &line[LSIZE-2]) *p++ = c; } if(c == EOF){ if(cflag){ if(curfile) printf("%s: %d\n", curfile, nmatch); else printf("%d\n", nmatch); } return; } eol = p; if(match()){ if(vflag) continue; } else { if(!vflag) continue; } if(cflag){ nmatch++; continue; } if(lflag && curfile){ if(nflag) printf("%s: %d\n", curfile, nline); else printf("%s\n", curfile); fflush(stdout); return; } if(curfile){ if(nflag) printf("%s: %d %s\n", curfile, nline, line); else printf("%s: %s\n", curfile, line); } else { if(nflag) printf("%d: %s\n", nline, line); else printf("%s\n", line); } fflush(stdout); } } match() { char *curp; char c; curp = line; switch(*ex_p){ case CHAR: for(c = ex_p[1] ; *curp != c ; curp++) if(*curp == '\0') return(0); break; case LSTART: return(matchit(ex_p, line)); } do { if(matchit(ex_p, curp)) return(1); } while(*curp++); return(0); } matchit(matp, curp) char *matp, *curp; { char *savep, c; for(;;){ switch(*matp++){ case CHAR: if(*matp++ != *curp++) return(0); break; case CHAR|STAR: for(c = *matp++ ; *curp && c != *curp ; curp++) if(!matchit(matp-2, curp+1)) break; break; case CHAR|QSTAR: if(*matp++ == *curp) if(matchit(matp, curp+1)) return(1); break; case DOT: if(*curp++ == '\0') return(0); break; case DOT|STAR: for(savep = eol ; savep > curp ; savep--) if(matchit(matp, savep)) break; curp = savep; break; case DOT|QSTAR: if(matchit(matp, curp+1)) return(1); break; case LSTART: case LSTART|STAR: if(curp != line) return(0); break; case LSTART|QSTAR: break; case EOL: case EOL|STAR: if(*curp != '\0') return(0); break; case EOL|QSTAR: break; case CCL: if(!inset(matp+1, curp)) return(0); curp++; matp += *matp; break; case CCL|QSTAR: if(inset(matp+1, curp)) if(matchit(matp + *matp, curp+1)) return(1); matp += *matp; break; case NCCL: if(inset(matp+1, curp)) return(0); curp++; matp += *matp; break; case NCCL|QSTAR: if(!inset(matp+1, curp)) if(matchit(matp + *matp, curp+1)) return(1); matp += *matp; break; case CCL|STAR: for(; inset(matp+1, curp) ;curp++){ if(!matchit(matp-1, curp+1)) break; if(*curp == '\0') break; } matp += *matp; break; case NCCL|STAR: for(;;curp++){ if(inset(matp+1, curp)) break; if(!matchit(matp-1, curp+1)) break; if(*curp == '\0') break; } matp += *matp; break; case EOP: /* end of pattern - success */ return(1); default: fprintf(stderr, "%s: Unknown type 0x%x in ex_p !\n", progname, *matp); exit(23); } } } inset(pat, curp) char *pat, *curp; { char c = *curp; char cc; for(;*pat != EOP;pat++) switch(*pat){ case CHAR: if(*++pat == c) return(1); break; case LSTART: if(curp == line) return(1); break; case EOL: if(c == '\0') return(1); break; case SRANGE: cc = *++pat; if(c <= *++pat && c >= cc) return(1); break; } return(0); }