/* * From https://github.com/geocar/ed-v6 * On Slackware 15.0 32bit compile with... * gcc -m32 -O2 -march=i686 \ * -static \ * -mtune=i686 -Os -ansi \ * -w -D_XOPEN_SOURCE=500 \ * -o 6ed 6ed.c * * sbrk(4096) increased to sbrk(12288) allowing 3070 lines * to be in buffer before segfaults. */ #include #include #include #include #include /* * Editor */ #define FNSIZE 64 /* file name size */ #define LBSIZE 512 /* line buffer length max */ #define ESIZE 128 /* regexp length max */ #define GBSIZE 256 /* global command length max */ #define NBRA 5 #define EOF -1 #define CBRA 1 #define CCHR 2 #define CDOT 4 #define CCL 6 #define NCCL 8 #define CDOL 10 #define CEOF 11 #define CKET 12 #define STAR 01 #define error errlab() #define READ 0 #define WRITE 1 jmp_buf setexit; int peekc; int lastc; char savedfile[FNSIZE]; char file[FNSIZE]; char linebuf[LBSIZE]; char rhsbuf[LBSIZE/2]; char expbuf[ESIZE+4]; int circfl; int *zero; int *dot; int *dol; int *endcore; int *fendcore; int *addr1; int *addr2; char genbuf[LBSIZE]; int count[2]; char *nextip; char *linebp; int ninbuf; int io; int pflag; void *onhup; void *onquit; int vflag = 1; int listf; int col; char *globp; int tfile = -1; int tline; char tfname[16]; char *loc1; char *loc2; char *locs; char ibuff[512]; int iblock = -1; char obuff[512]; int oblock = -1; int ichanged; int nleft; void errfunc(void); void (*errlab)(void); char TMPERR[] ="TMP"; int names[26]; char *braslist[NBRA]; char *braelist[NBRA]; main(argc, argv) char **argv; { char *p1, *p2; extern int onintr(); errlab = errfunc; onquit = signal(SIGQUIT, SIG_IGN); onhup = signal(SIGHUP, SIG_IGN); argv++; if (argc > 1 && **argv=='-') { vflag = 0; /* allow debugging quits? */ if ((*argv)[1]=='q') { signal(SIGQUIT, SIG_DFL); vflag++; } argv++; argc--; } if (argc>1) { p1 = *argv; p2 = savedfile; while (*p2++ = *p1++); globp = "r"; } fendcore = sbrk(0); init(); if ((signal(SIGINT, SIG_IGN)) != SIG_IGN) signal(SIGINT, onintr); setjmp(setexit); commands(); unlink(tfname); } commands() { int getfile(), gettty(); int *a1, c; char *p; int r; for (;;) { if (pflag) { pflag = 0; addr1 = addr2 = dot; goto print; } addr1 = 0; addr2 = 0; do { addr1 = addr2; if ((a1 = address())==0) { c = getchar(); break; } addr2 = a1; if ((c=getchar()) == ';') { c = ','; dot = a1; } } while (c==','); if (addr1==0) addr1 = addr2; switch(c) { case 'a': setdot(); newline(); append(gettty, addr2); continue; case 'c': delete(); append(gettty, addr1-1); continue; case 'd': delete(); continue; case 'e': setnoaddr(); if ((peekc = getchar()) != ' ') error; savedfile[0] = 0; init(); addr2 = zero; goto caseread; case 'f': setnoaddr(); if ((c = getchar()) != '\n') { peekc = c; savedfile[0] = 0; filename(); } puts(savedfile); continue; case 'g': global(1); continue; case 'i': setdot(); nonzero(); newline(); append(gettty, addr2-1); continue; case 'k': if ((c = getchar()) < 'a' || c > 'z') error; newline(); setdot(); nonzero(); names[c-'a'] = *addr2 | 01; continue; case 'm': move(0); continue; case '\n': if (addr2==0) addr2 = dot+1; addr1 = addr2; goto print; case 'l': listf++; case 'p': newline(); print: setdot(); nonzero(); a1 = addr1; do puts(getline(*a1++)); while (a1 <= addr2); dot = addr2; listf = 0; continue; case 'q': setnoaddr(); newline(); unlink(tfname); exit(0); case 'r': caseread: filename(); if ((io = open(file, 0)) < 0) { lastc = '\n'; error; } setall(); ninbuf = 0; append(getfile, addr2); exfile(); continue; case 's': setdot(); nonzero(); substitute(globp); continue; case 't': move(1); continue; case 'v': global(0); continue; case 'w': setall(); nonzero(); filename(); if ((io = creat(file, 0666)) < 0) error; putfile(); exfile(); continue; case '=': setall(); newline(); count[1] = (addr2-zero)&077777; putd(); putc('\n'); continue; case '!': run_unix(); continue; case EOF: return; } error; } } address() { int *a1, minus, c; int n, relerr; minus = 0; a1 = 0; for (;;) { c = getchar(); if ('0'<=c && c<='9') { n = 0; do { n *= 10; n += c - '0'; } while ((c = getchar())>='0' && c<='9'); peekc = c; if (a1==0) a1 = zero; if (minus<0) n = -n; a1 += n; minus = 0; continue; } relerr = 0; if (a1 || minus) relerr++; switch(c) { case ' ': case '\t': continue; case '+': minus++; if (a1==0) a1 = dot; continue; case '-': case '^': minus--; if (a1==0) a1 = dot; continue; case '?': case '/': compile(c); a1 = dot; for (;;) { if (c=='/') { a1++; if (a1 > dol) a1 = zero; } else { a1--; if (a1 < zero) a1 = dol; } if (execute(0, a1)) break; if (a1==dot) error; } break; case '$': a1 = dol; break; case '.': a1 = dot; break; case '\'': if ((c = getchar()) < 'a' || c > 'z') error; for (a1=zero; a1<=dol; a1++) if (names[c-'a'] == (*a1|01)) break; break; default: peekc = c; if (a1==0) return(0); a1 += minus; if (a1dol) error; return(a1); } if (relerr) error; } } setdot() { if (addr2 == 0) addr1 = addr2 = dot; if (addr1 > addr2) error; } setall() { if (addr2==0) { addr1 = zero+1; addr2 = dol; if (dol==zero) addr1 = zero; } setdot(); } setnoaddr() { if (addr2) error; } nonzero() { if (addr1<=zero || addr2>dol) error; } newline() { int c; if ((c = getchar()) == '\n') return; if (c=='p' || c=='l') { pflag++; if (c=='l') listf++; if (getchar() == '\n') return; } error; } filename() { char *p1, *p2; int c; count[1] = 0; c = getchar(); if (c=='\n' || c==EOF) { p1 = savedfile; if (*p1==0) error; p2 = file; while (*p2++ = *p1++); return; } if (c!=' ') error; while ((c = getchar()) == ' '); if (c=='\n') error; p1 = file; do { *p1++ = c; } while ((c = getchar()) != '\n'); *p1++ = 0; if (savedfile[0]==0) { p1 = savedfile; p2 = file; while (*p1++ = *p2++); } } exfile() { close(io); io = -1; if (vflag) { putd(); putc('\n'); } } onintr() { signal(SIGINT, onintr); putc('\n'); lastc = '\n'; error; } void errfunc(void) { int c; listf = 0; puts("?"); count[0] = 0; lseek(0, 0, SEEK_END); pflag = 0; if (globp) lastc = '\n'; globp = 0; peekc = lastc; while ((c = getchar()) != '\n' && c != EOF); if (io > 0) { close(io); io = -1; } longjmp(setexit,1); } getchar() { if (lastc=peekc) { peekc = 0; return(lastc); } if (globp) { if ((lastc = *globp++) != 0) return(lastc); globp = 0; return(EOF); } if (read(0, &lastc, 1) <= 0) return(lastc = EOF); lastc &= 0177; return(lastc); } gettty() { int c, gf; char *p; p = linebuf; gf = globp; while ((c = getchar()) != '\n') { if (c==EOF) { if (gf) peekc = c; return(c); } if ((c &= 0177) == 0) continue; *p++ = c; if (p >= &linebuf[LBSIZE-2]) error; } *p++ = 0; if (linebuf[0]=='.' && linebuf[1]==0) return(EOF); return(0); } getfile() { int c; char *lp, *fp; lp = linebuf; fp = nextip; do { if (--ninbuf < 0) { if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0) return(EOF); fp = genbuf; } if (lp >= &linebuf[LBSIZE]) error; if ((*lp++ = c = *fp++ & 0177) == 0) { lp--; continue; } if (++count[1] == 0) ++count[0]; } while (c != '\n'); *--lp = 0; nextip = fp; return(0); } putfile() { int *a1; char *fp, *lp; int nib; nib = 512; fp = genbuf; a1 = addr1; do { lp = getline(*a1++); for (;;) { if (--nib < 0) { write(io, genbuf, fp-genbuf); nib = 511; fp = genbuf; } if (++count[1] == 0) ++count[0]; if ((*fp++ = *lp++) == 0) { fp[-1] = '\n'; break; } } } while (a1 <= addr2); write(io, genbuf, fp-genbuf); } append(f, a) int (*f)(); { int *a1, *a2, *rdot; int nline, tl; struct { int integer; }; nline = 0; dot = a; while ((*f)() == 0) { if (dol >= endcore) { if (sbrk(12288) == -1) error; endcore += 12288; } tl = putline(); nline++; a1 = ++dol; a2 = a1+1; rdot = ++dot; while (a1 > rdot) *--a2 = *--a1; *rdot = tl; } return(nline); } run_unix() { int savint, pid, rpid; int retcode; setnoaddr(); if ((pid = fork()) == 0) { signal(SIGHUP, onhup); signal(SIGQUIT, onquit); execl("/bin/sh", "sh", "-t", 0); exit(255); } savint = signal(SIGINT, SIG_IGN); while ((rpid = wait(&retcode)) != pid && rpid != -1); signal(SIGINT, savint); puts("!"); } delete() { int *a1, *a2, *a3; setdot(); newline(); nonzero(); a1 = addr1; a2 = addr2+1; a3 = dol; dol -= a2 - a1; do *a1++ = *a2++; while (a2 <= a3); a1 = addr1; if (a1 > dol) a1 = dol; dot = a1; } getline(tl) { char *bp, *lp; int nl; lp = linebuf; bp = getblock(tl, READ); nl = nleft; tl &= ~0377; while (*lp++ = *bp++) if (--nl == 0) { bp = getblock(tl+=0400, READ); nl = nleft; } return(linebuf); } putline() { char *bp, *lp; int nl; int tl; lp = linebuf; tl = tline; bp = getblock(tl, WRITE); nl = nleft; tl &= ~0377; while (*bp = *lp++) { if (*bp++ == '\n') { *--bp = 0; linebp = lp; break; } if (--nl == 0) { bp = getblock(tl+=0400, WRITE); nl = nleft; } } nl = tline; tline += (((lp-linebuf)+03)>>1)&077776; return(nl); } getblock(atl, iof) { extern read(), write(); int bno, off; bno = (atl>>8)&0377; off = (atl<<1)&0774; if (bno >= 255) { puts(TMPERR); error; } nleft = 512 - off; if (bno==iblock) { ichanged |= iof; return(ibuff+off); } if (bno==oblock) return(obuff+off); if (iof==READ) { if (ichanged) blkio(iblock, ibuff, write); ichanged = 0; iblock = bno; blkio(bno, ibuff, read); return(ibuff+off); } if (oblock>=0) blkio(oblock, obuff, write); oblock = bno; return(obuff+off); } blkio(b, buf, iofcn) int (*iofcn)(); { lseek(tfile, b * 512, SEEK_SET); if ((*iofcn)(tfile, buf, 512) != 512) { puts(TMPERR); error; } } init() { char *p; int pid; close(tfile); tline = 0; iblock = -1; oblock = -1; strcpy(tfname,"/tmp/exxxxx"); ichanged = 0; pid = getpid(); for (p = &tfname[11]; p > &tfname[6];) { *--p = (pid&07) + '0'; pid >>= 3; } close(creat(tfname, 0600)); tfile = open(tfname, 2); brk(fendcore); dot = zero = dol = fendcore; endcore = fendcore - 2; } global(k) { char *gp; int c; int *a1; char globuf[GBSIZE]; if (globp) error; setall(); nonzero(); if ((c=getchar())=='\n') error; compile(c); gp = globuf; while ((c = getchar()) != '\n') { if (c==EOF) error; if (c=='\\') { c = getchar(); if (c!='\n') *gp++ = '\\'; } *gp++ = c; if (gp >= &globuf[GBSIZE-2]) error; } *gp++ = '\n'; *gp++ = 0; for (a1=zero; a1<=dol; a1++) { *a1 &= ~01; if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k) *a1 |= 01; } for (a1=zero; a1<=dol; a1++) { if (*a1 & 01) { *a1 &= ~01; dot = a1; globp = globuf; commands(); a1 = zero; } } } substitute(inglob) { int gsubf, *a1, nl; int getsub(); gsubf = compsub(); for (a1 = addr1; a1 <= addr2; a1++) { if (execute(0, a1)==0) continue; inglob |= 01; dosub(); if (gsubf) { while (*loc2) { if (execute(1)==0) break; dosub(); } } *a1 = putline(); nl = append(getsub, a1); a1 += nl; addr2 += nl; } if (inglob==0) error; } compsub() { int seof, c; char *p; int gsubf; if ((seof = getchar()) == '\n') error; compile(seof); p = rhsbuf; for (;;) { c = getchar(); if (c=='\\') c = getchar() | 0200; if (c=='\n') error; if (c==seof) break; *p++ = c; if (p >= &rhsbuf[LBSIZE/2]) error; } *p++ = 0; if ((peekc = getchar()) == 'g') { peekc = 0; newline(); return(1); } newline(); return(0); } getsub() { char *p1, *p2; p1 = linebuf; if ((p2 = linebp) == 0) return(EOF); while (*p1++ = *p2++); linebp = 0; return(0); } dosub() { 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<0 && (c &= 0177) >='1' && c < NBRA+'1') { sp = place(sp, braslist[c-'1'], braelist[c-'1']); continue; } *sp++ = c&0177; if (sp >= &genbuf[LBSIZE]) error; } lp = loc2; loc2 = sp + sizeof(linebuf) - sizeof(genbuf); while (*sp++ = *lp++) if (sp >= &genbuf[LBSIZE]) error; lp = linebuf; sp = genbuf; while (*lp++ = *sp++); } place(asp, al1, al2) { char *sp, *l1, *l2; sp = asp; l1 = al1; l2 = al2; while (l1 < l2) { *sp++ = *l1++; if (sp >= &genbuf[LBSIZE]) error; } return(sp); } move(cflag) { int *adt, *ad1, *ad2; int getcopy(); setdot(); nonzero(); if ((adt = address())==0) error; newline(); ad1 = addr1; ad2 = addr2; if (cflag) { ad1 = dol; append(getcopy, ad1++); ad2 = dol; } ad2++; if (adt= ad2) { dot = adt++; reverse(ad1, ad2); reverse(ad2, adt); reverse(ad1, adt); } else error; } reverse(aa1,aa2) { int *a1, *a2, t; a1 = aa1; a2 = aa2; for (;;) { t = *--a2; if (a2 <= a1) return; *a2 = *a1; *a1++ = t; } } getcopy() { if (addr1 > addr2) return(EOF); getline(*addr1++); return(0); } compile(aeof) { int eof, c; char *ep; char *lastep; char bracket[NBRA], *bracketp; int nbra; int cclcnt; ep = expbuf; eof = aeof; bracketp = bracket; nbra = 0; if ((c = getchar()) == eof) { if (*ep==0) error; return; } circfl = 0; if (c=='^') { c = getchar(); circfl++; } if (c=='*') goto cerror; peekc = c; for (;;) { if (ep >= &expbuf[ESIZE]) goto cerror; c = getchar(); if (c==eof) { *ep++ = CEOF; return; } if (c!='*') lastep = ep; switch (c) { case '\\': if ((c = getchar())=='(') { if (nbra >= NBRA) goto cerror; *bracketp++ = nbra; *ep++ = CBRA; *ep++ = nbra++; continue; } if (c == ')') { if (bracketp <= bracket) goto cerror; *ep++ = CKET; *ep++ = *--bracketp; continue; } *ep++ = CCHR; if (c=='\n') goto cerror; *ep++ = c; continue; case '.': *ep++ = CDOT; continue; case '\n': goto cerror; case '*': if (*lastep==CBRA || *lastep==CKET) error; *lastep |= STAR; continue; case '$': if ((peekc=getchar()) != eof) goto defchar; *ep++ = CDOL; continue; case '[': *ep++ = CCL; *ep++ = 0; cclcnt = 1; if ((c=getchar()) == '^') { c = getchar(); ep[-2] = NCCL; } do { if (c=='\n') goto cerror; *ep++ = c; cclcnt++; if (ep >= &expbuf[ESIZE]) goto cerror; } while ((c = getchar()) != ']'); lastep[1] = cclcnt; continue; defchar: default: *ep++ = CCHR; *ep++ = c; } } cerror: expbuf[0] = 0; error; } execute(gf, addr) int *addr; { char *p1, *p2, c; if (gf) { if (circfl) return(0); p1 = linebuf; p2 = genbuf; while (*p1++ = *p2++); locs = p1 = loc2; } else { if (addr==zero) return(0); p1 = getline(*addr); locs = 0; } p2 = expbuf; if (circfl) { loc1 = p1; 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); } /* regular algorithm */ do { if (advance(p1, p2)) { loc1 = p1; return(1); } } while (*p1++); return(0); } advance(alp, aep) { char *lp, *ep, *curlp; char *nextep; lp = alp; ep = aep; for (;;) switch (*ep++) { case CCHR: if (*ep++ == *lp++) continue; return(0); case CDOT: if (*lp++) continue; return(0); case CDOL: if (*lp==0) continue; return(0); case CEOF: loc2 = lp; return(1); case CCL: if (cclass(ep, *lp++, 1)) { ep += *ep; continue; } return(0); case NCCL: if (cclass(ep, *lp++, 0)) { ep += *ep; continue; } return(0); case CBRA: braslist[*ep++] = lp; continue; case CKET: braelist[*ep++] = lp; continue; case CDOT|STAR: curlp = lp; while (*lp++); goto star; case CCHR|STAR: curlp = lp; while (*lp++ == *ep); ep++; goto star; case CCL|STAR: case NCCL|STAR: curlp = lp; while (cclass(ep, *lp++, ep[-1]==(CCL|STAR))); ep += *ep; goto star; star: do { lp--; if (lp==locs) break; if (advance(lp, ep)) return(1); } while (lp > curlp); return(0); default: error; } } cclass(aset, ac, af) { char *set, c; int n; set = aset; if ((c = ac) == 0) return(0); n = *set++; while (--n) if (*set++ == c) return(af); return(!af); } putd() { int r; long x = count[0]; x <<= 16; x += count[1]; count[1] = x / 10; count[0] = 0; r = x % 10; if (count[1]) putd(); putc(r + '0'); } puts(as) { char *sp; sp = as; col = 0; while (*sp) putc(*sp++); putc('\n'); } char line[70]; char *linp = line; putc(ac) { char *lp; int c; lp = linp; c = ac; if (listf) { col++; if (col >= 72) { col = 0; *lp++ = '\\'; *lp++ = '\n'; } if (c=='\t') { c = '>'; goto esc; } if (c=='\b') { c = '<'; esc: *lp++ = '-'; *lp++ = '\b'; *lp++ = c; goto out; } if (c<' ' && c!= '\n') { *lp++ = '\\'; *lp++ = (c>>3)+'0'; *lp++ = (c&07)+'0'; col += 2; goto out; } } *lp++ = c; out: if(c == '\n' || lp >= &line[64]) { linp = line; write(1, line, lp-line); return; } linp = lp; } /* * Get process ID routine if system call is unavailable. getpid() { int f; int b[1]; f = open("/dev/kmem", 0); if(f < 0) return(-1); seek(f, 0140074, 0); read(f, b, 2); seek(f, b[0]+8, 0); read(f, b, 2); close(f); return(b[0]); } */