123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849 |
- #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 = 0;
- 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){
- for(i=0; i<m; i++)
- c[i] = rcvchar();
- c[m] = 0;
- str = tmpcstr(c);
- free(c);
- bufreset(&snarfbuf);
- bufinsert(&snarfbuf, (Posn)0, str->s, str->n);
- freetmpstr(str);
- outT0(Hunlock);
- }
- break;
- case Tack:
- waitack = 0;
- break;
- case Tplumb:
- f = whichfile(inshort());
- p0 = inlong();
- p1 = inlong();
- pm = emalloc(sizeof(Plumbmsg));
- pm->src = strdup("sam");
- pm->dst = 0;
- /* construct current directory */
- c = Strtoc(&f->name);
- if(c[0] == '/')
- pm->wdir = c;
- else{
- wdir = emalloc(1024);
- getwd(wdir, 1024);
- pm->wdir = emalloc(1024);
- snprint(pm->wdir, 1024, "%s/%s", wdir, c);
- cleanname(pm->wdir);
- free(wdir);
- free(c);
- }
- c = strrchr(pm->wdir, '/');
- if(c)
- *c = '\0';
- pm->type = strdup("text");
- if(p1 > p0)
- pm->attr = nil;
- else{
- p = p0;
- while(p0>0 && (i=filereadc(f, p0 - 1))!=' ' && i!='\t' && i!='\n')
- p0--;
- while(p1<f->nc && (i=filereadc(f, p1))!=' ' && i!='\t' && i!='\n')
- p1++;
- sprint(cbuf, "click=%ld", p-p0);
- pm->attr = plumbunpackattr(cbuf);
- }
- if(p0==p1 || p1-p0>=BLOCKSIZE){
- plumbfree(pm);
- break;
- }
- setgenstr(f, p0, p1);
- pm->data = Strtoc(&genstr);
- pm->ndata = strlen(pm->data);
- c = plumbpack(pm, &i);
- if(c != 0){
- outTs(Hplumb, i);
- Write(1, c, i);
- free(c);
- }
- plumbfree(pm);
- break;
- case Texit:
- exits(0);
- }
- return TRUE;
- }
- void
- snarf(File *f, Posn p1, Posn p2, Buffer *buf, int emptyok)
- {
- Posn l;
- int i;
- if(!emptyok && p1==p2)
- return;
- bufreset(buf);
- /* Stage through genbuf to avoid compaction problems (vestigial) */
- if(p2 > f->nc){
- fprint(2, "bad snarf addr p1=%ld p2=%ld f->nc=%d\n", p1, p2, f->nc); /*ZZZ should never happen, can remove */
- p2 = f->nc;
- }
- for(l=p1; l<p2; l+=i){
- i = p2-l>BLOCKSIZE? BLOCKSIZE : p2-l;
- bufread(f, l, genbuf, i);
- bufinsert(buf, buf->nc, tmprstr(genbuf, i)->s, i);
- }
- }
- int
- inshort(void)
- {
- ushort n;
- n = inp[0] | (inp[1]<<8);
- inp += 2;
- return n;
- }
- long
- inlong(void)
- {
- ulong n;
- n = inp[0] | (inp[1]<<8) | (inp[2]<<16) | (inp[3]<<24);
- inp += 4;
- return n;
- }
- vlong
- invlong(void)
- {
- vlong v;
-
- v = (inp[7]<<24) | (inp[6]<<16) | (inp[5]<<8) | inp[4];
- v = (v<<16) | (inp[3]<<8) | inp[2];
- v = (v<<16) | (inp[1]<<8) | inp[0];
- inp += 8;
- return v;
- }
- void
- setgenstr(File *f, Posn p0, Posn p1)
- {
- if(p0 != p1){
- if(p1-p0 >= TBLOCKSIZE)
- error(Etoolong);
- Strinsure(&genstr, p1-p0);
- bufread(f, p0, genbuf, p1-p0);
- memmove(genstr.s, genbuf, RUNESIZE*(p1-p0));
- genstr.n = p1-p0;
- }else{
- if(snarfbuf.nc == 0)
- error(Eempty);
- if(snarfbuf.nc > TBLOCKSIZE)
- error(Etoolong);
- bufread(&snarfbuf, (Posn)0, genbuf, snarfbuf.nc);
- Strinsure(&genstr, snarfbuf.nc);
- memmove(genstr.s, genbuf, RUNESIZE*snarfbuf.nc);
- genstr.n = snarfbuf.nc;
- }
- }
- void
- outT0(Hmesg type)
- {
- outstart(type);
- outsend();
- }
- void
- outTl(Hmesg type, long l)
- {
- outstart(type);
- outlong(l);
- outsend();
- }
- void
- outTs(Hmesg type, int s)
- {
- outstart(type);
- journaln(1, s);
- outshort(s);
- outsend();
- }
- void
- outS(String *s)
- {
- char *c;
- int i;
- c = Strtoc(s);
- i = strlen(c);
- outcopy(i, c);
- if(i > 99)
- c[99] = 0;
- journaln(1, i);
- journal(1, c);
- free(c);
- }
- void
- outTsS(Hmesg type, int s1, String *s)
- {
- outstart(type);
- outshort(s1);
- outS(s);
- outsend();
- }
- void
- outTslS(Hmesg type, int s1, Posn l1, String *s)
- {
- outstart(type);
- outshort(s1);
- journaln(1, s1);
- outlong(l1);
- journaln(1, l1);
- outS(s);
- outsend();
- }
- void
- outTS(Hmesg type, String *s)
- {
- outstart(type);
- outS(s);
- outsend();
- }
- void
- outTsllS(Hmesg type, int s1, Posn l1, Posn l2, String *s)
- {
- outstart(type);
- outshort(s1);
- outlong(l1);
- outlong(l2);
- journaln(1, l1);
- journaln(1, l2);
- outS(s);
- outsend();
- }
- void
- outTsll(Hmesg type, int s, Posn l1, Posn l2)
- {
- outstart(type);
- outshort(s);
- outlong(l1);
- outlong(l2);
- journaln(1, l1);
- journaln(1, l2);
- outsend();
- }
- void
- outTsl(Hmesg type, int s, Posn l)
- {
- outstart(type);
- outshort(s);
- outlong(l);
- journaln(1, l);
- outsend();
- }
- void
- outTsv(Hmesg type, int s, vlong v)
- {
- outstart(type);
- outshort(s);
- outvlong(v);
- journalv(1, v);
- outsend();
- }
- void
- outstart(Hmesg type)
- {
- journal(1, hname[type]);
- outmsg[0] = type;
- outp = outmsg+3;
- }
- void
- outcopy(int count, void *data)
- {
- memmove(outp, data, count);
- outp += count;
- }
- void
- outshort(int s)
- {
- *outp++ = s;
- *outp++ = s>>8;
- }
- void
- outlong(long l)
- {
- *outp++ = l;
- *outp++ = l>>8;
- *outp++ = l>>16;
- *outp++ = l>>24;
- }
- void
- outvlong(vlong v)
- {
- int i;
- for(i = 0; i < 8; i++){
- *outp++ = v;
- v >>= 8;
- }
- }
- void
- outsend(void)
- {
- int outcount;
- if(outp >= outdata+nelem(outdata))
- panic("outsend");
- outcount = outp-outmsg;
- outcount -= 3;
- outmsg[1] = outcount;
- outmsg[2] = outcount>>8;
- outmsg = outp;
- if(!outbuffered){
- outcount = outmsg-outdata;
- if (write(1, (char*) outdata, outcount) != outcount)
- rescue();
- outmsg = outdata;
- return;
- }
- }
- int
- needoutflush(void)
- {
- return outmsg >= outdata+DATASIZE;
- }
- void
- outflush(void)
- {
- if(outmsg == outdata)
- return;
- outbuffered = 0;
- /* flow control */
- outT0(Hack);
- waitack = 1;
- do
- if(rcv() == 0){
- rescue();
- exits("eof");
- }
- while(waitack);
- outmsg = outdata;
- outbuffered = 1;
- }
|