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 |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/cmd/sed')
-rwxr-xr-x | sys/src/ape/cmd/sed/mkfile | 13 | ||||
-rwxr-xr-x | sys/src/ape/cmd/sed/sed.h | 178 | ||||
-rwxr-xr-x | sys/src/ape/cmd/sed/sed0.c | 994 | ||||
-rwxr-xr-x | sys/src/ape/cmd/sed/sed1.c | 719 |
4 files changed, 1904 insertions, 0 deletions
diff --git a/sys/src/ape/cmd/sed/mkfile b/sys/src/ape/cmd/sed/mkfile new file mode 100755 index 000000000..d280c30eb --- /dev/null +++ b/sys/src/ape/cmd/sed/mkfile @@ -0,0 +1,13 @@ +APE=/sys/src/ape +<$APE/config + +TARG=sed +OFILES=sed0.$O\ + sed1.$O + +HFILES=sed.h + +BIN=$APEBIN +</sys/src/cmd/mkone + +CFLAGS=-c -D_POSIX_SOURCE diff --git a/sys/src/ape/cmd/sed/sed.h b/sys/src/ape/cmd/sed/sed.h new file mode 100755 index 000000000..ac4481bd8 --- /dev/null +++ b/sys/src/ape/cmd/sed/sed.h @@ -0,0 +1,178 @@ +# +/* + * sed -- stream editor + * + * + */ + +#define CBRA 1 +#define CCHR 2 +#define CDOT 4 +#define CCL 6 +#define CNL 8 +#define CDOL 10 +#define CEOF 11 +#define CKET 12 +#define CNULL 13 +#define CLNUM 14 +#define CEND 16 +#define CDONT 17 +#define CBACK 18 + +#define STAR 01 + +#define NLINES 256 +#define DEPTH 20 +#define PTRSIZE 1024 +#define RESIZE 20000 +#define ABUFSIZE 20 +#define LBSIZE 4000 +#define LABSIZE 50 +#define NBRA 9 + +typedef unsigned char uchar; + +FILE *fin; +union reptr *abuf[ABUFSIZE]; +union reptr **aptr; +uchar *lastre; +uchar ibuf[512]; +uchar *cbp; +uchar *ebp; +uchar genbuf[LBSIZE]; +uchar *loc1; +uchar *loc2; +uchar *locs; +uchar seof; +uchar *reend; +uchar *lbend; +uchar *hend; +uchar *lcomend; +union reptr *ptrend; +int eflag; +int dolflag; +int sflag; +int jflag; +int numbra; +int delflag; +long lnum; +uchar linebuf[LBSIZE+1]; +uchar holdsp[LBSIZE+1]; +uchar *spend; +uchar *hspend; +int nflag; +int gflag; +uchar *braelist[NBRA]; +uchar *braslist[NBRA]; +long tlno[NLINES]; +int nlno; +#define MAXFILES 120 +char fname[MAXFILES][40]; +FILE *fcode[MAXFILES]; +int nfiles; + +#define ACOM 01 +#define BCOM 020 +#define CCOM 02 +#define CDCOM 025 +#define CNCOM 022 +#define COCOM 017 +#define CPCOM 023 +#define DCOM 03 +#define ECOM 015 +#define EQCOM 013 +#define FCOM 016 +#define GCOM 027 +#define CGCOM 030 +#define HCOM 031 +#define CHCOM 032 +#define ICOM 04 +#define LCOM 05 +#define NCOM 012 +#define PCOM 010 +#define QCOM 011 +#define RCOM 06 +#define SCOM 07 +#define TCOM 021 +#define WCOM 014 +#define CWCOM 024 +#define YCOM 026 +#define XCOM 033 + +uchar *cp; +uchar *reend; +uchar *lbend; + +union reptr { + struct reptr1 { + uchar *ad1; + uchar *ad2; + uchar *re1; + uchar *rhs; + FILE *fcode; + uchar command; + uchar gfl; + uchar pfl; + uchar inar; + uchar negfl; + } r1; + struct reptr2 { + uchar *ad1; + uchar *ad2; + union reptr *lb1; + uchar *rhs; + FILE *fcode; + uchar command; + uchar gfl; + uchar pfl; + uchar inar; + uchar negfl; + } r2; +} ptrspace[PTRSIZE], *rep; + + +uchar respace[RESIZE]; + +struct label { + uchar asc[9]; + union reptr *chain; + union reptr *address; +} ltab[LABSIZE]; + +struct label *lab; +struct label *labend; + +int f; +int depth; + +int eargc; +uchar **eargv; + +uchar *address(uchar *); +int advance(uchar *, uchar *); +void arout(void); +extern uchar bittab[]; +uchar bad; +uchar *badp; +int cmp(uchar *, uchar *); +union reptr **cmpend[DEPTH]; +void command(union reptr *); +uchar compfl; +uchar *compile(uchar *); +uchar *compsub(uchar *); +void dechain(void); +int depth; +void dosub(uchar *); +int ecmp(uchar *, uchar *, int); +void execute(uchar *); +void fcomp(void); +uchar *gline(uchar *); +uchar *lformat(int, uchar *); +int match(uchar *, int); +union reptr *pending; +uchar *place(uchar *, uchar *, uchar *); +int rline(uchar *); +struct label *search(struct label *); +int substitute(union reptr *); +uchar *text(uchar *); +uchar *ycomp(uchar *); diff --git a/sys/src/ape/cmd/sed/sed0.c b/sys/src/ape/cmd/sed/sed0.c new file mode 100755 index 000000000..be117aaba --- /dev/null +++ b/sys/src/ape/cmd/sed/sed0.c @@ -0,0 +1,994 @@ +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include "sed.h" + +struct label *labtab = ltab; +char CGMES[] = "sed: Command garbled: %s\n"; +char TMMES[] = "sed: Too much text: %s\n"; +char LTL[] = "sed: Label too long: %s\n"; +char AD0MES[] = "sed: No addresses allowed: %s\n"; +char AD1MES[] = "sed: Only one address allowed: %s\n"; +uchar bittab[] = { + 1, + 2, + 4, + 8, + 16, + 32, + 64, + 128 + }; + +main(int argc, char **argv) +{ + + eargc = argc; + eargv = (uchar**)argv; + + badp = &bad; + aptr = abuf; + hspend = holdsp; + lab = labtab + 1; /* 0 reserved for end-pointer */ + rep = ptrspace; + rep->r1.ad1 = respace; + lbend = &linebuf[LBSIZE]; + hend = &holdsp[LBSIZE]; + lcomend = &genbuf[64]; + ptrend = &ptrspace[PTRSIZE]; + reend = &respace[RESIZE]; + labend = &labtab[LABSIZE]; + lnum = 0; + pending = 0; + depth = 0; + spend = linebuf; + hspend = holdsp; + fcode[0] = stdout; + nfiles = 1; + lastre = NULL; + + if(eargc == 1) + exit(0); + + + while (--eargc > 0 && (++eargv)[0][0] == '-') + switch (eargv[0][1]) { + + case 'n': + nflag++; + continue; + + case 'f': + if(eargc-- <= 0) exit(2); + + if((fin = fopen((char*)(*++eargv), "r")) == NULL) { + fprintf(stderr, "sed: Cannot open pattern-file: %s\n", *eargv); + exit(2); + } + + fcomp(); + fclose(fin); + continue; + + case 'e': + eflag++; + fcomp(); + eflag = 0; + continue; + + case 'g': + gflag++; + continue; + + default: + fprintf(stderr, "sed: Unknown flag: %c\n", eargv[0][1]); + continue; + } + + + if(compfl == 0) { + eargv--; + eargc++; + eflag++; + fcomp(); + eargv++; + eargc--; + eflag = 0; + } + + if(depth) { + fprintf(stderr, "sed: Too many {'s\n"); + exit(2); + } + + labtab->address = rep; + + dechain(); + +/* abort(); /*DEBUG*/ + + if(eargc <= 0) + execute((uchar *)NULL); + else while(--eargc >= 0) { + execute(*eargv++); + } + fclose(stdout); + exit(0); +} +void +fcomp(void) +{ + + uchar *p, *op, *tp; + uchar *address(uchar*); + union reptr *pt, *pt1; + int i; + struct label *lpt; + + compfl = 1; + op = lastre; + + if(rline(linebuf) < 0) { + lastre = op; + return; + } + if(*linebuf == '#') { + if(linebuf[1] == 'n') + nflag = 1; + } + else { + cp = linebuf; + goto comploop; + } + + for(;;) { + if(rline(linebuf) < 0) break; + + cp = linebuf; + +comploop: +/* fprintf(stdout, "cp: %s\n", cp); /*DEBUG*/ + while(*cp == ' ' || *cp == '\t') cp++; + if(*cp == '\0' || *cp == '#') continue; + if(*cp == ';') { + cp++; + goto comploop; + } + + p = address(rep->r1.ad1); + if(p == badp) { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + + if(p == 0) { + p = rep->r1.ad1; + rep->r1.ad1 = 0; + } else { + if(p == rep->r1.ad1) { + if(op) + rep->r1.ad1 = op; + else { + fprintf(stderr, "sed: First RE may not be null\n"); + exit(2); + } + } + if(*rep->r1.ad1 != CLNUM && *rep->r1.ad1 != CEND) + op = rep->r1.ad1; + if(*cp == ',' || *cp == ';') { + cp++; + if((rep->r1.ad2 = p) > reend) { + fprintf(stderr, TMMES, linebuf); + exit(2); + } + p = address(rep->r1.ad2); + if(p == badp || p == 0) { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + if(p == rep->r1.ad2) + rep->r1.ad2 = op; + else{ + if(*rep->r1.ad2 != CLNUM && *rep->r1.ad2 != CEND) + op = rep->r1.ad2; + } + + } else + rep->r1.ad2 = 0; + } + + if(p > reend) { + fprintf(stderr, "sed: Too much text: %s\n", linebuf); + exit(2); + } + + while(*cp == ' ' || *cp == '\t') cp++; + +swit: + switch(*cp++) { + + default: +/*fprintf(stderr, "cp = %d; *cp = %o\n", cp - linebuf, *cp);*/ + fprintf(stderr, "sed: Unrecognized command: %s\n", linebuf); + exit(2); + + case '!': + rep->r1.negfl = 1; + goto swit; + + case '{': + rep->r1.command = BCOM; + rep->r1.negfl = !(rep->r1.negfl); + cmpend[depth++] = &rep->r2.lb1; + if(++rep >= ptrend) { + fprintf(stderr, "sed: Too many commands: %s\n", linebuf); + exit(2); + } + rep->r1.ad1 = p; + if(*cp == '\0') continue; + + goto comploop; + + case '}': + if(rep->r1.ad1) { + fprintf(stderr, AD0MES, linebuf); + exit(2); + } + + if(--depth < 0) { + fprintf(stderr, "sed: Too many }'s\n"); + exit(2); + } + *cmpend[depth] = rep; + + rep->r1.ad1 = p; + if(*cp == 0) continue; + goto comploop; + + case '=': + rep->r1.command = EQCOM; + if(rep->r1.ad2) { + fprintf(stderr, AD1MES, linebuf); + exit(2); + } + break; + + case ':': + if(rep->r1.ad1) { + fprintf(stderr, AD0MES, linebuf); + exit(2); + } + + while(*cp++ == ' '); + cp--; + + + tp = lab->asc; + while((*tp = *cp++) && *tp != ';') + if(++tp >= &(lab->asc[8])) { + fprintf(stderr, LTL, linebuf); + exit(2); + } + *tp = '\0'; + if(*lab->asc == 0) { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + + if(lpt = search(lab)) { + if(lpt->address) { + fprintf(stderr, "sed: Duplicate labels: %s\n", linebuf); + exit(2); + } + } else { + lab->chain = 0; + lpt = lab; + if(++lab >= labend) { + fprintf(stderr, "sed: Too many labels: %s\n", linebuf); + exit(2); + } + } + lpt->address = rep; + rep->r1.ad1 = p; + + continue; + + case 'a': + rep->r1.command = ACOM; + if(rep->r1.ad2) { + fprintf(stderr, AD1MES, linebuf); + exit(2); + } + if(*cp == '\\') cp++; + if(*cp++ != '\n') { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + rep->r1.re1 = p; + p = text(rep->r1.re1); + break; + case 'c': + rep->r1.command = CCOM; + if(*cp == '\\') cp++; + if(*cp++ != ('\n')) { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + rep->r1.re1 = p; + p = text(rep->r1.re1); + break; + case 'i': + rep->r1.command = ICOM; + if(rep->r1.ad2) { + fprintf(stderr, AD1MES, linebuf); + exit(2); + } + if(*cp == '\\') cp++; + if(*cp++ != ('\n')) { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + rep->r1.re1 = p; + p = text(rep->r1.re1); + break; + + case 'g': + rep->r1.command = GCOM; + break; + + case 'G': + rep->r1.command = CGCOM; + break; + + case 'h': + rep->r1.command = HCOM; + break; + + case 'H': + rep->r1.command = CHCOM; + break; + + case 't': + rep->r1.command = TCOM; + goto jtcommon; + + case 'b': + rep->r1.command = BCOM; +jtcommon: + while(*cp++ == ' '); + cp--; + + if(*cp == '\0') { + if(pt = labtab->chain) { + while(pt1 = pt->r2.lb1) + pt = pt1; + pt->r2.lb1 = rep; + } else + labtab->chain = rep; + break; + } + tp = lab->asc; + while((*tp = *cp++) && *tp != ';') + if(++tp >= &(lab->asc[8])) { + fprintf(stderr, LTL, linebuf); + exit(2); + } + cp--; + *tp = '\0'; + if(*lab->asc == 0) { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + + if(lpt = search(lab)) { + if(lpt->address) { + rep->r2.lb1 = lpt->address; + } else { + pt = lpt->chain; + while(pt1 = pt->r2.lb1) + pt = pt1; + pt->r2.lb1 = rep; + } + } else { + lab->chain = rep; + lab->address = 0; + if(++lab >= labend) { + fprintf(stderr, "sed: Too many labels: %s\n", linebuf); + exit(2); + } + } + break; + + case 'n': + rep->r1.command = NCOM; + break; + + case 'N': + rep->r1.command = CNCOM; + break; + + case 'p': + rep->r1.command = PCOM; + break; + + case 'P': + rep->r1.command = CPCOM; + break; + + case 'r': + rep->r1.command = RCOM; + if(rep->r1.ad2) { + fprintf(stderr, AD1MES, linebuf); + exit(2); + } + if(*cp++ != ' ') { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + rep->r1.re1 = p; + p = text(rep->r1.re1); + break; + + case 'd': + rep->r1.command = DCOM; + break; + + case 'D': + rep->r1.command = CDCOM; + rep->r2.lb1 = ptrspace; + break; + + case 'q': + rep->r1.command = QCOM; + if(rep->r1.ad2) { + fprintf(stderr, AD1MES, linebuf); + exit(2); + } + break; + + case 'l': + rep->r1.command = LCOM; + break; + + case 's': + rep->r1.command = SCOM; + seof = *cp++; + rep->r1.re1 = p; + p = compile(rep->r1.re1); + if(p == badp) { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + if(p == rep->r1.re1) { + if(op == NULL) { + fprintf(stderr, "sed: First RE may not be null.\n"); + exit(2); + } + rep->r1.re1 = op; + } else { + op = rep->r1.re1; + } + + if((rep->r1.rhs = p) > reend) { + fprintf(stderr, TMMES, linebuf); + exit(2); + } + + if((p = compsub(rep->r1.rhs)) == badp) { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + if(*cp == 'g') { + cp++; + rep->r1.gfl++; + } else if(gflag) + rep->r1.gfl++; + + if(*cp == 'p') { + cp++; + rep->r1.pfl = 1; + } + + if(*cp == 'P') { + cp++; + rep->r1.pfl = 2; + } + + if(*cp == 'w') { + cp++; + if(*cp++ != ' ') { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + if(nfiles >= MAXFILES) { + fprintf(stderr, "sed: Too many files in w commands 1 \n"); + exit(2); + } + + text((uchar*)fname[nfiles]); + for(i = nfiles - 1; i >= 0; i--) + if(cmp((uchar*)fname[nfiles],(uchar*)fname[i]) == 0) { + rep->r1.fcode = fcode[i]; + goto done; + } + if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) { + fprintf(stderr, "sed: Cannot open %s\n", fname[nfiles]); + exit(2); + } + fcode[nfiles++] = rep->r1.fcode; + } + break; + + case 'w': + rep->r1.command = WCOM; + if(*cp++ != ' ') { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + if(nfiles >= MAXFILES){ + fprintf(stderr, "sed: Too many files in w commands 2 \n"); + fprintf(stderr, "nfiles = %d; MAXF = %d\n", nfiles, MAXFILES); + exit(2); + } + + text((uchar*)fname[nfiles]); + for(i = nfiles - 1; i >= 0; i--) + if(cmp((uchar*)fname[nfiles], (uchar*)fname[i]) == 0) { + rep->r1.fcode = fcode[i]; + goto done; + } + + if((rep->r1.fcode = fopen(fname[nfiles], "w")) == NULL) { + fprintf(stderr, "sed: Cannot create %s\n", fname[nfiles]); + exit(2); + } + fcode[nfiles++] = rep->r1.fcode; + break; + + case 'x': + rep->r1.command = XCOM; + break; + + case 'y': + rep->r1.command = YCOM; + seof = *cp++; + rep->r1.re1 = p; + p = ycomp(rep->r1.re1); + if(p == badp) { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + if(p > reend) { + fprintf(stderr, TMMES, linebuf); + exit(2); + } + break; + + } +done: + if(++rep >= ptrend) { + fprintf(stderr, "sed: Too many commands, last: %s\n", linebuf); + exit(2); + } + + rep->r1.ad1 = p; + + if(*cp++ != '\0') { + if(cp[-1] == ';') + goto comploop; + fprintf(stderr, CGMES, linebuf); + exit(2); + } + + } +} + +uchar * +compsub(uchar *rhsbuf) +{ + uchar *p, *q, *r; + p = rhsbuf; + q = cp; + for(;;) { + if((*p = *q++) == '\\') { + *++p = *q++; + if(*p >= '1' && *p <= '9' && *p > numbra + '0') + return(badp); + if(*p == 'n') + *--p = '\n'; + } else if(*p == seof) { + *p++ = '\0'; + cp = q; + return(p); + } + if(*p++ == '\0') { + return(badp); + } + + } +} + +uchar * +compile(uchar *expbuf) +{ + int c; + uchar *ep, *sp; + uchar neg; + uchar *lastep, *cstart; + int cclcnt; + int closed; + uchar bracket[NBRA], *bracketp; + + if(*cp == seof) { + cp++; + return(expbuf); + } + + ep = expbuf; + lastep = 0; + bracketp = bracket; + closed = numbra = 0; + sp = cp; + if (*sp == '^') { + *ep++ = 1; + sp++; + } else { + *ep++ = 0; + } + for (;;) { + if (ep >= reend) { + cp = sp; + return(badp); + } + if((c = *sp++) == seof) { + if(bracketp != bracket) { + cp = sp; + return(badp); + } + cp = sp; + *ep++ = CEOF; + return(ep); + } + if(c != '*') + lastep = ep; + switch (c) { + + case '\\': + if((c = *sp++) == '(') { + if(numbra >= NBRA) { + cp = sp; + return(badp); + } + *bracketp++ = numbra; + *ep++ = CBRA; + *ep++ = numbra++; + continue; + } + if(c == ')') { + if(bracketp <= bracket) { + cp = sp; + return(badp); + } + *ep++ = CKET; + *ep++ = *--bracketp; + closed++; + continue; + } + + if(c >= '1' && c <= '9') { + if((c -= '1') >= closed) + return(badp); + + *ep++ = CBACK; + *ep++ = c; + continue; + } + if(c == '\n') { + cp = sp; + return(badp); + } + if(c == 'n') { + c = '\n'; + } + goto defchar; + + case '\0': + case '\n': + cp = sp; + return(badp); + + case '.': + *ep++ = CDOT; + continue; + + case '*': + if (lastep == 0) + goto defchar; + if(*lastep == CKET) { + cp = sp; + return(badp); + } + *lastep |= STAR; + continue; + + case '$': + if (*sp != seof) + goto defchar; + *ep++ = CDOL; + continue; + + case '[': + if(&ep[33] >= reend) { + fprintf(stderr, "sed: RE too long: %s\n", linebuf); + exit(2); + } + + *ep++ = CCL; + + neg = 0; + if((c = *sp++) == '^') { + neg = 1; + c = *sp++; + } + + cstart = sp; + do { + if(c == '\0') { + fprintf(stderr, CGMES, linebuf); + exit(2); + } + if (c=='-' && sp>cstart && *sp!=']') { + for (c = sp[-2]; c<*sp; c++) + ep[c>>3] |= bittab[c&07]; + } + if(c == '\\') { + switch(c = *sp++) { + case 'n': + c = '\n'; + break; + } + } + + ep[c >> 3] |= bittab[c & 07]; + } while((c = *sp++) != ']'); + + if(neg) + for(cclcnt = 0; cclcnt < 32; cclcnt++) + ep[cclcnt] ^= -1; + ep[0] &= 0376; + + ep += 32; + + continue; + + defchar: + default: + *ep++ = CCHR; + *ep++ = c; + } + } +} +int +rline(uchar *lbuf) +{ + uchar *p, *q; + int t; + static uchar *saveq; + + p = lbuf - 1; + + if(eflag) { + if(eflag > 0) { + eflag = -1; + if(eargc-- <= 0) + exit(2); + q = *++eargv; + while(*++p = *q++) { + if(*p == '\\') { + if((*++p = *q++) == '\0') { + saveq = 0; + return(-1); + } else + continue; + } + if(*p == '\n') { + *p = '\0'; + saveq = q; + return(1); + } + } + saveq = 0; + return(1); + } + if((q = saveq) == 0) return(-1); + + while(*++p = *q++) { + if(*p == '\\') { + if((*++p = *q++) == '0') { + saveq = 0; + return(-1); + } else + continue; + } + if(*p == '\n') { + *p = '\0'; + saveq = q; + return(1); + } + } + saveq = 0; + return(1); + } + + while((t = getc(fin)) != EOF) { + *++p = t; + if(*p == '\\') { + t = getc(fin); + *++p = t; + } + else if(*p == '\n') { + *p = '\0'; + return(1); + } + } + *++p = '\0'; + return(-1); +} + +uchar * +address(uchar *expbuf) +{ + uchar *rcp; + long lno; + + if(*cp == '$') { + cp++; + *expbuf++ = CEND; + *expbuf++ = CEOF; + return(expbuf); + } + + if(*cp == '/') { + seof = '/'; + cp++; + return(compile(expbuf)); + } + + rcp = cp; + lno = 0; + + while(*rcp >= '0' && *rcp <= '9') + lno = lno*10 + *rcp++ - '0'; + + if(rcp > cp) { + if(!lno){ + fprintf(stderr, "sed: line number 0 is illegal\n"); + exit(2); + } + *expbuf++ = CLNUM; + *expbuf++ = lno; + *expbuf++ = lno >> 8; + *expbuf++ = lno >> 16; + *expbuf++ = lno >> 24; + *expbuf++ = CEOF; + cp = rcp; + return(expbuf); + } + return(0); +} +int +cmp(uchar *a, uchar *b) +{ + uchar *ra, *rb; + + ra = a - 1; + rb = b - 1; + + while(*++ra == *++rb) + if(*ra == '\0') return(0); + return(1); +} + +uchar * +text(uchar *textbuf) +{ + uchar *p, *q; + + p = textbuf; + q = cp; + while(*q == '\t' || *q == ' ') q++; + for(;;) { + + if((*p = *q++) == '\\') + *p = *q++; + if(*p == '\0') { + cp = --q; + return(++p); + } + if(*p == '\n') { + while(*q == '\t' || *q == ' ') q++; + } + p++; + } +} + + +struct label * +search(struct label *ptr) +{ + struct label *rp; + + rp = labtab; + while(rp < ptr) { + if(cmp(rp->asc, ptr->asc) == 0) + return(rp); + rp++; + } + + return(0); +} + +void +dechain(void) +{ + struct label *lptr; + union reptr *rptr, *trptr; + + for(lptr = labtab; lptr < lab; lptr++) { + + if(lptr->address == 0) { + fprintf(stderr, "sed: Undefined label: %s\n", lptr->asc); + exit(2); + } + + if(lptr->chain) { + rptr = lptr->chain; + while(trptr = rptr->r2.lb1) { + rptr->r2.lb1 = lptr->address; + rptr = trptr; + } + rptr->r2.lb1 = lptr->address; + } + } +} + +uchar * +ycomp(uchar *expbuf) +{ + uchar *ep, *tsp; + int c; + uchar *sp; + + ep = expbuf; + sp = cp; + for(tsp = cp; *tsp != seof; tsp++) { + if(*tsp == '\\') + tsp++; + if(*tsp == '\n' || *tsp == '\0') + return(badp); + } + tsp++; + + while((c = *sp++) != seof) { + if(c == '\\' && *sp == 'n') { + sp++; + c = '\n'; + } + if((ep[c] = *tsp++) == '\\' && *tsp == 'n') { + ep[c] = '\n'; + tsp++; + } + if(ep[c] == seof || ep[c] == '\0') + return(badp); + } + if(*tsp != seof) + return(badp); + cp = ++tsp; + + for(c = 0; c<0400; c++) + if(ep[c] == 0) + ep[c] = c; + + return(ep + 0400); +} + 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; +} + |