?? sam.c
字號:
#include "sam.h"Rune genbuf[BLOCKSIZE];int io;int panicking;int rescuing;String genstr;String rhs;String curwd;String cmdstr;Rune empty[] = { 0 };char *genc;File *curfile;File *flist;File *cmd;jmp_buf mainloop;List tempfile = { 'p' };int quitok = TRUE;int downloaded;int dflag;int Rflag;char *machine;char *home;int bpipeok;int termlocked;char *samterm = SAMTERM;char *rsamname = RSAM;File *lastfile;Disk *disk;long seq;Rune baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'};void usage(void);void main(int argc, char *argv[]){ int i; String *t; char *termargs[10], **ap; ap = termargs; *ap++ = "samterm"; ARGBEGIN{ case 'd': dflag++; break; case 'r': machine = EARGF(usage()); break; case 'R': Rflag++; break; case 't': samterm = EARGF(usage()); break; case 's': rsamname = EARGF(usage()); break; default: dprint("sam: unknown flag %c\n", ARGC()); usage(); /* options for samterm */ case 'a': *ap++ = "-a"; break; }ARGEND *ap = nil; Strinit(&cmdstr); Strinit0(&lastpat); Strinit0(&lastregexp); Strinit0(&genstr); Strinit0(&rhs); Strinit0(&curwd); Strinit0(&plan9cmd); home = getenv(HOME); disk = diskinit(); if(home == 0) home = "/"; if(!dflag) startup(machine, Rflag, termargs, argv); notify(notifyf); getcurwd(); if(argc>0){ for(i=0; i<argc; i++){ if(!setjmp(mainloop)){ t = tmpcstr(argv[i]); Straddc(t, '\0'); Strduplstr(&genstr, t); freetmpstr(t); fixname(&genstr); logsetname(newfile(), &genstr); } } }else if(!downloaded) newfile(); seq++; if(file.nused) current(file.filepptr[0]); setjmp(mainloop); cmdloop(); trytoquit(); /* if we already q'ed, quitok will be TRUE */ exits(0);}voidusage(void){ dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n"); exits("usage");}voidrescue(void){ int i, nblank = 0; File *f; char *c; char buf[256]; if(rescuing++) return; io = -1; for(i=0; i<file.nused; i++){ f = file.filepptr[i]; if(f==cmd || f->nc==0 || !fileisdirty(f)) continue; if(io == -1){ sprint(buf, "%s/sam.save", home); io = create(buf, 1, 0777); if(io<0) return; } if(f->name.s[0]){ c = Strtoc(&f->name); strncpy(buf, c, sizeof buf-1); buf[sizeof buf-1] = 0; free(c); }else sprint(buf, "nameless.%d", nblank++); fprint(io, "#!%s '%s' $* <<'---%s'\n", SAMSAVECMD, buf, buf); addr.r.p1 = 0, addr.r.p2 = f->nc; writeio(f); fprint(io, "\n---%s\n", (char *)buf); }}voidpanic(char *s){ int wasd; if(!panicking++ && !setjmp(mainloop)){ wasd = downloaded; downloaded = 0; dprint("sam: panic: %s: %r\n", s); if(wasd) fprint(2, "sam: panic: %s: %r\n", s); rescue(); abort(); }}voidhiccough(char *s){ File *f; int i; if(rescuing) exits("rescue"); if(s) dprint("%s\n", s); resetcmd(); resetxec(); resetsys(); if(io > 0) close(io); /* * back out any logged changes & restore old sequences */ for(i=0; i<file.nused; i++){ f = file.filepptr[i]; if(f==cmd) continue; if(f->seq==seq){ bufdelete(&f->epsilon, 0, f->epsilon.nc); f->seq = f->prevseq; f->dot.r = f->prevdot; f->mark = f->prevmark; state(f, f->prevmod ? Dirty: Clean); } } update(); if (curfile) { if (curfile->unread) curfile->unread = FALSE; else if (downloaded) outTs(Hcurrent, curfile->tag); } longjmp(mainloop, 1);}voidintr(void){ error(Eintr);}voidtrytoclose(File *f){ char *t; char buf[256]; if(f == cmd) /* possible? */ return; if(f->deleted) return; if(fileisdirty(f) && !f->closeok){ f->closeok = TRUE; if(f->name.s[0]){ t = Strtoc(&f->name); strncpy(buf, t, sizeof buf-1); free(t); }else strcpy(buf, "nameless file"); error_s(Emodified, buf); } f->deleted = TRUE;}voidtrytoquit(void){ int c; File *f; if(!quitok){ for(c = 0; c<file.nused; c++){ f = file.filepptr[c]; if(f!=cmd && fileisdirty(f)){ quitok = TRUE; eof = FALSE; error(Echanges); } } }}voidload(File *f){ Address saveaddr; Strduplstr(&genstr, &f->name); filename(f); if(f->name.s[0]){ saveaddr = addr; edit(f, 'I'); addr = saveaddr; }else{ f->unread = 0; f->cleanseq = f->seq; } fileupdate(f, TRUE, TRUE);}voidcmdupdate(void){ if(cmd && cmd->seq!=0){ fileupdate(cmd, FALSE, downloaded); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc; telldot(cmd); }}voiddelete(File *f){ if(downloaded && f->rasp) outTs(Hclose, f->tag); delfile(f); if(f == curfile) current(0);}voidupdate(void){ int i, anymod; File *f; settempfile(); for(anymod = i=0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f==cmd) /* cmd gets done in main() */ continue; if(f->deleted) { delete(f); continue; } if(f->seq==seq && fileupdate(f, FALSE, downloaded)) anymod++; if(f->rasp) telldot(f); } if(anymod) seq++;}File *current(File *f){ return curfile = f;}voidedit(File *f, int cmd){ int empty = TRUE; Posn p; int nulls; if(cmd == 'r') logdelete(f, addr.r.p1, addr.r.p2); if(cmd=='e' || cmd=='I'){ logdelete(f, (Posn)0, f->nc); addr.r.p2 = f->nc; }else if(f->nc!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0)) empty = FALSE; if((io = open(genc, OREAD))<0) { if (curfile && curfile->unread) curfile->unread = FALSE; error_r(Eopen, genc); } p = readio(f, &nulls, empty, TRUE); closeio((cmd=='e' || cmd=='I')? -1 : p); if(cmd == 'r') f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p; else f->ndot.r.p1 = f->ndot.r.p2 = 0; f->closeok = empty; if (quitok) quitok = empty; else quitok = FALSE; state(f, empty && !nulls? Clean : Dirty); if(empty && !nulls) f->cleanseq = f->seq; if(cmd == 'e') filename(f);}intgetname(File *f, String *s, int save){ int c, i; Strzero(&genstr); if(genc){ free(genc); genc = 0; } if(s==0 || (c = s->s[0])==0){ /* no name provided */ if(f) Strduplstr(&genstr, &f->name); goto Return; } if(c!=' ' && c!='\t') error(Eblank); for(i=0; (c=s->s[i])==' ' || c=='\t'; i++) ; while(s->s[i] > ' ') Straddc(&genstr, s->s[i++]); if(s->s[i]) error(Enewline); fixname(&genstr); if(f && (save || f->name.s[0]==0)){ logsetname(f, &genstr); if(Strcmp(&f->name, &genstr)){ quitok = f->closeok = FALSE; f->qidpath = 0; f->mtime = 0; state(f, Dirty); /* if it's 'e', fix later */ } } Return: genc = Strtoc(&genstr); i = genstr.n; if(i && genstr.s[i-1]==0) i--; return i; /* strlen(name) */}voidfilename(File *f){ if(genc) free(genc); genc = Strtoc(&genstr); dprint("%c%c%c %s\n", " '"[f->mod], "-+"[f->rasp!=0], " ."[f==curfile], genc);}voidundostep(File *f, int isundo){ uint p1, p2; int mod; mod = f->mod; fileundo(f, isundo, 1, &p1, &p2, TRUE); f->ndot = f->dot; if(f->mod){ f->closeok = 0; quitok = 0; }else f->closeok = 1; if(f->mod != mod){ f->mod = mod; if(mod) mod = Clean; else mod = Dirty; state(f, mod); }}intundo(int isundo){ File *f; int i; Mod max; max = undoseq(curfile, isundo); if(max == 0) return 0; settempfile(); for(i = 0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f!=cmd && undoseq(f, isundo)==max) undostep(f, isundo); } return 1;}intreadcmd(String *s){ int retcode; if(flist != 0) fileclose(flist); flist = fileopen(); addr.r.p1 = 0, addr.r.p2 = flist->nc; retcode = plan9(flist, '<', s, FALSE); fileupdate(flist, FALSE, FALSE); flist->seq = 0; if (flist->nc > BLOCKSIZE) error(Etoolong); Strzero(&genstr); Strinsure(&genstr, flist->nc); bufread(flist, (Posn)0, genbuf, flist->nc); memmove(genstr.s, genbuf, flist->nc*RUNESIZE); genstr.n = flist->nc; Straddc(&genstr, '\0'); return retcode;}voidgetcurwd(void){ String *t; char buf[256]; buf[0] = 0; getwd(buf, sizeof(buf)); t = tmpcstr(buf); Strduplstr(&curwd, t); freetmpstr(t); if(curwd.n == 0) warn(Wpwd); else if(curwd.s[curwd.n-1] != '/') Straddc(&curwd, '/');}voidcd(String *str){ int i, fd; char *s; File *f; String owd; getcurwd(); if(getname((File *)0, str, FALSE)) s = genc; else s = home; if(chdir(s)) syserror("chdir"); fd = open("/dev/wdir", OWRITE); if(fd > 0) write(fd, s, strlen(s)); dprint("!\n"); Strinit(&owd); Strduplstr(&owd, &curwd); getcurwd(); settempfile(); for(i=0; i<tempfile.nused; i++){ f = tempfile.filepptr[i]; if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){ Strinsert(&f->name, &owd, (Posn)0); fixname(&f->name); sortname(f); }else if(f != cmd && Strispre(&curwd, &f->name)){ fixname(&f->name); sortname(f); } } Strclose(&owd);}intloadflist(String *s){ int c, i; c = s->s[0]; for(i = 0; s->s[i]==' ' || s->s[i]=='\t'; i++) ; if((c==' ' || c=='\t') && s->s[i]!='\n'){ if(s->s[i]=='<'){ Strdelete(s, 0L, (long)i+1); readcmd(s); }else{ Strzero(&genstr); while((c = s->s[i++]) && c!='\n') Straddc(&genstr, c); Straddc(&genstr, '\0'); } }else{ if(c != '\n') error(Eblank); Strdupl(&genstr, empty); } if(genc) free(genc); genc = Strtoc(&genstr); return genstr.s[0];}File *readflist(int readall, int delete){ Posn i; int c; File *f; String t; Strinit(&t); for(i=0,f=0; f==0 || readall || delete; i++){ /* ++ skips blank */ Strdelete(&genstr, (Posn)0, i); for(i=0; (c = genstr.s[i])==' ' || c=='\t' || c=='\n'; i++) ; if(i >= genstr.n) break; Strdelete(&genstr, (Posn)0, i); for(i=0; (c=genstr.s[i]) && c!=' ' && c!='\t' && c!='\n'; i++) ; if(i == 0) break; genstr.s[i] = 0; Strduplstr(&t, tmprstr(genstr.s, i+1)); fixname(&t); f = lookfile(&t); if(delete){ if(f == 0) warn_S(Wfile, &t); else trytoclose(f); }else if(f==0 && readall) logsetname(f = newfile(), &t); } Strclose(&t); return f;}File *tofile(String *s){ File *f; if(s->s[0] != ' ') error(Eblank); if(loadflist(s) == 0){ f = lookfile(&genstr); /* empty string ==> nameless file */ if(f == 0) error_s(Emenu, genc); }else if((f=readflist(FALSE, FALSE)) == 0) error_s(Emenu, genc); return current(f);}File *getfile(String *s){ File *f; if(loadflist(s) == 0) logsetname(f = newfile(), &genstr); else if((f=readflist(TRUE, FALSE)) == 0) error(Eblank); return current(f);}voidclosefiles(File *f, String *s){ if(s->s[0] == 0){ if(f == 0) error(Enofile); trytoclose(f); return; } if(s->s[0] != ' ') error(Eblank); if(loadflist(s) == 0) error(Enewline); readflist(FALSE, TRUE);}voidcopy(File *f, Address addr2){ Posn p; int ni; for(p=addr.r.p1; p<addr.r.p2; p+=ni){ ni = addr.r.p2-p; if(ni > BLOCKSIZE) ni = BLOCKSIZE; bufread(f, p, genbuf, ni); loginsert(addr2.f, addr2.r.p2, tmprstr(genbuf, ni)->s, ni); } addr2.f->ndot.r.p2 = addr2.r.p2+(f->dot.r.p2-f->dot.r.p1); addr2.f->ndot.r.p1 = addr2.r.p2;}voidmove(File *f, Address addr2){ if(addr.r.p2 <= addr2.r.p2){ logdelete(f, addr.r.p1, addr.r.p2); copy(f, addr2); }else if(addr.r.p1 >= addr2.r.p2){ copy(f, addr2); logdelete(f, addr.r.p1, addr.r.p2); }else error(Eoverlap);}Posnnlcount(File *f, Posn p0, Posn p1){ Posn nl = 0; while(p0 < p1) if(filereadc(f, p0++)=='\n') nl++; return nl;}voidprintposn(File *f, int charsonly){ Posn l1, l2; if(!charsonly){ l1 = 1+nlcount(f, (Posn)0, addr.r.p1); l2 = l1+nlcount(f, addr.r.p1, addr.r.p2); /* check if addr ends with '\n' */ if(addr.r.p2>0 && addr.r.p2>addr.r.p1 && filereadc(f, addr.r.p2-1)=='\n') --l2; dprint("%lud", l1); if(l2 != l1) dprint(",%lud", l2); dprint("; "); } dprint("#%lud", addr.r.p1); if(addr.r.p2 != addr.r.p1) dprint(",#%lud", addr.r.p2); dprint("\n");}voidsettempfile(void){ if(tempfile.nalloc < file.nused){ if(tempfile.filepptr) free(tempfile.filepptr); tempfile.filepptr = emalloc(sizeof(File*)*file.nused); tempfile.nalloc = file.nused; } memmove(tempfile.filepptr, file.filepptr, sizeof(File*)*file.nused); tempfile.nused = file.nused;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -