📄 ed.c
字号:
/* * Editor */#include <signal.h>#include <sgtty.h>#include <setjmp.h>#define NULL 0#define FNSIZE 64#define LBSIZE 512#define ESIZE 128#define GBSIZE 256#define NBRA 5#define EOF -1#define KSIZE 9#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 CBACK 14#define STAR 01char Q[] = "";char T[] = "TMP";#define READ 0#define WRITE 1int 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 *addr1;int *addr2;char genbuf[LBSIZE];long count;char *nextip;char *linebp;int ninbuf;int io;int pflag;long lseek();int (*oldhup)();int (*oldquit)();int vflag = 1;int xflag;int xtflag;int kflag;char key[KSIZE + 1];char crbuf[512];char perm[768];char tperm[768];int listf;int col;char *globp;int tfile = -1;int tline;char *tfname;char *loc1;char *loc2;char *locs;char ibuff[512];int iblock = -1;char obuff[512];int oblock = -1;int ichanged;int nleft;char WRERR[] = "WRITE ERROR";int names[26];int anymarks;char *braslist[NBRA];char *braelist[NBRA];int nbra;int subnewa;int subolda;int fchange;int wrapp;unsigned nlall = 128;int *address();char *getline();char *getblock();char *place();char *mktemp();char *malloc();char *realloc();jmp_buf savej;main(argc, argv)char **argv;{ register char *p1, *p2; extern int onintr(), quit(), onhup(); int (*oldintr)(); oldquit = signal(SIGQUIT, SIG_IGN); oldhup = signal(SIGHUP, SIG_IGN); oldintr = signal(SIGINT, SIG_IGN); if ((int)signal(SIGTERM, SIG_IGN) == 0) signal(SIGTERM, quit); argv++; while (argc > 1 && **argv=='-') { switch((*argv)[1]) { case '\0': vflag = 0; break; case 'q': signal(SIGQUIT, SIG_DFL); vflag = 1; break; case 'x': xflag = 1; break; } argv++; argc--; } if(xflag){ getkey(); kflag = crinit(key, perm); } if (argc>1) { p1 = *argv; p2 = savedfile; while (*p2++ = *p1++) ; globp = "r"; } zero = (int *)malloc(nlall*sizeof(int)); tfname = mktemp("/tmp/eXXXXX"); init(); if (((int)oldintr&01) == 0) signal(SIGINT, onintr); if (((int)oldhup&01) == 0) signal(SIGHUP, onhup); setjmp(savej); commands(); quit();}commands(){ int getfile(), gettty(); register *a1, c; for (;;) { if (pflag) { pflag = 0; addr1 = addr2 = dot; goto print; } addr1 = 0; addr2 = 0; do { addr1 = addr2; if ((a1 = address())==0) { c = getchr(); break; } addr2 = a1; if ((c=getchr()) == ';') { 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': fchange = 0; c = 'e'; case 'e': setnoaddr(); if (vflag && fchange) { fchange = 0; error(Q); } filename(c); init(); addr2 = zero; goto caseread; case 'f': setnoaddr(); filename(c); puts(savedfile); continue; case 'g': global(1); continue; case 'i': setdot(); nonzero(); newline(); append(gettty, addr2-1); continue; case 'j': if (addr2==0) { addr1 = dot; addr2 = dot+1; } setdot(); newline(); nonzero(); join(); continue; case 'k': if ((c = getchr()) < 'a' || c > 'z') error(Q); newline(); setdot(); nonzero(); names[c-'a'] = *addr2 & ~01; anymarks |= 01; continue; case 'm': move(0); continue; case '\n': if (addr2==0) addr2 = dot+1; addr1 = addr2; goto print; case 'l': listf++; case 'p': case 'P': newline(); print: setdot(); nonzero(); a1 = addr1; do { puts(getline(*a1++)); } while (a1 <= addr2); dot = addr2; listf = 0; continue; case 'Q': fchange = 0; case 'q': setnoaddr(); newline(); quit(); case 'r': filename(c); caseread: if ((io = open(file, 0)) < 0) { lastc = '\n'; error(file); } setall(); ninbuf = 0; c = zero != dol; append(getfile, addr2); exfile(); fchange = c; continue; case 's': setdot(); nonzero(); substitute(globp!=0); continue; case 't': move(1); continue; case 'u': setdot(); nonzero(); newline(); if ((*addr2&~01) != subnewa) error(Q); *addr2 = subolda; dot = addr2; continue; case 'v': global(0); continue; case 'W': wrapp++; case 'w': setall(); nonzero(); filename(c); if(!wrapp || ((io = open(file,1)) == -1) || ((lseek(io, 0L, 2)) == -1)) if ((io = creat(file, 0666)) < 0) error(file); wrapp = 0; putfile(); exfile(); if (addr1==zero+1 && addr2==dol) fchange = 0; continue; case 'x': setnoaddr(); newline(); xflag = 1; puts("Entering encrypting mode!"); getkey(); kflag = crinit(key, perm); continue; case '=': setall(); newline(); count = (addr2-zero)&077777; putd(); putchr('\n'); continue; case '!': callunix(); continue; case EOF: return; } error(Q); }}int *address(){ register *a1, minus, c; int n, relerr; minus = 0; a1 = 0; for (;;) { c = getchr(); if ('0'<=c && c<='9') { n = 0; do { n *= 10; n += c - '0'; } while ((c = getchr())>='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(Q); } break; case '$': a1 = dol; break; case '.': a1 = dot; break; case '\'': if ((c = getchr()) < 'a' || c > 'z') error(Q); 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 (a1<zero || a1>dol) error(Q); return(a1); } if (relerr) error(Q); }}setdot(){ if (addr2 == 0) addr1 = addr2 = dot; if (addr1 > addr2) error(Q);}setall(){ if (addr2==0) { addr1 = zero+1; addr2 = dol; if (dol==zero) addr1 = zero; } setdot();}setnoaddr(){ if (addr2) error(Q);}nonzero(){ if (addr1<=zero || addr2>dol) error(Q);}newline(){ register c; if ((c = getchr()) == '\n') return; if (c=='p' || c=='l') { pflag++; if (c=='l') listf++; if (getchr() == '\n') return; } error(Q);}filename(comm){ register char *p1, *p2; register c; count = 0; c = getchr(); if (c=='\n' || c==EOF) { p1 = savedfile; if (*p1==0 && comm!='f') error(Q); p2 = file; while (*p2++ = *p1++) ; return; } if (c!=' ') error(Q); while ((c = getchr()) == ' ') ; if (c=='\n') error(Q); p1 = file; do { *p1++ = c; if (c==' ' || c==EOF) error(Q); } while ((c = getchr()) != '\n'); *p1++ = 0; if (savedfile[0]==0 || comm=='e' || comm=='f') { p1 = savedfile; p2 = file; while (*p1++ = *p2++) ; }}exfile(){ close(io); io = -1; if (vflag) { putd(); putchr('\n'); }}onintr(){ signal(SIGINT, onintr); putchr('\n'); lastc = '\n'; error(Q);}onhup(){ signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); if (dol > zero) { addr1 = zero+1; addr2 = dol; io = creat("ed.hup", 0666); if (io > 0) putfile(); } fchange = 0; quit();}error(s)char *s;{ register c; wrapp = 0; listf = 0; putchr('?'); puts(s); count = 0; lseek(0, (long)0, 2); pflag = 0; if (globp) lastc = '\n'; globp = 0; peekc = lastc; if(lastc) while ((c = getchr()) != '\n' && c != EOF) ; if (io > 0) { close(io); io = -1; } longjmp(savej, 1);}getchr(){ char c; if (lastc=peekc) { peekc = 0; return(lastc); } if (globp) { if ((lastc = *globp++) != 0) return(lastc); globp = 0; return(EOF); } if (read(0, &c, 1) <= 0) return(lastc = EOF); lastc = c&0177; return(lastc);}gettty(){ register c; register char *gf; register char *p; p = linebuf; gf = globp; while ((c = getchr()) != '\n') { if (c==EOF) { if (gf) peekc = c; return(c); } if ((c &= 0177) == 0) continue; *p++ = c; if (p >= &linebuf[LBSIZE-2]) error(Q); } *p++ = 0; if (linebuf[0]=='.' && linebuf[1]==0) return(EOF); return(0);}getfile(){ register c; register char *lp, *fp; lp = linebuf; fp = nextip; do { if (--ninbuf < 0) { if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0) return(EOF); fp = genbuf; while(fp < &genbuf[ninbuf]) { if (*fp++ & 0200) { if (kflag) crblock(perm, genbuf, ninbuf+1, count); break; } } fp = genbuf; } c = *fp++; if (c=='\0') continue; if (c&0200 || lp >= &linebuf[LBSIZE]) { lastc = '\n'; error(Q); } *lp++ = c; count++; } while (c != '\n'); *--lp = 0; nextip = fp; return(0);}putfile(){ int *a1, n; register char *fp, *lp; register nib; nib = 512; fp = genbuf; a1 = addr1; do { lp = getline(*a1++); for (;;) { if (--nib < 0) { n = fp-genbuf; if(kflag) crblock(perm, genbuf, n, count-n); if(write(io, genbuf, n) != n) { puts(WRERR); error(Q); } nib = 511; fp = genbuf; } count++; if ((*fp++ = *lp++) == 0) { fp[-1] = '\n'; break; } } } while (a1 <= addr2); n = fp-genbuf; if(kflag) crblock(perm, genbuf, n, count-n); if(write(io, genbuf, n) != n) { puts(WRERR); error(Q); }}append(f, a)int *a;int (*f)();{ register *a1, *a2, *rdot; int nline, tl; nline = 0; dot = a; while ((*f)() == 0) { if ((dol-zero)+1 >= nlall) { int *ozero = zero; nlall += 512; free((char *)zero); if ((zero = (int *)realloc((char *)zero, nlall*sizeof(int)))==NULL) { lastc = '\n'; zero = ozero; error("MEM?"); } dot += zero - ozero; dol += zero - ozero; } tl = putline(); nline++; a1 = ++dol; a2 = a1+1; rdot = ++dot; while (a1 > rdot) *--a2 = *--a1; *rdot = tl; } return(nline);}callunix(){ register (*savint)(), pid, rpid; int retcode; setnoaddr(); if ((pid = fork()) == 0) { signal(SIGHUP, oldhup); signal(SIGQUIT, oldquit); execl("/bin/sh", "sh", "-t", 0); exit(0100); } savint = signal(SIGINT, SIG_IGN); while ((rpid = wait(&retcode)) != pid && rpid != -1) ; signal(SIGINT, savint); puts("!");}quit(){ if (vflag && fchange && dol!=zero) { fchange = 0; error(Q); } unlink(tfname); exit(0);}delete(){ setdot(); newline(); nonzero(); rdelete(addr1, addr2);}rdelete(ad1, ad2)int *ad1, *ad2;{ register *a1, *a2, *a3; a1 = ad1; a2 = ad2+1; a3 = dol; dol -= a2 - a1; do { *a1++ = *a2++; } while (a2 <= a3); a1 = ad1; if (a1 > dol) a1 = dol; dot = a1; fchange = 1;}gdelete(){ register *a1, *a2, *a3; a3 = dol; for (a1=zero+1; (*a1&01)==0; a1++) if (a1>=a3) return; for (a2=a1+1; a2<=a3;) { if (*a2&01) { a2++; dot = a1; } else *a1++ = *a2++; } dol = a1-1; if (dot>dol) dot = dol; fchange = 1;}char *getline(tl){ register char *bp, *lp; register 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(){ register char *bp, *lp; register nl; int tl; fchange = 1; 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -