📄 ed.c
字号:
/* * Editor */#include <u.h>#include <libc.h>#include <bio.h>#include <regexp.h>enum{ FNSIZE = 128, /* file name */ LBSIZE = 4096, /* max line size */ BLKSIZE = 4096, /* block size in temp file */ NBLK = 8191, /* max size of temp file */ ESIZE = 256, /* max size of reg exp */ GBSIZE = 256, /* max size of global command */ MAXSUB = 9, /* max number of sub reg exp */ ESCFLG = 0xFFFF, /* escape Rune - user defined code */ EOF = -1,};void (*oldhup)(int);void (*oldquit)(int);int* addr1;int* addr2;int anymarks;Biobuf bcons;int col;long count;int* dol;int* dot;int fchange;char file[FNSIZE];Rune genbuf[LBSIZE];int given;Rune* globp;int iblock;int ichanged;int io;Biobuf iobuf;int lastc;char line[70];Rune* linebp;Rune linebuf[LBSIZE];int listf;int listn;Rune* loc1;Rune* loc2;int names[26];int nleft;int oblock;int oflag;Reprog *pattern;int peekc;int pflag;int rescuing;Rune rhsbuf[LBSIZE/2];char savedfile[FNSIZE];jmp_buf savej;int subnewa;int subolda;Resub subexp[MAXSUB];char* tfname;int tline;int waiting;int wrapp;int* zero;char Q[] = "";char T[] = "TMP";char WRERR[] = "WRITE ERROR";int bpagesize = 20;char hex[] = "0123456789abcdef";char* linp = line;ulong nlall = 128;int tfile = -1;int vflag = 1;void add(int);int* address(void);int append(int(*)(void), int*);void browse(void);void callunix(void);void commands(void);void compile(int);int compsub(void);void dosub(void);void error(char*);int match(int*);void exfile(int);void filename(int);Rune* getblock(int, int);int getchr(void);int getcopy(void);int getfile(void);Rune* getline(int);int getnum(void);int getsub(void);int gettty(void);void global(int);void init(void);void join(void);void move(int);void newline(void);void nonzero(void);void notifyf(void*, char*);Rune* place(Rune*, Rune*, Rune*);void printcom(void);void putchr(int);void putd(void);void putfile(void);int putline(void);void putshst(Rune*);void putst(char*);void quit(void);void rdelete(int*, int*);void regerror(char *);void reverse(int*, int*);void setnoaddr(void);void setwide(void);void squeeze(int);void substitute(int);voidmain(int argc, char *argv[]){ char *p1, *p2; Binit(&bcons, 0, OREAD); notify(notifyf); ARGBEGIN { case 'o': oflag = 1; vflag = 0; break; } ARGEND USED(argc); if(*argv && (strcmp(*argv, "-") == 0)) { argv++; vflag = 0; } if(oflag) { p1 = "/fd/1"; p2 = savedfile; while(*p2++ = *p1++) ; globp = L"a"; } else if(*argv) { p1 = *argv; p2 = savedfile; while(*p2++ = *p1++) if(p2 >= &savedfile[sizeof(savedfile)]) p2--; globp = L"r"; } zero = malloc((nlall+5)*sizeof(int*)); tfname = mktemp("/tmp/eXXXXX"); init(); setjmp(savej); commands(); quit();}voidcommands(void){ int *a1, c, temp; char lastsep; Dir *d; for(;;) { if(pflag) { pflag = 0; addr1 = addr2 = dot; printcom(); } c = '\n'; for(addr1 = 0;;) { lastsep = c; a1 = address(); c = getchr(); if(c != ',' && c != ';') break; if(lastsep == ',') error(Q); if(a1 == 0) { a1 = zero+1; if(a1 > dol) a1--; } addr1 = a1; if(c == ';') dot = a1; } if(lastsep != '\n' && a1 == 0) a1 = dol; if((addr2=a1) == 0) { given = 0; addr2 = dot; } else given = 1; if(addr1 == 0) addr1 = addr2; switch(c) { case 'a': add(0); continue; case 'b': nonzero(); browse(); continue; case 'c': nonzero(); newline(); rdelete(addr1, addr2); append(gettty, addr1-1); continue; case 'd': nonzero(); newline(); rdelete(addr1, addr2); 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); putst(savedfile); continue; case 'g': global(1); continue; case 'i': add(-1); continue; case 'j': if(!given) addr2++; newline(); join(); continue; case 'k': nonzero(); c = getchr(); if(c < 'a' || c > 'z') error(Q); newline(); names[c-'a'] = *addr2 & ~01; anymarks |= 01; continue; case 'm': move(0); continue; case 'n': listn++; newline(); printcom(); continue; case '\n': if(a1==0) { a1 = dot+1; addr2 = a1; addr1 = a1; } if(lastsep==';') addr1 = a1; printcom(); continue; case 'l': listf++; case 'p': case 'P': newline(); printcom(); continue; case 'Q': fchange = 0; case 'q': setnoaddr(); newline(); quit(); case 'r': filename(c); caseread: if((io=open(file, OREAD)) < 0) { lastc = '\n'; error(file); } if((d = dirfstat(io)) != nil){ if(d->mode & DMAPPEND) print("warning: %s is append only\n", file); free(d); } Binit(&iobuf, io, OREAD); setwide(); squeeze(0); c = zero != dol; append(getfile, addr2); exfile(OREAD); fchange = c; continue; case 's': nonzero(); substitute(globp != 0); continue; case 't': move(1); continue; case 'u': nonzero(); newline(); if((*addr2&~01) != subnewa) error(Q); *addr2 = subolda; dot = addr2; continue; case 'v': global(0); continue; case 'W': wrapp++; case 'w': setwide(); squeeze(dol>zero); temp = getchr(); if(temp != 'q' && temp != 'Q') { peekc = temp; temp = 0; } filename(c); if(!wrapp || ((io = open(file, OWRITE)) == -1) || ((seek(io, 0L, 2)) == -1)) if((io = create(file, OWRITE, 0666)) < 0) error(file); Binit(&iobuf, io, OWRITE); wrapp = 0; if(dol > zero) putfile(); exfile(OWRITE); if(addr1<=zero+1 && addr2==dol) fchange = 0; if(temp == 'Q') fchange = 0; if(temp) quit(); continue; case '=': setwide(); squeeze(0); newline(); count = addr2 - zero; putd(); putchr(L'\n'); continue; case '!': callunix(); continue; case EOF: return; } error(Q); }}voidprintcom(void){ int *a1; nonzero(); a1 = addr1; do { if(listn) { count = a1-zero; putd(); putchr(L'\t'); } putshst(getline(*a1++)); } while(a1 <= addr2); dot = addr2; listf = 0; listn = 0; pflag = 0;}int*address(void){ int sign, *a, opcnt, nextopand, *b, c; nextopand = -1; sign = 1; opcnt = 0; a = dot; do { do { c = getchr(); } while(c == ' ' || c == '\t'); if(c >= '0' && c <= '9') { peekc = c; if(!opcnt) a = zero; a += sign*getnum(); } else switch(c) { case '$': a = dol; case '.': if(opcnt) error(Q); break; case '\'': c = getchr(); if(opcnt || c < 'a' || c > 'z') error(Q); a = zero; do { a++; } while(a <= dol && names[c-'a'] != (*a & ~01)); break; case '?': sign = -sign; case '/': compile(c); b = a; for(;;) { a += sign; if(a <= zero) a = dol; if(a > dol) a = zero; if(match(a)) break; if(a == b) error(Q); } break; default: if(nextopand == opcnt) { a += sign; if(a < zero || dol < a) continue; /* error(Q); */ } if(c != '+' && c != '-' && c != '^') { peekc = c; if(opcnt == 0) a = 0; return a; } sign = 1; if(c != '+') sign = -sign; nextopand = ++opcnt; continue; } sign = 1; opcnt++; } while(zero <= a && a <= dol); error(Q); return 0;}intgetnum(void){ int r, c; r = 0; for(;;) { c = getchr(); if(c < '0' || c > '9') break; r = r*10 + (c-'0'); } peekc = c; return r;}voidsetwide(void){ if(!given) { addr1 = zero + (dol>zero); addr2 = dol; }}voidsetnoaddr(void){ if(given) error(Q);}voidnonzero(void){ squeeze(1);}voidsqueeze(int i){ if(addr1 < zero+i || addr2 > dol || addr1 > addr2) error(Q);}voidnewline(void){ int c; c = getchr(); if(c == '\n' || c == EOF) return; if(c == 'p' || c == 'l' || c == 'n') { pflag++; if(c == 'l') listf++; else if(c == 'n') listn++; c = getchr(); if(c == '\n') return; } error(Q);}voidfilename(int comm){ char *p1, *p2; Rune rune; int 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 { if(p1 >= &file[sizeof(file)-6] || c == ' ' || c == EOF) error(Q); rune = c; p1 += runetochar(p1, &rune); } while((c=getchr()) != '\n'); *p1 = 0; if(savedfile[0] == 0 || comm == 'e' || comm == 'f') { p1 = savedfile; p2 = file; while(*p1++ = *p2++) ; }}voidexfile(int om){ if(om == OWRITE) if(Bflush(&iobuf) < 0) error(Q); close(io); io = -1; if(vflag) { putd(); putchr(L'\n'); }}voiderror1(char *s){ int c; wrapp = 0; listf = 0; listn = 0; count = 0; seek(0, 0, 2); pflag = 0; if(globp) lastc = '\n'; globp = 0; peekc = lastc; if(lastc) for(;;) { c = getchr(); if(c == '\n' || c == EOF) break; } if(io > 0) { close(io); io = -1; } putchr(L'?'); putst(s);}voiderror(char *s){ error1(s); longjmp(savej, 1);}voidrescue(void){ rescuing = 1; if(dol > zero) { addr1 = zero+1; addr2 = dol; io = create("ed.hup", OWRITE, 0666); if(io > 0){ Binit(&iobuf, io, OWRITE); putfile(); } } fchange = 0; quit();}voidnotifyf(void *a, char *s){ if(strcmp(s, "interrupt") == 0){ if(rescuing || waiting) noted(NCONT); putchr(L'\n'); lastc = '\n'; error1(Q); notejmp(a, savej, 0); } if(strcmp(s, "hangup") == 0){ if(rescuing) noted(NDFLT); rescue(); } fprint(2, "ed: note: %s\n", s); abort();}intgetchr(void){ if(lastc = peekc) { peekc = 0; return lastc; } if(globp) { if((lastc=*globp++) != 0) return lastc; globp = 0; return EOF; } lastc = Bgetrune(&bcons); return lastc;}intgety(void){ int c; Rune *gf, *p; p = linebuf; gf = globp; for(;;) { c = getchr(); if(c == '\n') { *p = 0; return 0; } if(c == EOF) { if(gf) peekc = c; return c; } if(c == 0) continue; *p++ = c; if(p >= &linebuf[LBSIZE-2]) error(Q); }}intgettty(void){ int rc; rc = gety(); if(rc) return rc; if(linebuf[0] == '.' && linebuf[1] == 0) return EOF; return 0;}intgetfile(void){ int c; Rune *lp; lp = linebuf; do { c = Bgetrune(&iobuf); if(c < 0) { if(lp > linebuf) { putst("'\\n' appended"); c = '\n'; } else return EOF; } if(lp >= &linebuf[LBSIZE]) { lastc = '\n'; error(Q); } *lp++ = c; count++; } while(c != '\n'); lp[-1] = 0; return 0;}voidputfile(void){ int *a1; Rune *lp; long c; a1 = addr1; do { lp = getline(*a1++); for(;;) { count++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -