+#include <stdio.h>
+#include "sed.h"
+
+execute(file)
+char *file;
+{
+ register char *p1, *p2;
+ register union reptr *ipc;
+ int c;
+ char *execp;
+
+ if (file) {
+ if ((f = open(file, 0)) < 0) {
+ fprintf(stderr, "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->command; ) {
+
+ p1 = ipc->ad1;
+ p2 = ipc->ad2;
+
+ if(p1) {
+
+ if(ipc->inar) {
+ if(*p2 == CEND) {
+ p1 = 0;
+ } else if(*p2 == CLNUM) {
+ c = p2[1];
+ if(lnum > tlno[c]) {
+ ipc->inar = 0;
+ if(ipc->negfl)
+ goto yes;
+ ipc++;
+ continue;
+ }
+ if(lnum == tlno[c]) {
+ ipc->inar = 0;
+ }
+ } else if(match(p2, 0)) {
+ ipc->inar = 0;
+ }
+ } else if(*p1 == CEND) {
+ if(!dolflag) {
+ if(ipc->negfl)
+ goto yes;
+ ipc++;
+ continue;
+ }
+
+ } else if(*p1 == CLNUM) {
+ c = p1[1];
+ if(lnum != tlno[c]) {
+ if(ipc->negfl)
+ goto yes;
+ ipc++;
+ continue;
+ }
+ if(p2)
+ ipc->inar = 1;
+ } else if(match(p1, 0)) {
+ if(p2)
+ ipc->inar = 1;
+ } else {
+ if(ipc->negfl)
+ goto yes;
+ ipc++;
+ continue;
+ }
+ }
+
+ if(ipc->negfl) {
+ ipc++;
+ continue;
+ }
+ yes:
+ command(ipc);
+
+ if(delflag)
+ break;
+
+ if(jflag) {
+ jflag = 0;
+ if((ipc = ipc->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;
+
+ }
+}
+match(expbuf, gf)
+char *expbuf;
+{
+ register char *p1, *p2, 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);
+}
+advance(alp, aep)
+char *alp, *aep;
+{
+ register char *lp, *ep, *curlp;
+ char c;
+ char *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++ & 0177;
+ if(ep[c>>3] & bittab[c & 07]) {
+ ep += 16;
+ 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++ & 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))
+ 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, "RE botch, %o\n", *--ep);
+ }
+}
+substitute(ipc)
+union reptr *ipc;
+{
+ if(match(ipc->re1, 0) == 0) return(0);
+
+ sflag = 1;
+ dosub(ipc->rhs);
+
+ if(ipc->gfl) {
+ while(*loc2) {
+ if(match(ipc->re1, 1) == 0) break;
+ dosub(ipc->rhs);
+ }
+ }
+ 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&0200 && (c &= 0177) >= '1' && c < NBRA+'1') {
+ sp = place(sp, braslist[c-'1'], braelist[c-'1']);
+ continue;
+ }
+ *sp++ = c&0177;
+ if (sp >= &genbuf[LBSIZE])
+ fprintf(stderr, "output line too long.\n");
+ }
+ lp = loc2;
+ loc2 = sp - genbuf + linebuf;
+ while (*sp++ = *lp++)
+ if (sp >= &genbuf[LBSIZE]) {
+ fprintf(stderr, "Output line too long.\n");
+ }
+ lp = linebuf;
+ sp = genbuf;
+ while (*lp++ = *sp++);
+ spend = lp-1;
+}
+char *place(asp, al1, al2)
+char *asp, *al1, *al2;
+{
+ register char *sp, *l1, *l2;
+
+ sp = asp;
+ l1 = al1;
+ l2 = al2;
+ while (l1 < l2) {
+ *sp++ = *l1++;
+ if (sp >= &genbuf[LBSIZE])
+ fprintf(stderr, "Output line too long.\n");
+ }
+ return(sp);
+}
+
+command(ipc)
+union reptr *ipc;
+{
+ register int i;
+ register char *p1, *p2;
+ char *execp;
+
+
+ switch(ipc->command) {
+
+ case ACOM:
+ *aptr++ = ipc;
+ if(aptr >= &abuf[ABUFSIZE]) {
+ fprintf(stderr, "Too many appends after line %ld\n",
+ lnum);
+ }
+ *aptr = 0;
+ break;
+
+ case CCOM:
+ delflag = 1;
+ if(!ipc->inar || dolflag) {
+ for(p1 = ipc->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++);
+ 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++);
+ hspend = p1-1;
+ break;
+
+ case ICOM:
+ for(p1 = ipc->re1; *p1; )
+ putc(*p1++, stdout);
+ putc('\n', stdout);
+ break;
+
+ case BCOM:
+ jflag = 1;
+ break;
+
+ case LCOM:
+ 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);
+ exit(0);
+ case RCOM:
+
+ *aptr++ = ipc;
+ if(aptr >= &abuf[ABUFSIZE])
+ fprintf(stderr, "Too many reads after line%ld\n",
+ lnum);
+
+ *aptr = 0;
+
+ break;
+
+ case SCOM:
+ i = substitute(ipc);
+ if(ipc->pfl && nflag && i)
+ if(ipc->pfl == 1) {
+ for(p1 = linebuf; p1 < spend; p1++)
+ putc(*p1, stdout);
+ putc('\n', stdout);
+ }
+ else
+ goto cpcom;
+ if(i && ipc->fcode)
+ goto wcom;
+ break;
+
+ case TCOM:
+ if(sflag == 0) break;
+ sflag = 0;
+ jflag = 1;
+ break;
+
+ wcom:
+ case WCOM:
+ fprintf(ipc->fcode, "%s\n", linebuf);
+ 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->re1;
+ while(*p1 = p2[*p1]) p1++;
+ break;
+ }
+
+}
+
+char *gline(addr)
+char *addr;
+{
+ register char *p1, *p2;
+ register c;
+ 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);
+}
+ecmp(a, b, count)
+char *a, *b;
+{
+ while(count--)
+ if(*a++ != *b++) return(0);
+ return(1);
+}
+
+arout()
+{
+ register char *p1;
+ FILE *fi;
+ char c;
+ int t;
+
+ aptr = abuf - 1;
+ while(*++aptr) {
+ if((*aptr)->command == ACOM) {
+ for(p1 = (*aptr)->re1; *p1; )
+ putc(*p1++, stdout);
+ putc('\n', stdout);
+ } else {
+ if((fi = fopen((*aptr)->re1, "r")) == NULL)
+ continue;
+ while((t = getc(fi)) != EOF) {
+ c = t;
+ putc(c, stdout);
+ }
+ fclose(fi);
+ }
+ }
+ aptr = abuf;
+ *aptr = 0;
+}
+