|
|
researchv10 Norman
/*
* grep -- print lines matching (or not matching) a pattern
*
* status returns:
* 0 - ok, and some matches
* 1 - ok, but no matches
* 2 - some error
*/
/*#define DOSTATS /* define this to gather stats */
#ifdef DOSTATS
char *statsexpr;
long nlines, nbytes, ndepth, nmaxdepth;
char statsflags[1024], *statsfptr = statsflags;
dostats();
#endif
#include <ctype.h>
#include <stdio.h>
#include <fio.h>
#define CBRA 1
#define CCHR 2
#define CDOT 4
#define CCL 6
#define NCCL 8
#define CDOL 10
#define CEOF 11
#define CKET 12
#define CBACK 18
#define STAR 01
#define LBSIZE 512
#define ESIZE 256
#define NBRA 9
char expbuf[ESIZE];
long lnum;
char stdbuf[BUFSIZ];
char *linebuf = stdbuf;
char ybuf[5000];
int bflag;
int lflag;
int nflag;
int cflag;
int vflag;
int nfile;
int hflag = 1;
int sflag;
int scanexit;
int iflag;
int retcode = 0;
int circf;
long tln;
int nsucc;
char *braslist[NBRA];
char *braelist[NBRA];
char bittab[] = {
1,
2,
4,
8,
16,
32,
64,
128
};
main(argc, argv)
char **argv;
{
extern etext();
while (--argc > 0 && (++argv)[0][0]=='-'){
#ifdef DOSTATS
*statsfptr++ = argv[0][1];
#endif
switch (argv[0][1]) {
case 'i':
iflag++;
continue;
case 'h':
hflag = 0;
continue;
case 's':
sflag++;
continue;
case 'v':
vflag++;
continue;
case 'b':
bflag++;
continue;
case 'l':
lflag++;
continue;
case 'c':
cflag++;
continue;
case 'n':
nflag++;
continue;
case 'e':
--argc;
++argv;
goto out;
default:
errexit("grep: unknown flag %c\n", argv[0][1]);
continue;
}
}
out:
if (argc<=0)
exit(2);
if (iflag) {
register char *p;
for ( p = *argv; *p; p++ )
*p = tolower(*p);
}
#ifdef DOSTATS
statsexpr = (char *)strdup(*argv);
onexit(dostats);
#endif
compile(*argv);
nfile = --argc;
if (argc<=0) {
scanexit = 1;
execute("/dev/stdin");
} else while (--argc >= 0) {
argv++;
scanexit = argc == 0;
execute(*argv);
}
exit (retcode != 0 ? retcode : nsucc == 0);
}
compile(astr)
char *astr;
{
register c;
register char *ep, *sp;
char *cstart;
char *lastep;
int cclcnt;
char bracket[NBRA], *bracketp;
char numbra;
char neg;
ep = expbuf;
sp = astr;
lastep = 0;
bracketp = bracket;
numbra = 0;
if (*sp == '^') {
circf++;
sp++;
}
for (;;) {
if (ep >= &expbuf[ESIZE])
goto cerror;
if ((c = *sp++) != '*')
lastep = ep;
switch (c) {
case '\0':
*ep++ = CEOF;
return;
case '.':
*ep++ = CDOT;
continue;
case '*':
if (lastep==0 || *lastep==CBRA || *lastep==CKET)
goto defchar;
*lastep |= STAR;
continue;
case '$':
if (*sp != '\0')
goto defchar;
*ep++ = CDOL;
continue;
case '[':
if(&ep[17] >= &expbuf[ESIZE])
goto cerror;
*ep++ = CCL;
neg = 0;
if((c = *sp++) == '^') {
neg = 1;
c = *sp++;
}
cstart = sp;
do {
if (c=='\0')
goto cerror;
if (c=='-' && sp>cstart && *sp!=']') {
for (c = sp[-2]; c<*sp; c++)
ep[c>>3] |= bittab[c&07];
sp++;
}
ep[c>>3] |= bittab[c&07];
} while((c = *sp++) != ']');
if(neg) {
for(cclcnt = 0; cclcnt < 16; cclcnt++)
ep[cclcnt] ^= -1;
ep[0] &= 0376;
}
ep += 16;
continue;
case '\\':
if((c = *sp++) == '(') {
if(numbra >= NBRA) {
goto cerror;
}
*bracketp++ = numbra;
*ep++ = CBRA;
*ep++ = numbra++;
continue;
}
if(c == ')') {
if(bracketp <= bracket) {
goto cerror;
}
*ep++ = CKET;
*ep++ = *--bracketp;
continue;
}
if(c >= '1' && c <= '9') {
char *bp;
c -= '1';
if(c >= numbra)
goto cerror;
for(bp=bracket; bp<bracketp; bp++)
if(c == *bp)
goto cerror;
*ep++ = CBACK;
*ep++ = c;
continue;
}
defchar:
default:
*ep++ = CCHR;
*ep++ = c;
}
}
cerror:
errexit("grep: RE error\n", (char *)0);
}
execute(file)
char *file;
{
register char *p1, *p2;
register c;
register fd;
if ((fd = open(file, 0)) < 0) {
Fprint(2, "grep: can't open %s\n", file);
retcode = 2;
return;
}
Finit(fd, (char *)0);
Ftie(fd, 1);
lnum = 0;
tln = 0;
for (;;) {
if (tln && lflag) {
close(fd);
return;
}
lnum++;
if((p1 = linebuf = Frdline(fd)) == 0) {
if (cflag) {
if (nfile>1)
Fprint(1, "%s:", file);
Fprint(1, "%ld\n", tln);
}
#ifdef DOSTATS
nbytes += FIOSEEK(fd);
nlines += lnum-1;
#endif
close(fd);
return;
}
if (iflag) {
char *s = p1;
char *t = ybuf;
do {
*t++ = tolower(*s);
} while (*s++);
p1 = ybuf;
}
p2 = expbuf;
if (circf) {
if (advance(p1, p2))
goto found;
goto nfound;
}
/* fast check for first character */
if (*p2==CCHR) {
c = p2[1];
do {
if (*p1!=c)
continue;
if (advance(p1, p2))
goto found;
} while (*p1++);
goto nfound;
}
/* regular algorithm */
do {
if (advance(p1, p2))
goto found;
} while (*p1++);
nfound:
if (vflag)
succeed(file, fd);
continue;
found:
if (vflag==0)
succeed(file, fd);
}
}
advance(lp, ep)
register char *lp, *ep;
{
register char *curlp;
char c;
char *bbeg;
int ct;
#ifdef DOSTATS
if(++ndepth > nmaxdepth) nmaxdepth = ndepth;
#endif
for (;;) switch (*ep++) {
case CCHR:
if (*ep++ == *lp++)
continue;
#ifdef DOSTATS
ndepth--;
#endif
return(0);
case CDOT:
if (*lp++)
continue;
#ifdef DOSTATS
ndepth--;
#endif
return(0);
case CDOL:
if (*lp==0)
continue;
#ifdef DOSTATS
ndepth--;
#endif
return(0);
case CEOF:
#ifdef DOSTATS
ndepth--;
#endif
return(1);
case CCL:
c = *lp++ & 0177;
if(ep[c>>3] & bittab[c & 07]) {
ep += 16;
continue;
}
#ifdef DOSTATS
ndepth--;
#endif
return(0);
case CBRA:
braslist[*ep++] = lp;
continue;
case CKET:
braelist[*ep++] = lp;
continue;
case CBACK:
bbeg = braslist[*ep];
if (braelist[*ep]==0){
#ifdef DOSTATS
ndepth--;
#endif
return(0);
}
ct = braelist[*ep++] - bbeg;
if(ecmp(bbeg, lp, ct)) {
lp += ct;
continue;
}
#ifdef DOSTATS
ndepth--;
#endif
return(0);
case CBACK|STAR:
bbeg = braslist[*ep];
if (braelist[*ep]==0){
#ifdef DOSTATS
ndepth--;
#endif
return(0);
}
ct = braelist[*ep++] - bbeg;
curlp = lp;
while(ecmp(bbeg, lp, ct))
lp += ct;
while(lp >= curlp) {
if(advance(lp, ep)){
#ifdef DOSTATS
ndepth--;
#endif
return(1);
}
lp -= ct;
}
#ifdef DOSTATS
ndepth--;
#endif
return(0);
case CDOT|STAR:
curlp = lp;
while (*lp++);
goto star;
case CCHR|STAR:
curlp = lp;
while (*lp++ == *ep);
ep++;
goto star;
case CCL|STAR:
curlp = lp;
do {
c = *lp++ & 0177;
} while(ep[c>>3] & bittab[c & 07]);
ep += 16;
goto star;
star:
if(--lp == curlp) {
continue;
}
if(*ep == CCHR) {
c = ep[1];
do {
if(*lp != c)
continue;
if(advance(lp, ep)){
#ifdef DOSTATS
ndepth--;
#endif
return(1);
}
} while(lp-- > curlp);
#ifdef DOSTATS
ndepth--;
#endif
return(0);
}
do {
if (advance(lp, ep)){
#ifdef DOSTATS
ndepth--;
#endif
return(1);
}
} while (lp-- > curlp);
#ifdef DOSTATS
ndepth--;
#endif
return(0);
default:
errexit("grep RE botch\n", (char *)0);
}
}
succeed(f, fd)
char *f;
int fd;
{
nsucc = 1;
if (sflag){
if(scanexit) exit(0);
return;
}
if (cflag) {
tln++;
return;
}
if (lflag) {
Fprint(1, "%s\n", f);
tln++;
return;
}
if (nfile > 1 && hflag)
Fprint(1, "%s:", f);
if (bflag)
Fprint(1, "%ld:", (FIOSEEK(fd)-FIOLINELEN(fd)-1)/1024);
if (nflag)
Fprint(1, "%ld:", lnum);
{
register x = FIOLINELEN(fd);
linebuf[x] = '\n';
Fwrite(1, linebuf, x+1);
}
}
ecmp(a, b, count)
char *a, *b;
{
register cc = count;
while(cc--)
if(*a++ != *b++) return(0);
return(1);
}
errexit(s, f)
char *s, *f;
{
Fprint(2, s, f);
exit(2);
}
#ifdef DOSTATS
#include <errno.h>
#define NAME "/tmp/grepdata"
dostats()
{
int mailfd;
umask(0);
mailfd = open(NAME, 1);
if((mailfd < 0) && (errno != ECONC)){
umask(0);
mailfd = creat(NAME, 03666);
}
if(mailfd >= 0){
Finit(mailfd, (char *)0);
Fseek(mailfd, 0L, 2);
*statsfptr = 0;
Fprint(mailfd, "\321grep:%s:%d:%d:%d: %s\n", statsflags, nlines, nbytes, nmaxdepth, statsexpr);
Fflush(mailfd);
close(mailfd);
}
}
#endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.