summaryrefslogtreecommitdiff
path: root/sys/src/ape/cmd/sed
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/cmd/sed
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/cmd/sed')
-rwxr-xr-xsys/src/ape/cmd/sed/mkfile13
-rwxr-xr-xsys/src/ape/cmd/sed/sed.h178
-rwxr-xr-xsys/src/ape/cmd/sed/sed0.c994
-rwxr-xr-xsys/src/ape/cmd/sed/sed1.c719
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;
+}
+