BSD 1 development
[unix-history] / s6 / gres.c
#
/*
* gres -- substitute in lines matching (or not) a pattern
*
*
* Owner: lem
*/
#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 STAR 01
#define PTRSIZE 100
#define RESIZE 5000
#define LBSIZE 256
#define ESIZE 256
#define NBRA 5
char ibuf[512];
char genbuf[LBSIZE];
char *loc1;
char *loc2;
char *locs;
int lnum;
char linebuf[LBSIZE+1];
int gflag;
int vflag;
char *braelist[NBRA];
char *braslist[NBRA];
struct reptr {
char *re1;
char *re2;
char *rhs;
char gcirc;
char scirc;
} ptrspace[PTRSIZE];
struct reptr *rep;
struct reptr *ptrend;
char *bufend;
char *reend;
char respace[RESIZE];
main(argc, argv)
char **argv;
{
extern fout, fin;
register char *p1, *p2;
char *cp;
int p;
fin = dup(0);
fout = dup(1);
flush();
rep = ptrspace;
rep->re1 = respace;
bufend = &linebuf[LBSIZE];
ptrend = &rep[PTRSIZE];
reend = &respace[RESIZE];
lnum = 0;
while (--argc > 0 && (++argv)[0][0]=='-')
switch (argv[0][1]) {
case 'v':
vflag++;
continue;
case 'g':
gflag++;
continue;
case 'f':
fcomp(argc, argv);
argc--;
argv++;
continue;
case 'e':
ecomp(argc,argv);
argc =- 3;
argv =+ 3;
continue;
default:
printf2("Unknown flag: %c\n", argv[0][1]);
continue;
}
if(rep == ptrspace) {
argv--;
argc++;
ecomp(argc, argv);
argc =- 4;
argv =+ 4;
}
/* abort(); /*DEBUG*/
if(argc <= 0)
execute(0);
else while(--argc >= 0) {
execute(*argv++);
}
flush();
exit(0);
}
fcomp(argc, argv)
char *argv[];
{
register int p;
register char *cp;
extern fin;
if(argc-- <= 0) exit(2);
if(fin) close(fin);
if((fin = open(*++argv, 0)) < 0) {
printf2("Cannot open pattern file: %s\n",
*argv);
exit(1);
}
for(;;) {
lnum++;
cp = linebuf - 1;
while(*++cp = getchar()) {
if(cp >= bufend) {
printf2("RE too long, line %d\n", lnum);
}
if(*cp == '\n') break;
}
if(*cp == 0) break;
p = compile(linebuf, rep->re1, &rep->gcirc);
if(p < 1)
printf2("RE error, line %d\n", lnum);
if(p == 1 && rep->gcirc == 0) {
if(rep > ptrspace) {
rep->re2 = rep->re1;
rep->re1 = rep[-1].re2;
rep->gcirc = rep[-1].scirc;
} else
printf2("RE error, line %d\n",
lnum);
} else
if((rep->re2 = rep->re1 + p) > reend)
printf2("RE space exhausted; line %d\n", lnum);
lnum++;
cp = linebuf - 1;
while(*++cp = getchar()) {
if(cp >= bufend)
printf("RE too long, line %d\n", lnum);
if(*cp == '\n') break;
}
if(*cp == 0) break;
p = compile(linebuf, rep->re2, &rep->scirc);
if(p < 1)
printf2("RE error, line %d\n", lnum);
if(p == 1 && rep->scirc == 0) {
rep->rhs = rep->re2;
rep->re2 = rep->re1;
rep->scirc = rep->gcirc;
} else
if((rep->rhs = rep->re2 + p) > reend)
printf2("RE space exhausted, line %d\n", lnum);
lnum++;
cp = linebuf - 1;
while(*++cp = getchar()) {
if(cp >= bufend)
printf2("RE too long, line %d\n", lnum);
if(*cp == '\n') break;
}
if(*cp == 0) break;
if((p = compsub(linebuf, rep->rhs)) < 1)
printf2("RHS error, line %d\n", lnum);
if(++rep >= ptrend)
printf2("Too many lines in pattern file, %d\n",
lnum);
if ((rep->re1 = rep[-1].rhs + p) > reend)
printf2("RE space exhausted, line %d\n", lnum);
}
}
ecomp(argc, argv)
char *argv[];
{
register int p;
if(argc-- <= 0)
exit(2);
p = compile(*++argv, rep->re1, &rep->gcirc);
if(p < 1)
printf2("RE error, re%d\n", 1);
if(p == 1 && rep->gcirc == 0) {
if(rep > ptrspace) {
rep->re2 = rep->re1;
rep->re1 = rep[-1].re2;
rep->gcirc = rep[-1].scirc;
} else
printf2("RE error: re1\n");
}
rep->re2 = rep->re1 + p;
if(argc-- <= 0)
exit(2);
if((p = compile(*++argv, rep->re2, &rep->scirc)) < 1)
printf2("RE error, re%d\n", 2);
if(p == 1 && rep->scirc == 0) {
rep->rhs = rep->re2;
rep->re2 = rep->re1;
rep->scirc = rep->gcirc;
} else
rep->rhs = rep->re2 + p;
if((p = compsub(*++argv, rep->rhs)) < 1)
printf2("RHS error\n");
if(argc-- <= 0)
exit(2);
if(++rep >= ptrend)
printf2("Too many patterns\n");
if((rep->re1 = rep[-1].rhs + p) > reend)
printf2("RE space exhausted\n");
}
compile(astr, expbuf, circf)
char *astr;
char *expbuf;
char *circf;
{
register c;
register char *ep, *sp;
char *lastep;
int cclcnt;
char bracket[NBRA], *bracketp;
int nbra;
ep = expbuf;
bracketp = bracket;
nbra = 0;
sp = astr;
if (*sp == '^') {
(*circf)++;
sp++;
}
for (;;) {
if (ep >= &expbuf[ESIZE])
return(-1);
if ((c = *sp++) != '*')
lastep = ep;
switch (c) {
case '\\':
if((c = *sp++) == '(') {
if(nbra >= NBRA)
return(-1);
*bracketp++ = nbra;
*ep++ = CBRA;
*ep++ = nbra++;
continue;
}
if(c == ')') {
if(bracketp <= bracket)
return(-1);
*ep++ = CKET;
*ep++ = *--bracketp;
continue;
}
if(c == '\n') return(-1);
goto defchar;
case '\0':
case '\n':
if(ep >= expbuf[ESIZE] - 1) return(-1);
*ep++ = CEOF;
return(ep - expbuf);
case '.':
*ep++ = CDOT;
continue;
case '*':
if (lastep==0)
goto defchar;
*lastep =| STAR;
continue;
case '$':
if (*sp != '\0' && *sp != '\n')
goto defchar;
*ep++ = CDOL;
continue;
case '[':
*ep++ = CCL;
*ep++ = 0;
cclcnt = 1;
if ((c = *sp++) == '^') {
c = *sp++;
ep[-2] = NCCL;
}
do {
*ep++ = c;
cclcnt++;
if (c=='\0' || ep >= &expbuf[ESIZE])
return(-1);
} while ((c = *sp++) != ']');
lastep[1] = cclcnt;
continue;
defchar:
default:
*ep++ = CCHR;
*ep++ = c;
}
}
}
execute(file)
{
register char *p1, *p2;
register c;
int count;
int f;
char *ebp, *cbp;
rep->re1 = 0;
if (file) {
if ((f = open(file, 0)) < 0) {
printf2("Can't open %s\n", file);
}
} else
f = 0;
ebp = ibuf;
cbp = ibuf;
for (;;) {
p1 = linebuf;
p2 = cbp;
for (;;) {
if (p2 >= ebp) {
if ((count = c = read(f, ibuf, 512)) <= 0) {
close(f);
return;
}
p2 = ibuf;
ebp = ibuf+c;
}
if ((c = *p2++) == '\n')
break;
if(c)
if (p1 < &linebuf[LBSIZE-1])
*p1++ = c;
}
*p1++ = 0;
cbp = p2;
for(rep = ptrspace; rep->re1; rep++) {
p1 = linebuf;
p2 = rep->re1;
if (rep->gcirc) {
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);
continue;
found:
if (vflag==0)
succeed(file);
continue;
}
printf("%s\n", linebuf);
if (count != 512) flush();
}
}
advance(alp, aep)
{
register char *lp, *ep, *curlp;
char *nextep;
lp = alp;
ep = aep;
for (;;) switch (*ep++) {
case CCHR:
if (*ep++ == *lp++)
continue;
return(0);
case CDOT:
if (*lp++)
continue;
return(0);
case CDOL:
if (*lp==0)
continue;
return(0);
case CEOF:
loc2 = lp;
return(1);
case CCL:
if (cclass(ep, *lp++, 1)) {
ep =+ *ep;
continue;
}
return(0);
case NCCL:
if (cclass(ep, *lp++, 0)) {
ep =+ *ep;
continue;
}
return(0);
case CBRA:
braslist[*ep++] = lp;
continue;
case CKET:
braelist[*ep++] = lp;
continue;
case CDOT|STAR:
curlp = lp;
while (*lp++);
goto star;
case CCHR|STAR:
curlp = lp;
while (*lp++ == *ep);
ep++;
goto star;
case CCL|STAR:
case NCCL|STAR:
curlp = lp;
while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
ep =+ *ep;
goto star;
star:
do {
lp--;
if(lp == locs) break;
if (advance(lp, ep))
return(1);
} while (lp > curlp);
return(0);
default:
printf2("RE botch\n");
}
}
succeed()
{
if(sexec(0) == 0) return;
dosub(rep->rhs);
if(gflag) {
while(*loc2) {
if(sexec(1) == 0) break;
dosub(rep->rhs);
}
}
}
sexec(gf)
{
register char *p1, *p2, c;
if(gf) {
if(rep->scirc) return(0);
p1 = linebuf;
p2 = genbuf;
while(*p1++ = *p2++);
locs = p1 = loc2;
} else {
p1 = linebuf;
locs = 0;
}
p2 = rep->re2;
if(rep->scirc) {
loc1 = p1;
return(advance(p1, p2));
}
/* fast check for first character */
if(*p2 == CCHR) {
c = p2[1];
do {
if(*p1 != c)
continue;
if(advance(p1, p2)) {
loc1 = p1;
return(1);
}
} while(*p1++);
}
do {
if(advance(p1, p2)) {
loc1 = p1;
return(1);
}
} while(*p1++);
return(0);
}
cclass(aset, ac, af)
{
register char *set, c;
register n;
set = aset;
if ((c = ac) == 0)
return(0);
n = *set++;
while (--n)
if (*set++ == c)
return(af);
return(!af);
}
printf2(s, a)
{
extern fout;
flush();
fout = 2;
printf(s, a);
flush();
exit(2);
}
compsub(arg, rhsbuf)
char *arg, *rhsbuf;
{
register char *rhsend;
register char *p, *q;
p = rhsbuf;
q = arg;
rhsend = &rhsbuf[LBSIZE];
for(;;) {
if((*p = *q++) == '\\')
*p = *q++ | 0200;
if(*p == '\n') {
*p++ = '\0';
return(p - rhsbuf);
}
if(*p++ == '\0')
return(p - rhsbuf);
if(p >= rhsend) {
return(-1);
}
}
}
dosub(rhsbuf)
char *rhsbuf;
{
register char *lp, *sp, *rp;
int c;
lp = linebuf;
sp = genbuf;
rp = rhsbuf;
while (lp < loc1)
*sp++ = *lp++;
while(c = *rp++) {
if (c=='&') {
sp = place(sp, loc1, loc2);
continue;
} else if (c<0 && (c =& 0177) >='1' && c < NBRA+'1') {
sp = place(sp, braslist[c-'1'], braelist[c-'1']);
continue;
}
*sp++ = c&0177;
if (sp >= &genbuf[LBSIZE])
printf2("output line too long.\n");
}
lp = loc2;
loc2 = sp + linebuf - genbuf;
while (*sp++ = *lp++)
if (sp >= &genbuf[LBSIZE]) {
printf2("Output line too long.\n");
}
lp = linebuf;
sp = genbuf;
while (*lp++ = *sp++);
}
place(asp, al1, al2)
{
register char *sp, *l1, *l2;
sp = asp;
l1 = al1;
l2 = al2;
while (l1 < l2) {
*sp++ = *l1++;
if (sp >= &genbuf[LBSIZE])
printf2("Output line too long.\n");
}
return(sp);
}