#include "sam.h" Header h;uchar indata[DATASIZE];uchar outdata[2*DATASIZE+3]; /* room for overflow message */uchar *inp;uchar *outp;uchar *outmsg = outdata;Posn cmdpt;Posn cmdptadv;Buffer snarfbuf;int waitack;int outbuffered;int tversion; int inshort(void);long inlong(void);vlong invlong(void);int inmesg(Tmesg); void outshort(int);void outlong(long);void outvlong(vlong);void outcopy(int, void*);void outsend(void);void outstart(Hmesg); void setgenstr(File*, Posn, Posn); #ifdef DEBUGchar *hname[] = { [Hversion] "Hversion", [Hbindname] "Hbindname", [Hcurrent] "Hcurrent", [Hnewname] "Hnewname", [Hmovname] "Hmovname", [Hgrow] "Hgrow", [Hcheck0] "Hcheck0", [Hcheck] "Hcheck", [Hunlock] "Hunlock", [Hdata] "Hdata", [Horigin] "Horigin", [Hunlockfile] "Hunlockfile", [Hsetdot] "Hsetdot", [Hgrowdata] "Hgrowdata", [Hmoveto] "Hmoveto", [Hclean] "Hclean", [Hdirty] "Hdirty", [Hcut] "Hcut", [Hsetpat] "Hsetpat", [Hdelname] "Hdelname", [Hclose] "Hclose", [Hsetsnarf] "Hsetsnarf", [Hsnarflen] "Hsnarflen", [Hack] "Hack", [Hexit] "Hexit", [Hplumb] "Hplumb",}; char *tname[] = { [Tversion] "Tversion", [Tstartcmdfile] "Tstartcmdfile", [Tcheck] "Tcheck", [Trequest] "Trequest", [Torigin] "Torigin", [Tstartfile] "Tstartfile", [Tworkfile] "Tworkfile", [Ttype] "Ttype", [Tcut] "Tcut", [Tpaste] "Tpaste", [Tsnarf] "Tsnarf", [Tstartnewfile] "Tstartnewfile", [Twrite] "Twrite", [Tclose] "Tclose", [Tlook] "Tlook", [Tsearch] "Tsearch", [Tsend] "Tsend", [Tdclick] "Tdclick", [Tstartsnarf] "Tstartsnarf", [Tsetsnarf] "Tsetsnarf", [Tack] "Tack", [Texit] "Texit", [Tplumb] "Tplumb",}; voidjournal(int out, char *s){ static int fd = -1; if(fd < 0) fd = create("/tmp/sam.out", 1, 0666L); fprint(fd, "%s%s\n", out? "out: " : "in: ", s);} voidjournaln(int out, long n){ char buf[32]; snprint(buf, sizeof(buf), "%ld", n); journal(out, buf);} voidjournalv(int out, vlong v){ char buf[32]; sprint(buf, sizeof(buf), "%lld", v); journal(out, buf);}#else#define journal(a, b)#define journaln(a, b)#define journalv(a, b)#endif intrcvchar(void){ static uchar buf[64]; static i, nleft = 0; if(nleft <= 0){ nleft = read(0, (char *)buf, sizeof buf); if(nleft <= 0) return -1; i = 0; } --nleft; return buf[i++];} intrcv(void){ int c; static state = 0; static count = 0; static i = 0; while((c=rcvchar()) != -1) switch(state){ case 0: h.type = c; state++; break; case 1: h.count0 = c; state++; break; case 2: h.count1 = c; count = h.count0|(h.count1<<8); i = 0; if(count > DATASIZE) panic("count>DATASIZE"); if(count == 0) goto zerocount; state++; break; case 3: indata[i++] = c; if(i == count){ zerocount: indata[i] = 0; state = count = 0; return inmesg(h.type); } break; } return 0;} File *whichfile(int tag){ int i; for(i = 0; i<file.nused; i++) if(file.filepptr[i]->tag==tag) return file.filepptr[i]; hiccough((char *)0); return 0;} intinmesg(Tmesg type){ Rune buf[1025]; char cbuf[64]; int i, m; short s; long l, l1; vlong v; File *f; Posn p0, p1, p; Range r; String *str; char *c, *wdir; Rune *rp; Plumbmsg *pm; if(type > TMAX) panic("inmesg"); journal(0, tname[type]); inp = indata; switch(type){ case -1: panic("rcv error"); default: fprint(2, "unknown type %d\n", type); panic("rcv unknown"); case Tversion: tversion = inshort(); journaln(0, tversion); break; case Tstartcmdfile: v = invlong(); /* for 64-bit pointers */ journalv(0, v); Strdupl(&genstr, samname); cmd = newfile(); cmd->unread = 0; outTsv(Hbindname, cmd->tag, v); outTs(Hcurrent, cmd->tag); logsetname(cmd, &genstr); cmd->rasp = listalloc('P'); cmd->mod = 0; if(cmdstr.n){ loginsert(cmd, 0L, cmdstr.s, cmdstr.n); Strdelete(&cmdstr, 0L, (Posn)cmdstr.n); } fileupdate(cmd, FALSE, TRUE); outT0(Hunlock); break; case Tcheck: /* go through whichfile to check the tag */ outTs(Hcheck, whichfile(inshort())->tag); break; case Trequest: f = whichfile(inshort()); p0 = inlong(); p1 = p0+inshort(); journaln(0, p0); journaln(0, p1-p0); if(f->unread) panic("Trequest: unread"); if(p1>f->nc) p1 = f->nc; if(p0>f->nc) /* can happen e.g. scrolling during command */ p0 = f->nc; if(p0 == p1){ i = 0; r.p1 = r.p2 = p0; }else{ r = rdata(f->rasp, p0, p1-p0); i = r.p2-r.p1; bufread(f, r.p1, buf, i); } buf[i]=0; outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1)); break; case Torigin: s = inshort(); l = inlong(); l1 = inlong(); journaln(0, l1); lookorigin(whichfile(s), l, l1); break; case Tstartfile: termlocked++; f = whichfile(inshort()); if(!f->rasp) /* this might be a duplicate message */ f->rasp = listalloc('P'); current(f); outTsv(Hbindname, f->tag, invlong()); /* for 64-bit pointers */ outTs(Hcurrent, f->tag); journaln(0, f->tag); if(f->unread) load(f); else{ if(f->nc>0){ rgrow(f->rasp, 0L, f->nc); outTsll(Hgrow, f->tag, 0L, f->nc); } outTs(Hcheck0, f->tag); moveto(f, f->dot.r); } break; case Tworkfile: i = inshort(); f = whichfile(i); current(f); f->dot.r.p1 = inlong(); f->dot.r.p2 = inlong(); f->tdot = f->dot.r; journaln(0, i); journaln(0, f->dot.r.p1); journaln(0, f->dot.r.p2); break; case Ttype: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); journal(0, (char*)inp); str = tmpcstr((char*)inp); i = str->n; loginsert(f, p0, str->s, str->n); if(fileupdate(f, FALSE, FALSE)) seq++; if(f==cmd && p0==f->nc-i && i>0 && str->s[i-1]=='\n'){ freetmpstr(str); termlocked++; termcommand(); }else freetmpstr(str); f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this already */ f->tdot = f->dot.r; break; case Tcut: f = whichfile(inshort()); p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); logdelete(f, p0, p1); if(fileupdate(f, FALSE, FALSE)) seq++; f->dot.r.p1 = f->dot.r.p2 = p0; f->tdot = f->dot.r; /* terminal knows the value of dot already */ break; case Tpaste: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); for(l=0; l<snarfbuf.nc; l+=m){ m = snarfbuf.nc-l; if(m>BLOCKSIZE) m = BLOCKSIZE; bufread(&snarfbuf, l, genbuf, m); loginsert(f, p0, tmprstr(genbuf, m)->s, m); } if(fileupdate(f, FALSE, TRUE)) seq++; f->dot.r.p1 = p0; f->dot.r.p2 = p0+snarfbuf.nc; f->tdot.p1 = -1; /* force telldot to tell (arguably a BUG) */ telldot(f); outTs(Hunlockfile, f->tag); break; case Tsnarf: i = inshort(); p0 = inlong(); p1 = inlong(); snarf(whichfile(i), p0, p1, &snarfbuf, 0); break; case Tstartnewfile: v = invlong(); Strdupl(&genstr, empty); f = newfile(); f->rasp = listalloc('P'); outTsv(Hbindname, f->tag, v); logsetname(f, &genstr); outTs(Hcurrent, f->tag); current(f); load(f); break; case Twrite: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); addr.r.p1 = 0; addr.r.p2 = f->nc; if(f->name.s[0] == 0) error(Enoname); Strduplstr(&genstr, &f->name); writef(f); break; case Tclose: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); current(f); trytoclose(f); /* if trytoclose fails, will error out */ delete(f); break; case Tlook: f = whichfile(inshort()); termlocked++; p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); setgenstr(f, p0, p1); for(l = 0; l<genstr.n; l++){ i = genstr.s[l]; if(utfrune(".*+?(|)\\[]^$", i)){ str = tmpcstr("\\"); Strinsert(&genstr, str, l++); freetmpstr(str); } } Straddc(&genstr, '\0'); nextmatch(f, &genstr, p1, 1); moveto(f, sel.p[0]); break; case Tsearch: termlocked++; if(curfile == 0) error(Enofile); if(lastpat.s[0] == 0) panic("Tsearch"); nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1); moveto(curfile, sel.p[0]); break; case Tsend: termlocked++; inshort(); /* ignored */ p0 = inlong(); p1 = inlong(); setgenstr(cmd, p0, p1); bufreset(&snarfbuf); bufinsert(&snarfbuf, (Posn)0, genstr.s, genstr.n); outTl(Hsnarflen, genstr.n); if(genstr.s[genstr.n-1] != '\n') Straddc(&genstr, '\n'); loginsert(cmd, cmd->nc, genstr.s, genstr.n); fileupdate(cmd, FALSE, TRUE); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc; telldot(cmd); termcommand(); break; case Tdclick: f = whichfile(inshort()); p1 = inlong(); doubleclick(f, p1); f->tdot.p1 = f->tdot.p2 = p1; telldot(f); outTs(Hunlockfile, f->tag); break; case Tstartsnarf: if (snarfbuf.nc <= 0) { /* nothing to export */ outTs(Hsetsnarf, 0); break; } c = 0; i = 0; m = snarfbuf.nc; if(m > SNARFSIZE) { m = SNARFSIZE; dprint("?warning: snarf buffer truncated\n"); } rp = malloc(m*sizeof(Rune)); if(rp){ bufread(&snarfbuf, 0, rp, m); c = Strtoc(tmprstr(rp, m)); free(rp); i = strlen(c); } outTs(Hsetsnarf, i); if(c){ Write(1, c, i); free(c); } else dprint("snarf buffer too long\n"); break; case Tsetsnarf: m = inshort(); if(m > SNARFSIZE) error(Etoolong); c = malloc(m+1); if(c){Lines 1–500 of 849. Load more
#include "sam.h" Header h; uchar indata[DATASIZE]; uchar outdata[2*DATASIZE+3]; /* room for overflow message */ uchar *inp; uchar *outp; uchar *outmsg = outdata; Posn cmdpt; Posn cmdptadv; Buffer snarfbuf; int waitack; int outbuffered; int tversion; int inshort(void); long inlong(void); vlong invlong(void); int inmesg(Tmesg); void outshort(int); void outlong(long); void outvlong(vlong); void outcopy(int, void*); void outsend(void); void outstart(Hmesg); void setgenstr(File*, Posn, Posn); #ifdef DEBUG char *hname[] = { [Hversion] "Hversion", [Hbindname] "Hbindname", [Hcurrent] "Hcurrent", [Hnewname] "Hnewname", [Hmovname] "Hmovname", [Hgrow] "Hgrow", [Hcheck0] "Hcheck0", [Hcheck] "Hcheck", [Hunlock] "Hunlock", [Hdata] "Hdata", [Horigin] "Horigin", [Hunlockfile] "Hunlockfile", [Hsetdot] "Hsetdot", [Hgrowdata] "Hgrowdata", [Hmoveto] "Hmoveto", [Hclean] "Hclean", [Hdirty] "Hdirty", [Hcut] "Hcut", [Hsetpat] "Hsetpat", [Hdelname] "Hdelname", [Hclose] "Hclose", [Hsetsnarf] "Hsetsnarf", [Hsnarflen] "Hsnarflen", [Hack] "Hack", [Hexit] "Hexit", [Hplumb] "Hplumb", }; char *tname[] = { [Tversion] "Tversion", [Tstartcmdfile] "Tstartcmdfile", [Tcheck] "Tcheck", [Trequest] "Trequest", [Torigin] "Torigin", [Tstartfile] "Tstartfile", [Tworkfile] "Tworkfile", [Ttype] "Ttype", [Tcut] "Tcut", [Tpaste] "Tpaste", [Tsnarf] "Tsnarf", [Tstartnewfile] "Tstartnewfile", [Twrite] "Twrite", [Tclose] "Tclose", [Tlook] "Tlook", [Tsearch] "Tsearch", [Tsend] "Tsend", [Tdclick] "Tdclick", [Tstartsnarf] "Tstartsnarf", [Tsetsnarf] "Tsetsnarf", [Tack] "Tack", [Texit] "Texit", [Tplumb] "Tplumb", }; void journal(int out, char *s) { static int fd = -1; if(fd < 0) fd = create("/tmp/sam.out", 1, 0666L); fprint(fd, "%s%s\n", out? "out: " : "in: ", s); } void journaln(int out, long n) { char buf[32]; snprint(buf, sizeof(buf), "%ld", n); journal(out, buf); } void journalv(int out, vlong v) { char buf[32]; sprint(buf, sizeof(buf), "%lld", v); journal(out, buf); } #else #define journal(a, b) #define journaln(a, b) #define journalv(a, b) #endif int rcvchar(void){ static uchar buf[64]; static i, nleft = 0; if(nleft <= 0){ nleft = read(0, (char *)buf, sizeof buf); if(nleft <= 0) return -1; i = 0; } --nleft; return buf[i++]; } int rcv(void){ int c; static state = 0; static count = 0; static i = 0; while((c=rcvchar()) != -1) switch(state){ case 0: h.type = c; state++; break; case 1: h.count0 = c; state++; break; case 2: h.count1 = c; count = h.count0|(h.count1<<8); i = 0; if(count > DATASIZE) panic("count>DATASIZE"); if(count == 0) goto zerocount; state++; break; case 3: indata[i++] = c; if(i == count){ zerocount: indata[i] = 0; state = count = 0; return inmesg(h.type); } break; } return 0; } File * whichfile(int tag) { int i; for(i = 0; i<file.nused; i++) if(file.filepptr[i]->tag==tag) return file.filepptr[i]; hiccough((char *)0); return 0; } int inmesg(Tmesg type) { Rune buf[1025]; char cbuf[64]; int i, m; short s; long l, l1; vlong v; File *f; Posn p0, p1, p; Range r; String *str; char *c, *wdir; Rune *rp; Plumbmsg *pm; if(type > TMAX) panic("inmesg"); journal(0, tname[type]); inp = indata; switch(type){ case -1: panic("rcv error"); default: fprint(2, "unknown type %d\n", type); panic("rcv unknown"); case Tversion: tversion = inshort(); journaln(0, tversion); break; case Tstartcmdfile: v = invlong(); /* for 64-bit pointers */ journalv(0, v); Strdupl(&genstr, samname); cmd = newfile(); cmd->unread = 0; outTsv(Hbindname, cmd->tag, v); outTs(Hcurrent, cmd->tag); logsetname(cmd, &genstr); cmd->rasp = listalloc('P'); cmd->mod = 0; if(cmdstr.n){ loginsert(cmd, 0L, cmdstr.s, cmdstr.n); Strdelete(&cmdstr, 0L, (Posn)cmdstr.n); } fileupdate(cmd, FALSE, TRUE); outT0(Hunlock); break; case Tcheck: /* go through whichfile to check the tag */ outTs(Hcheck, whichfile(inshort())->tag); break; case Trequest: f = whichfile(inshort()); p0 = inlong(); p1 = p0+inshort(); journaln(0, p0); journaln(0, p1-p0); if(f->unread) panic("Trequest: unread"); if(p1>f->nc) p1 = f->nc; if(p0>f->nc) /* can happen e.g. scrolling during command */ p0 = f->nc; if(p0 == p1){ i = 0; r.p1 = r.p2 = p0; }else{ r = rdata(f->rasp, p0, p1-p0); i = r.p2-r.p1; bufread(f, r.p1, buf, i); } buf[i]=0; outTslS(Hdata, f->tag, r.p1, tmprstr(buf, i+1)); break; case Torigin: s = inshort(); l = inlong(); l1 = inlong(); journaln(0, l1); lookorigin(whichfile(s), l, l1); break; case Tstartfile: termlocked++; f = whichfile(inshort()); if(!f->rasp) /* this might be a duplicate message */ f->rasp = listalloc('P'); current(f); outTsv(Hbindname, f->tag, invlong()); /* for 64-bit pointers */ outTs(Hcurrent, f->tag); journaln(0, f->tag); if(f->unread) load(f); else{ if(f->nc>0){ rgrow(f->rasp, 0L, f->nc); outTsll(Hgrow, f->tag, 0L, f->nc); } outTs(Hcheck0, f->tag); moveto(f, f->dot.r); } break; case Tworkfile: i = inshort(); f = whichfile(i); current(f); f->dot.r.p1 = inlong(); f->dot.r.p2 = inlong(); f->tdot = f->dot.r; journaln(0, i); journaln(0, f->dot.r.p1); journaln(0, f->dot.r.p2); break; case Ttype: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); journal(0, (char*)inp); str = tmpcstr((char*)inp); i = str->n; loginsert(f, p0, str->s, str->n); if(fileupdate(f, FALSE, FALSE)) seq++; if(f==cmd && p0==f->nc-i && i>0 && str->s[i-1]=='\n'){ freetmpstr(str); termlocked++; termcommand(); }else freetmpstr(str); f->dot.r.p1 = f->dot.r.p2 = p0+i; /* terminal knows this already */ f->tdot = f->dot.r; break; case Tcut: f = whichfile(inshort()); p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); logdelete(f, p0, p1); if(fileupdate(f, FALSE, FALSE)) seq++; f->dot.r.p1 = f->dot.r.p2 = p0; f->tdot = f->dot.r; /* terminal knows the value of dot already */ break; case Tpaste: f = whichfile(inshort()); p0 = inlong(); journaln(0, p0); for(l=0; l<snarfbuf.nc; l+=m){ m = snarfbuf.nc-l; if(m>BLOCKSIZE) m = BLOCKSIZE; bufread(&snarfbuf, l, genbuf, m); loginsert(f, p0, tmprstr(genbuf, m)->s, m); } if(fileupdate(f, FALSE, TRUE)) seq++; f->dot.r.p1 = p0; f->dot.r.p2 = p0+snarfbuf.nc; f->tdot.p1 = -1; /* force telldot to tell (arguably a BUG) */ telldot(f); outTs(Hunlockfile, f->tag); break; case Tsnarf: i = inshort(); p0 = inlong(); p1 = inlong(); snarf(whichfile(i), p0, p1, &snarfbuf, 0); break; case Tstartnewfile: v = invlong(); Strdupl(&genstr, empty); f = newfile(); f->rasp = listalloc('P'); outTsv(Hbindname, f->tag, v); logsetname(f, &genstr); outTs(Hcurrent, f->tag); current(f); load(f); break; case Twrite: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); addr.r.p1 = 0; addr.r.p2 = f->nc; if(f->name.s[0] == 0) error(Enoname); Strduplstr(&genstr, &f->name); writef(f); break; case Tclose: termlocked++; i = inshort(); journaln(0, i); f = whichfile(i); current(f); trytoclose(f); /* if trytoclose fails, will error out */ delete(f); break; case Tlook: f = whichfile(inshort()); termlocked++; p0 = inlong(); p1 = inlong(); journaln(0, p0); journaln(0, p1); setgenstr(f, p0, p1); for(l = 0; l<genstr.n; l++){ i = genstr.s[l]; if(utfrune(".*+?(|)\\[]^$", i)){ str = tmpcstr("\\"); Strinsert(&genstr, str, l++); freetmpstr(str); } } Straddc(&genstr, '\0'); nextmatch(f, &genstr, p1, 1); moveto(f, sel.p[0]); break; case Tsearch: termlocked++; if(curfile == 0) error(Enofile); if(lastpat.s[0] == 0) panic("Tsearch"); nextmatch(curfile, &lastpat, curfile->dot.r.p2, 1); moveto(curfile, sel.p[0]); break; case Tsend: termlocked++; inshort(); /* ignored */ p0 = inlong(); p1 = inlong(); setgenstr(cmd, p0, p1); bufreset(&snarfbuf); bufinsert(&snarfbuf, (Posn)0, genstr.s, genstr.n); outTl(Hsnarflen, genstr.n); if(genstr.s[genstr.n-1] != '\n') Straddc(&genstr, '\n'); loginsert(cmd, cmd->nc, genstr.s, genstr.n); fileupdate(cmd, FALSE, TRUE); cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc; telldot(cmd); termcommand(); break; case Tdclick: f = whichfile(inshort()); p1 = inlong(); doubleclick(f, p1); f->tdot.p1 = f->tdot.p2 = p1; telldot(f); outTs(Hunlockfile, f->tag); break; case Tstartsnarf: if (snarfbuf.nc <= 0) { /* nothing to export */ outTs(Hsetsnarf, 0); break; } c = 0; i = 0; m = snarfbuf.nc; if(m > SNARFSIZE) { m = SNARFSIZE; dprint("?warning: snarf buffer truncated\n"); } rp = malloc(m*sizeof(Rune)); if(rp){ bufread(&snarfbuf, 0, rp, m); c = Strtoc(tmprstr(rp, m)); free(rp); i = strlen(c); } outTs(Hsetsnarf, i); if(c){ Write(1, c, i); free(c); } else dprint("snarf buffer too long\n"); break; case Tsetsnarf: m = inshort(); if(m > SNARFSIZE) error(Etoolong); c = malloc(m+1); if(c){