diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/cmd/sed/sed1.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/cmd/sed/sed1.c')
-rwxr-xr-x | sys/src/ape/cmd/sed/sed1.c | 719 |
1 files changed, 719 insertions, 0 deletions
diff --git a/sys/src/ape/cmd/sed/sed1.c b/sys/src/ape/cmd/sed/sed1.c new file mode 100755 index 000000000..131e0e8a5 --- /dev/null +++ b/sys/src/ape/cmd/sed/sed1.c @@ -0,0 +1,719 @@ +#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; +} + |