2003-09-30 17:47:42 +00:00
|
|
|
#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 noflush;
|
|
|
|
int tversion;
|
|
|
|
|
|
|
|
long inlong(void);
|
|
|
|
long invlong(void);
|
|
|
|
int inshort(void);
|
|
|
|
int inmesg(Tmesg);
|
|
|
|
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];
|
|
|
|
|
|
|
|
sprint(buf, "%ld", n);
|
|
|
|
journal(out, buf);
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#define journal(a, b)
|
|
|
|
#define journaln(a, b)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int
|
|
|
|
rcvchar(void){
|
|
|
|
static uchar buf[64];
|
2003-09-30 19:05:50 +00:00
|
|
|
static int i, nleft = 0;
|
2003-09-30 17:47:42 +00:00
|
|
|
|
|
|
|
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;
|
2003-09-30 19:05:50 +00:00
|
|
|
static int state = 0;
|
|
|
|
static int count = 0;
|
|
|
|
static int i = 0;
|
2003-09-30 17:47:42 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
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:
|
|
|
|
l = invlong(); /* for 64-bit pointers */
|
|
|
|
journaln(0, l);
|
|
|
|
Strdupl(&genstr, samname);
|
|
|
|
cmd = newfile();
|
|
|
|
cmd->unread = 0;
|
|
|
|
outTsv(Hbindname, cmd->tag, l);
|
|
|
|
outTs(Hcurrent, cmd->tag);
|
|
|
|
logsetname(cmd, &genstr);
|
|
|
|
cmd->rasp = emalloc(sizeof(List));
|
|
|
|
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");
|
2003-09-30 19:05:50 +00:00
|
|
|
if(p1>f->b.nc)
|
|
|
|
p1 = f->b.nc;
|
|
|
|
if(p0>f->b.nc) /* can happen e.g. scrolling during command */
|
|
|
|
p0 = f->b.nc;
|
2003-09-30 17:47:42 +00:00
|
|
|
if(p0 == p1){
|
|
|
|
i = 0;
|
|
|
|
r.p1 = r.p2 = p0;
|
|
|
|
}else{
|
|
|
|
r = rdata(f->rasp, p0, p1-p0);
|
|
|
|
i = r.p2-r.p1;
|
2003-09-30 19:05:50 +00:00
|
|
|
bufread(&f->b, r.p1, buf, i);
|
2003-09-30 17:47:42 +00:00
|
|
|
}
|
|
|
|
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 = emalloc(sizeof(List));
|
|
|
|
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{
|
2003-09-30 19:05:50 +00:00
|
|
|
if(f->b.nc>0){
|
|
|
|
rgrow(f->rasp, 0L, f->b.nc);
|
|
|
|
outTsll(Hgrow, f->tag, 0L, f->b.nc);
|
2003-09-30 17:47:42 +00:00
|
|
|
}
|
|
|
|
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++;
|
2003-09-30 19:05:50 +00:00
|
|
|
if(f==cmd && p0==f->b.nc-i && i>0 && str->s[i-1]=='\n'){
|
2003-09-30 17:47:42 +00:00
|
|
|
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:
|
|
|
|
l = invlong();
|
|
|
|
Strdupl(&genstr, empty);
|
|
|
|
f = newfile();
|
|
|
|
f->rasp = emalloc(sizeof(List));
|
|
|
|
outTsv(Hbindname, f->tag, l);
|
|
|
|
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;
|
2003-09-30 19:05:50 +00:00
|
|
|
addr.r.p2 = f->b.nc;
|
2003-09-30 17:47:42 +00:00
|
|
|
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];
|
2005-03-18 21:52:19 +00:00
|
|
|
if(utfrune(".*+?(|)\\[]^$", i)){
|
|
|
|
str = tmpcstr("\\");
|
|
|
|
Strinsert(&genstr, str, l++);
|
|
|
|
freetmpstr(str);
|
|
|
|
}
|
2003-09-30 17:47:42 +00:00
|
|
|
}
|
|
|
|
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');
|
2003-09-30 19:05:50 +00:00
|
|
|
loginsert(cmd, cmd->b.nc, genstr.s, genstr.n);
|
2003-09-30 17:47:42 +00:00
|
|
|
fileupdate(cmd, FALSE, TRUE);
|
2003-09-30 19:05:50 +00:00
|
|
|
cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->b.nc;
|
2003-09-30 17:47:42 +00:00
|
|
|
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--;
|
2003-09-30 19:05:50 +00:00
|
|
|
while(p1<f->b.nc && (i=filereadc(f, p1))!=' ' && i!='\t' && i!='\n')
|
2003-09-30 17:47:42 +00:00
|
|
|
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) */
|
2003-09-30 19:05:50 +00:00
|
|
|
if(p2 > f->b.nc){
|
|
|
|
fprint(2, "bad snarf addr p1=%ld p2=%ld f->b.nc=%d\n", p1, p2, f->b.nc); /*ZZZ should never happen, can remove */
|
|
|
|
p2 = f->b.nc;
|
2003-09-30 17:47:42 +00:00
|
|
|
}
|
|
|
|
for(l=p1; l<p2; l+=i){
|
|
|
|
i = p2-l>BLOCKSIZE? BLOCKSIZE : p2-l;
|
2003-09-30 19:05:50 +00:00
|
|
|
bufread(&f->b, l, genbuf, i);
|
2003-09-30 17:47:42 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
long
|
|
|
|
invlong(void)
|
|
|
|
{
|
|
|
|
ulong n;
|
|
|
|
|
|
|
|
n = (inp[7]<<24) | (inp[6]<<16) | (inp[5]<<8) | inp[4];
|
|
|
|
n = (n<<16) | (inp[3]<<8) | inp[2];
|
|
|
|
n = (n<<16) | (inp[1]<<8) | inp[0];
|
|
|
|
inp += 8;
|
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
setgenstr(File *f, Posn p0, Posn p1)
|
|
|
|
{
|
|
|
|
if(p0 != p1){
|
|
|
|
if(p1-p0 >= TBLOCKSIZE)
|
|
|
|
error(Etoolong);
|
|
|
|
Strinsure(&genstr, p1-p0);
|
2003-09-30 19:05:50 +00:00
|
|
|
bufread(&f->b, p0, genbuf, p1-p0);
|
2003-09-30 17:47:42 +00:00
|
|
|
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, Posn l)
|
|
|
|
{
|
|
|
|
outstart(type);
|
|
|
|
outshort(s);
|
|
|
|
outvlong((void*)l);
|
|
|
|
journaln(1, l);
|
|
|
|
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(void *v)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
ulong l;
|
|
|
|
|
|
|
|
l = (ulong) v;
|
|
|
|
for(i = 0; i < 8; i++, l >>= 8)
|
|
|
|
*outp++ = l;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
outsend(void)
|
|
|
|
{
|
|
|
|
int outcount;
|
|
|
|
|
|
|
|
outcount = outp-outmsg;
|
|
|
|
outcount -= 3;
|
|
|
|
outmsg[1] = outcount;
|
|
|
|
outmsg[2] = outcount>>8;
|
|
|
|
outmsg = outp;
|
|
|
|
if(!noflush){
|
|
|
|
outcount = outmsg-outdata;
|
|
|
|
if (write(1, (char*) outdata, outcount) != outcount)
|
|
|
|
rescue();
|
|
|
|
outmsg = outdata;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(outmsg < outdata+DATASIZE)
|
|
|
|
return;
|
|
|
|
outflush();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
outflush(void)
|
|
|
|
{
|
|
|
|
if(outmsg == outdata)
|
|
|
|
return;
|
|
|
|
noflush = 0;
|
|
|
|
outT0(Hack);
|
|
|
|
waitack = 1;
|
|
|
|
do
|
|
|
|
if(rcv() == 0){
|
|
|
|
rescue();
|
|
|
|
exits("eof");
|
|
|
|
}
|
|
|
|
while(waitack);
|
|
|
|
outmsg = outdata;
|
|
|
|
noflush = 1;
|
|
|
|
}
|