#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include "sed.h"
#define Read(f, buf, n) (fflush(stdout), read(f, buf, n))
void
execute(uchar *file)
{
uchar *p1, *p2;
union reptr *ipc;
int c;
long l;
uchar *execp;
if (file) {
if ((f = open((char*)file, O_RDONLY)) < 0) {
fprintf(stderr, "sed: Can't open %s\n", file);
}
} else
f = 0;
ebp = ibuf;
cbp = ibuf;
if(pending) {
ipc = pending;
pending = 0;
goto yes;
}
for(;;) {
if((execp = gline(linebuf)) == badp) {
close(f);
return;
}
spend = execp;
for(ipc = ptrspace; ipc->r1.command; ) {
p1 = ipc->r1.ad1;
p2 = ipc->r1.ad2;
if(p1) {
if(ipc->r1.inar) {
if(*p2 == CEND) {
p1 = 0;
} else if(*p2 == CLNUM) {
l = p2[1]&0377
| ((p2[2]&0377)<<8)
| ((p2[3]&0377)<<16)
| ((p2[4]&0377)<<24);
if(lnum > l) {
ipc->r1.inar = 0;
if(ipc->r1.negfl)
goto yes;
ipc++;
continue;
}
if(lnum == l) {
ipc->r1.inar = 0;
}
} else if(match(p2, 0)) {
ipc->r1.inar = 0;
}
} else if(*p1 == CEND) {
if(!dolflag) {
if(ipc->r1.negfl)
goto yes;
ipc++;
continue;
}
} else if(*p1 == CLNUM) {
l = p1[1]&0377
| ((p1[2]&0377)<<8)
| ((p1[3]&0377)<<16)
| ((p1[4]&0377)<<24);
if(lnum != l) {
if(ipc->r1.negfl)
goto yes;
ipc++;
continue;
}
if(p2)
ipc->r1.inar = 1;
} else if(match(p1, 0)) {
if(p2)
ipc->r1.inar = 1;
} else {
if(ipc->r1.negfl)
goto yes;
ipc++;
continue;
}
}
if(ipc->r1.negfl) {
ipc++;
continue;
}
yes:
command(ipc);
if(delflag)
break;
if(jflag) {
jflag = 0;
if((ipc = ipc->r2.lb1) == 0) {
ipc = ptrspace;
break;
}
} else
ipc++;
}
if(!nflag && !delflag) {
for(p1 = linebuf; p1 < spend; p1++)
putc(*p1, stdout);
putc('\n', stdout);
}
if(aptr > abuf) {
arout();
}
delflag = 0;
}
}
int
match(uchar *expbuf, int gf)
{
uchar *p1, *p2;
int c;
if(gf) {
if(*expbuf) return(0);
p1 = linebuf;
p2 = genbuf;
while(*p1++ = *p2++);
locs = p1 = loc2;
} else {
p1 = linebuf;
locs = 0;
}
p2 = expbuf;
if(*p2++) {
loc1 = p1;
if(*p2 == CCHR && p2[1] != *p1)
return(0);
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++);
return(0);
}
do {
if(advance(p1, p2)) {
loc1 = p1;
return(1);
}
} while(*p1++);
return(0);
}
int
advance(uchar *alp, uchar *aep)
{
uchar *lp, *ep, *curlp;
uchar c;
uchar *bbeg;
int ct;
/*fprintf(stderr, "*lp = %c, %o\n*ep = %c, %o\n", *lp, *lp, *ep, *ep); /*DEBUG*/
lp = alp;
ep = aep;
for (;;) switch (*ep++) {
case CCHR:
if (*ep++ == *lp++)
continue;
return(0);
case CDOT:
if (*lp++)
continue;
return(0);
case CNL:
case CDOL:
if (*lp == 0)
continue;
return(0);
case CEOF:
loc2 = lp;
return(1);
case CCL:
c = *lp++;
if(ep[c>>3] & bittab[c & 07]) {
ep += 32;
continue;
}
return(0);
case CBRA:
braslist[*ep++] = lp;
continue;
case CKET:
braelist[*ep++] = lp;
continue;
case CBACK:
bbeg = braslist[*ep];
ct = braelist[*ep++] - bbeg;
if(ecmp(bbeg, lp, ct)) {
lp += ct;
continue;
}
return(0);
case CBACK|STAR:
bbeg = braslist[*ep];
ct = braelist[*ep++] - bbeg;
curlp = lp;
while(ecmp(bbeg, lp, ct))
lp += ct;
while(lp >= curlp) {
if(advance(lp, ep)) return(1);
lp -= ct;
}
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++;
} while(ep[c>>3] & bittab[c & 07]);
ep += 32;
goto star;
star:
if(--lp == curlp) {
continue;
}
if(*ep == CCHR) {
c = ep[1];
do {
if(*lp != c)
continue;
if(advance(lp, ep))
return(1);
} while(lp-- > curlp);
return(0);
}
if(*ep == CBACK) {
c = *(braslist[ep[1]]);
do {
if(*lp != c)
continue;
if(advance(lp, ep))
return(1);
} while(lp-- > curlp);
return(0);
}
do {
if(lp == locs) break;
if (advance(lp, ep))
return(1);
} while (lp-- > curlp);
return(0);
default:
fprintf(stderr, "sed: RE botch, %o\n", *--ep);
exit(1);
}
}
int
substitute(union reptr *ipc)
{
uchar *oloc2;
if(match(ipc->r1.re1, 0)) {
sflag = 1;
if(!ipc->r1.gfl) {
dosub(ipc->r1.rhs);
return(1);
}
oloc2 = NULL;
do {
if(oloc2 == loc2) {
loc2++;
continue;
} else {
dosub(ipc->r1.rhs);
if(*loc2 == 0)
break;
oloc2 = loc2;
}
} while(match(ipc->r1.re1, 1));
return(1);
}
return(0);
}
void
dosub(uchar *rhsbuf)
{
uchar *lp, *sp, *rp;
int c;
lp = linebuf;
sp = genbuf;
rp = rhsbuf;
while (lp < loc1)
*sp++ = *lp++;
while(c = *rp++) {
if (c == '\\') {
c = *rp++;
if (c >= '1' && c < NBRA+'1') {
sp = place(sp, braslist[c-'1'], braelist[c-'1']);
continue;
}
} else if(c == '&') {
sp = place(sp, loc1, loc2);
continue;
}
*sp++ = c;
if (sp >= &genbuf[LBSIZE])
fprintf(stderr, "sed: Output line too long.\n");
}
lp = loc2;
loc2 = sp - genbuf + linebuf;
while (*sp++ = *lp++)
if (sp >= &genbuf[LBSIZE]) {
fprintf(stderr, "sed: Output line too long.\n");
}
lp = linebuf;
sp = genbuf;
while (*lp++ = *sp++);
spend = lp-1;
}
uchar *
place(uchar *asp, uchar *al1, uchar *al2)
{
uchar *sp, *l1, *l2;
sp = asp;
l1 = al1;
l2 = al2;
while (l1 < l2) {
*sp++ = *l1++;
if (sp >= &genbuf[LBSIZE])
fprintf(stderr, "sed: Output line too long.\n");
}
return(sp);
}
void
command(union reptr *ipc)
{
int i;
uchar *p1, *p2;
uchar *execp;
switch(ipc->r1.command) {
case ACOM:
*aptr++ = ipc;
if(aptr >= &abuf[ABUFSIZE]) {
fprintf(stderr, "sed: Too many appends after line %ld\n",
lnum);
}
*aptr = 0;
break;
case CCOM:
delflag = 1;
if(!ipc->r1.inar || dolflag) {
for(p1 = ipc->r1.re1; *p1; )
putc(*p1++, stdout);
putc('\n', stdout);
}
break;
case DCOM:
delflag++;
break;
case CDCOM:
p1 = p2 = linebuf;
while(*p1 != '\n') {
if(*p1++ == 0) {
delflag++;
return;
}
}
p1++;
while(*p2++ = *p1++);
spend = p2-1;
jflag++;
break;
case EQCOM:
fprintf(stdout, "%ld\n", lnum);
break;
case GCOM:
p1 = linebuf;
p2 = holdsp;
while(*p1++ = *p2++);
spend = p1-1;
break;
case CGCOM:
*spend++ = '\n';
p1 = spend;
p2 = holdsp;
while(*p1++ = *p2++)
if(p1 >= lbend)
break;
spend = p1-1;
break;
case HCOM:
p1 = holdsp;
p2 = linebuf;
while(*p1++ = *p2++);
hspend = p1-1;
break;
case CHCOM:
*hspend++ = '\n';
p1 = hspend;
p2 = linebuf;
while(*p1++ = *p2++)
if(p1 >= hend)
break;
hspend = p1-1;
break;
case ICOM:
for(p1 = ipc->r1.re1; *p1; )
putc(*p1++, stdout);
putc('\n', stdout);
break;
case BCOM:
jflag = 1;
break;
case LCOM:
p1 = linebuf;
p2 = genbuf;
while(*p1) {
p2 = lformat(*p1++ & 0377, p2);
if(p2>lcomend && *p1) {
*p2 = 0;
fprintf(stdout, "%s\\\n", genbuf);
p2 = genbuf;
}
}
if(p2>genbuf && (p1[-1]==' '||p1[-1]=='\n'))
p2 = lformat('\n', p2);
*p2 = 0;
fprintf(stdout, "%s\n", genbuf);
break;
case NCOM:
if(!nflag) {
for(p1 = linebuf; p1 < spend; p1++)
putc(*p1, stdout);
putc('\n', stdout);
}
if(aptr > abuf)
arout();
if((execp = gline(linebuf)) == badp) {
pending = ipc;
delflag = 1;
break;
}
spend = execp;
break;
case CNCOM:
if(aptr > abuf)
arout();
*spend++ = '\n';
if((execp = gline(spend)) == badp) {
pending = ipc;
delflag = 1;
break;
}
spend = execp;
break;
case PCOM:
for(p1 = linebuf; p1 < spend; p1++)
putc(*p1, stdout);
putc('\n', stdout);
break;
case CPCOM:
cpcom:
for(p1 = linebuf; *p1 != '\n' && *p1 != '\0'; )
putc(*p1++, stdout);
putc('\n', stdout);
break;
case QCOM:
if(!nflag) {
for(p1 = linebuf; p1 < spend; p1++)
putc(*p1, stdout);
putc('\n', stdout);
}
if(aptr > abuf) arout();
fclose(stdout);
lseek(f,(long)(cbp-ebp),2);
exit(0);
case RCOM:
*aptr++ = ipc;
if(aptr >= &abuf[ABUFSIZE])
fprintf(stderr, "sed: Too many reads after line%ld\n",
lnum);
*aptr = 0;
break;
case SCOM:
i = substitute(ipc);
if(ipc->r1.pfl && i)
if(ipc->r1.pfl == 1) {
for(p1 = linebuf; p1 < spend; p1++)
putc(*p1, stdout);
putc('\n', stdout);
}
else
goto cpcom;
if(i && ipc->r1.fcode)
goto wcom;
break;
case TCOM:
if(sflag == 0) break;
sflag = 0;
jflag = 1;
break;
wcom:
case WCOM:
fprintf(ipc->r1.fcode, "%s\n", linebuf);
fflush(ipc->r1.fcode);
break;
case XCOM:
p1 = linebuf;
p2 = genbuf;
while(*p2++ = *p1++);
p1 = holdsp;
p2 = linebuf;
while(*p2++ = *p1++);
spend = p2 - 1;
p1 = genbuf;
p2 = holdsp;
while(*p2++ = *p1++);
hspend = p2 - 1;
break;
case YCOM:
p1 = linebuf;
p2 = ipc->r1.re1;
while(*p1 = p2[*p1]) p1++;
break;
}
}
uchar *
gline(uchar *addr)
{
uchar *p1, *p2;
int c;
sflag = 0;
p1 = addr;
p2 = cbp;
for (;;) {
if (p2 >= ebp) {
if ((c = Read(f, ibuf, 512)) <= 0) {
return(badp);
}
p2 = ibuf;
ebp = ibuf+c;
}
if ((c = *p2++) == '\n') {
if(p2 >= ebp) {
if((c = Read(f, ibuf, 512)) <= 0) {
close(f);
if(eargc == 0)
dolflag = 1;
}
p2 = ibuf;
ebp = ibuf + c;
}
break;
}
if(c)
if(p1 < lbend)
*p1++ = c;
}
lnum++;
*p1 = 0;
cbp = p2;
return(p1);
}
int
ecmp(uchar *a, uchar *b, int count)
{
while(count--)
if(*a++ != *b++) return(0);
return(1);
}
void
arout(void)
{
uchar *p1;
FILE *fi;
uchar c;
int t;
aptr = abuf - 1;
while(*++aptr) {
if((*aptr)->r1.command == ACOM) {
for(p1 = (*aptr)->r1.re1; *p1; )
putc(*p1++, stdout);
putc('\n', stdout);
} else {
if((fi = fopen((char*)((*aptr)->r1.re1), "r")) == NULL)
continue;
while((t = getc(fi)) != EOF) {
c = t;
putc(c, stdout);
}
fclose(fi);
}
}
aptr = abuf;
*aptr = 0;
}
uchar *
lformat(int c, uchar *p)
{
int trans =
c=='\b'? 'b':
c=='\t'? 't':
c=='\n'? 'n':
c=='\v'? 'v':
c=='\f'? 'f':
c=='\r'? 'r':
c=='\\'? '\\':
0;
if(trans) {
*p++ = '\\';
*p++ = trans;
} else if(c<040 || c>=0177) {
*p++ = '\\';
*p++ = ((c>>6)&07) + '0';
*p++ = ((c>>3)&07) + '0';
*p++ = (c&07) + '0';
} else
*p++ = c;
return p;
}
|