Fighting the good fight.
Move libfmt, libutf into subdirectories of lib9. Add poll-based socket i/o to libthread, so that we can avoid using multiple procs when possible, thus removing dependence on crappy pthreads implementations. Convert samterm, acme to the single-proc libthread. Bring libcomplete, acme up-to-date w.r.t. Plan 9 distribution.
This commit is contained in:
parent
d51419bf43
commit
5a8e63b2f0
107 changed files with 665 additions and 6637 deletions
|
|
@ -76,6 +76,7 @@ int isunix;
|
|||
Queue *outq;
|
||||
Queue *inq;
|
||||
int verbose;
|
||||
int msize = 8192;
|
||||
|
||||
void *gethash(Hash**, uint);
|
||||
int puthash(Hash**, uint, void*);
|
||||
|
|
@ -94,7 +95,6 @@ void *erealloc(void*, int);
|
|||
Queue *qalloc(void);
|
||||
int sendq(Queue*, void*);
|
||||
void *recvq(Queue*);
|
||||
void pollthread(void*);
|
||||
void connthread(void*);
|
||||
void connoutthread(void*);
|
||||
void listenthread(void*);
|
||||
|
|
@ -125,7 +125,6 @@ threadmain(int argc, char **argv)
|
|||
{
|
||||
char *file;
|
||||
|
||||
if(verbose) fprint(2, "9pserve running\n");
|
||||
ARGBEGIN{
|
||||
default:
|
||||
usage();
|
||||
|
|
@ -143,6 +142,7 @@ threadmain(int argc, char **argv)
|
|||
break;
|
||||
}ARGEND
|
||||
|
||||
if(verbose) fprint(2, "9pserve running\n");
|
||||
if(argc != 1)
|
||||
usage();
|
||||
addr = argv[0];
|
||||
|
|
@ -150,8 +150,19 @@ threadmain(int argc, char **argv)
|
|||
if((afd = announce(addr, adir)) < 0)
|
||||
sysfatal("announce %s: %r", addr);
|
||||
|
||||
proccreate(mainproc, nil, STACK);
|
||||
threadexits(0);
|
||||
if(verbose) fprint(2, "9pserve forking\n");
|
||||
switch(fork()){
|
||||
case -1:
|
||||
sysfatal("fork: %r");
|
||||
case 0:
|
||||
if(verbose) fprint(2, "running mainproc\n");
|
||||
mainproc(nil);
|
||||
if(verbose) fprint(2, "mainproc finished\n");
|
||||
_exits(0);
|
||||
default:
|
||||
if(verbose) fprint(2, "9pserve exiting\n");
|
||||
_exits(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -161,8 +172,6 @@ mainproc(void *v)
|
|||
Fcall f;
|
||||
USED(v);
|
||||
|
||||
yield(); /* let threadmain exit */
|
||||
|
||||
atnotify(ignorepipe, 1);
|
||||
fmtinstall('D', dirfmt);
|
||||
fmtinstall('M', dirmodefmt);
|
||||
|
|
@ -174,7 +183,7 @@ mainproc(void *v)
|
|||
|
||||
f.type = Tversion;
|
||||
f.version = "9P2000";
|
||||
f.msize = 8192;
|
||||
f.msize = msize;
|
||||
f.tag = NOTAG;
|
||||
n = convS2M(&f, vbuf, sizeof vbuf);
|
||||
if(verbose > 1) fprint(2, "* <- %F\n", &f);
|
||||
|
|
@ -182,12 +191,13 @@ mainproc(void *v)
|
|||
n = read9pmsg(0, vbuf, sizeof vbuf);
|
||||
if(convM2S(vbuf, n, &f) != n)
|
||||
sysfatal("convM2S failure");
|
||||
if(f.msize < msize)
|
||||
msize = f.msize;
|
||||
if(verbose > 1) fprint(2, "* -> %F\n", &f);
|
||||
|
||||
threadcreate(inputthread, nil, STACK);
|
||||
threadcreate(outputthread, nil, STACK);
|
||||
threadcreate(listenthread, nil, STACK);
|
||||
threadcreateidle(pollthread, nil, STACK);
|
||||
threadexits(0);
|
||||
}
|
||||
|
||||
|
|
@ -296,8 +306,8 @@ connthread(void *arg)
|
|||
case Tversion:
|
||||
m->rx.tag = m->tx.tag;
|
||||
m->rx.msize = m->tx.msize;
|
||||
if(m->rx.msize > 8192)
|
||||
m->rx.msize = 8192;
|
||||
if(m->rx.msize > msize)
|
||||
m->rx.msize = msize;
|
||||
m->rx.version = "9P2000";
|
||||
m->rx.type = Rversion;
|
||||
send9pmsg(m);
|
||||
|
|
@ -480,7 +490,7 @@ openfdthread(void *v)
|
|||
m->internal = 1;
|
||||
m->c = c;
|
||||
m->tx.type = Tread;
|
||||
m->tx.count = 8192;
|
||||
m->tx.count = msize - IOHDRSZ;
|
||||
m->tx.fid = fid->fid;
|
||||
m->tx.tag = m->tag;
|
||||
m->tx.offset = tot;
|
||||
|
|
@ -506,7 +516,10 @@ openfdthread(void *v)
|
|||
}else{
|
||||
for(;;){
|
||||
if(verbose) fprint(2, "twrite...");
|
||||
if((n=ioread(io, c->fd, buf, sizeof buf)) <= 0){
|
||||
n = sizeof buf;
|
||||
if(n > msize)
|
||||
n = msize;
|
||||
if((n=ioread(io, c->fd, buf, n)) <= 0){
|
||||
if(n < 0)
|
||||
fprint(2, "pipe read error: %r\n");
|
||||
m = nil;
|
||||
|
|
@ -1122,106 +1135,23 @@ struct Ioproc
|
|||
int index;
|
||||
};
|
||||
|
||||
static struct Ioproc **pio;
|
||||
static struct pollfd *pfd;
|
||||
static int npfd;
|
||||
static struct Ioproc *iofree;
|
||||
|
||||
Ioproc*
|
||||
ioproc(void)
|
||||
{
|
||||
Ioproc *io;
|
||||
|
||||
if(iofree == nil){
|
||||
pfd = erealloc(pfd, (npfd+1)*sizeof(pfd[0]));
|
||||
pfd[npfd].events = 0;
|
||||
pfd[npfd].fd = -1;
|
||||
iofree = emalloc(sizeof(Ioproc));
|
||||
iofree->index = npfd;
|
||||
iofree->c = chancreate(sizeof(ulong), 1);
|
||||
pio = erealloc(pio, (npfd+1)*sizeof(pio[0]));
|
||||
pio[npfd] = iofree;
|
||||
npfd++;
|
||||
}
|
||||
io = iofree;
|
||||
iofree = io->next;
|
||||
return io;
|
||||
return (Ioproc*)-1;
|
||||
}
|
||||
|
||||
void
|
||||
closeioproc(Ioproc *io)
|
||||
{
|
||||
io->next = iofree;
|
||||
iofree = io;
|
||||
}
|
||||
|
||||
void
|
||||
pollthread(void *v)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
for(;;){
|
||||
yield();
|
||||
for(i=0; i<npfd; i++)
|
||||
pfd[i].revents = 0;
|
||||
if(verbose){
|
||||
fprint(2, "poll:");
|
||||
for(i=0; i<npfd; i++)
|
||||
if(pfd[i].events)
|
||||
fprint(2, " %d%c", pfd[i].fd, pfd[i].events==POLLIN ? 'r' : pfd[i].events==POLLOUT ? 'w' : '?');
|
||||
fprint(2, "\n");
|
||||
}
|
||||
n = poll(pfd, npfd, -1);
|
||||
if(n <= 0)
|
||||
continue;
|
||||
for(i=0; i<npfd; i++)
|
||||
if(pfd[i].fd != -1 && pfd[i].revents){
|
||||
pfd[i].fd = -1;
|
||||
pfd[i].events = 0;
|
||||
pfd[i].revents = 0;
|
||||
nbsendul(pio[i]->c, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
noblock(int fd)
|
||||
{
|
||||
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
|
||||
}
|
||||
|
||||
static void
|
||||
xwait(Ioproc *io, int fd, int e)
|
||||
{
|
||||
if(verbose) fprint(2, "wait for %d%c\n", fd, e==POLLIN ? 'r' : 'w');
|
||||
pfd[io->index].fd = fd;
|
||||
pfd[io->index].events = e;
|
||||
recvul(io->c);
|
||||
if(verbose) fprint(2, "got %d\n", fd);
|
||||
}
|
||||
|
||||
static void
|
||||
rwait(Ioproc *io, int fd)
|
||||
{
|
||||
xwait(io, fd, POLLIN);
|
||||
}
|
||||
|
||||
static void
|
||||
wwait(Ioproc *io, int fd)
|
||||
{
|
||||
xwait(io, fd, POLLOUT);
|
||||
}
|
||||
|
||||
long
|
||||
ioread(Ioproc *io, int fd, void *v, long n)
|
||||
{
|
||||
long r;
|
||||
USED(io);
|
||||
|
||||
noblock(fd);
|
||||
while((r=read(fd, v, n)) < 0 && errno == EWOULDBLOCK)
|
||||
rwait(io, fd);
|
||||
return r;
|
||||
return threadread(fd, v, n);
|
||||
}
|
||||
|
||||
long
|
||||
|
|
@ -1247,9 +1177,16 @@ iorecvfd(Ioproc *io, int fd)
|
|||
{
|
||||
int r;
|
||||
|
||||
noblock(fd);
|
||||
while((r=recvfd(fd)) < 0 && errno == EWOULDBLOCK)
|
||||
rwait(io, fd);
|
||||
threadfdnoblock(fd);
|
||||
while((r=recvfd(fd)) < 0){
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
if(errno == EWOULDBLOCK || errno == EAGAIN){
|
||||
threadfdwait(fd, 'r');
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -1258,23 +1195,24 @@ iosendfd(Ioproc *io, int s, int fd)
|
|||
{
|
||||
int r;
|
||||
|
||||
noblock(s);
|
||||
while((r=sendfd(s, fd)) < 0 && errno == EWOULDBLOCK)
|
||||
wwait(io, s);
|
||||
if(r < 0) fprint(2, "sent %d, %d\n", s, fd);
|
||||
threadfdnoblock(s);
|
||||
while((r=sendfd(s, fd)) < 0){
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
if(errno == EWOULDBLOCK || errno == EAGAIN){
|
||||
threadfdwait(fd, 'w');
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
static long
|
||||
_iowrite(Ioproc *io, int fd, void *v, long n)
|
||||
{
|
||||
long r;
|
||||
USED(io);
|
||||
|
||||
noblock(fd);
|
||||
while((r=write(fd, v, n)) < 0 && errno == EWOULDBLOCK)
|
||||
wwait(io, fd);
|
||||
return r;
|
||||
return threadwrite(fd, v, n);
|
||||
}
|
||||
|
||||
long
|
||||
|
|
@ -1305,9 +1243,16 @@ iolisten(Ioproc *io, char *dir, char *ndir)
|
|||
|
||||
if((fd = _p9netfd(dir)) < 0)
|
||||
return -1;
|
||||
noblock(fd);
|
||||
while((r=listen(dir, ndir)) < 0 && errno == EWOULDBLOCK)
|
||||
rwait(io, fd);
|
||||
threadfdnoblock(fd);
|
||||
while((r=listen(dir, ndir)) < 0){
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
if(errno == EWOULDBLOCK || errno == EAGAIN){
|
||||
threadfdwait(fd, 'r');
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -1317,9 +1262,16 @@ ioaccept(Ioproc *io, int fd, char *dir)
|
|||
int r;
|
||||
USED(io);
|
||||
|
||||
noblock(fd);
|
||||
while((r=accept(fd, dir)) < 0 && errno == EWOULDBLOCK)
|
||||
rwait(io, fd);
|
||||
threadfdnoblock(fd);
|
||||
while((r=accept(fd, dir)) < 0){
|
||||
if(errno == EINTR)
|
||||
continue;
|
||||
if(errno == EWOULDBLOCK || errno == EAGAIN){
|
||||
threadfdwait(fd, 'r');
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,6 @@ threadmain(int argc, char *argv[])
|
|||
{
|
||||
int i;
|
||||
char *p, *loadfile;
|
||||
char buf[256];
|
||||
Column *c;
|
||||
int ncol;
|
||||
Display *d;
|
||||
|
|
@ -70,6 +69,9 @@ threadmain(int argc, char *argv[])
|
|||
|
||||
loadfile = nil;
|
||||
ARGBEGIN{
|
||||
case 'a':
|
||||
globalautoindent = TRUE;
|
||||
break;
|
||||
case 'b':
|
||||
bartflag = TRUE;
|
||||
break;
|
||||
|
|
@ -98,7 +100,7 @@ threadmain(int argc, char *argv[])
|
|||
break;
|
||||
default:
|
||||
Usage:
|
||||
fprint(2, "usage: acme -c ncol -f fontname -F fixedwidthfontname -l loadfile\n");
|
||||
fprint(2, "usage: acme -a -c ncol -f fontname -F fixedwidthfontname -l loadfile\n");
|
||||
exits("usage");
|
||||
}ARGEND
|
||||
|
||||
|
|
@ -183,7 +185,7 @@ threadmain(int argc, char *argv[])
|
|||
fprint(2, "acme: can't initialize plumber: %r\n");
|
||||
else{
|
||||
cplumb = chancreate(sizeof(Plumbmsg*), 0);
|
||||
proccreate(plumbproc, nil, STACK);
|
||||
threadcreate(plumbproc, nil, STACK);
|
||||
}
|
||||
plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
|
||||
|
||||
|
|
@ -315,7 +317,7 @@ acmeerrorproc(void *v)
|
|||
USED(v);
|
||||
threadsetname("acmeerrorproc");
|
||||
buf = emalloc(8192+1);
|
||||
while((n=read(errorfd, buf, 8192)) >= 0){
|
||||
while((n=threadread(errorfd, buf, 8192)) >= 0){
|
||||
buf[n] = '\0';
|
||||
sendp(cerr, estrdup(buf));
|
||||
}
|
||||
|
|
@ -324,8 +326,7 @@ acmeerrorproc(void *v)
|
|||
void
|
||||
acmeerrorinit(void)
|
||||
{
|
||||
int fd, pfd[2];
|
||||
char buf[64];
|
||||
int pfd[2];
|
||||
|
||||
if(pipe(pfd) < 0)
|
||||
error("can't create pipe");
|
||||
|
|
@ -351,7 +352,7 @@ acmeerrorinit(void)
|
|||
errorfd = pfd[1];
|
||||
if(errorfd < 0)
|
||||
error("can't re-open acmeerror file");
|
||||
proccreate(acmeerrorproc, nil, STACK);
|
||||
threadcreate(acmeerrorproc, nil, STACK);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -362,7 +363,7 @@ plumbproc(void *v)
|
|||
USED(v);
|
||||
threadsetname("plumbproc");
|
||||
for(;;){
|
||||
m = plumbrecv(plumbeditfd);
|
||||
m = threadplumbrecv(plumbeditfd);
|
||||
if(m == nil)
|
||||
threadexits(nil);
|
||||
sendp(cplumb, m);
|
||||
|
|
@ -399,6 +400,7 @@ keyboardthread(void *v)
|
|||
winlock(t->w, 'K');
|
||||
wincommit(t->w, t);
|
||||
winunlock(t->w);
|
||||
flushwarnings(1);
|
||||
flushimage(display, 1);
|
||||
}
|
||||
alts[KTimer].c = nil;
|
||||
|
|
@ -425,6 +427,7 @@ keyboardthread(void *v)
|
|||
}
|
||||
if(nbrecv(keyboardctl->c, &r) > 0)
|
||||
goto casekeyboard;
|
||||
flushwarnings(1);
|
||||
flushimage(display, 1);
|
||||
break;
|
||||
}
|
||||
|
|
@ -467,6 +470,7 @@ mousethread(void *v)
|
|||
draw(screen, screen->r, display->white, nil, ZP);
|
||||
scrlresize();
|
||||
rowresize(&row, screen->clipr);
|
||||
flushwarnings(1);
|
||||
flushimage(display, 1);
|
||||
break;
|
||||
case MPlumb:
|
||||
|
|
@ -477,6 +481,7 @@ mousethread(void *v)
|
|||
else if(strcmp(act, "showdata")==0)
|
||||
plumbshow(pm);
|
||||
}
|
||||
flushwarnings(1);
|
||||
flushimage(display, 1);
|
||||
plumbfree(pm);
|
||||
break;
|
||||
|
|
@ -562,6 +567,7 @@ mousethread(void *v)
|
|||
goto Continue;
|
||||
}
|
||||
Continue:
|
||||
flushwarnings(0);
|
||||
flushimage(display, 1);
|
||||
qunlock(&row.lk);
|
||||
break;
|
||||
|
|
@ -916,36 +922,48 @@ iconinit(void)
|
|||
void
|
||||
acmeputsnarf(void)
|
||||
{
|
||||
int fd, i, n;
|
||||
int i, n;
|
||||
Fmt f;
|
||||
char *s;
|
||||
|
||||
if(snarffd<0 || snarfbuf.nc==0)
|
||||
if(snarfbuf.nc==0)
|
||||
return;
|
||||
if(snarfbuf.nc > MAXSNARF)
|
||||
return;
|
||||
fd = open("/dev/snarf", OWRITE);
|
||||
if(fd < 0)
|
||||
return;
|
||||
|
||||
fmtstrinit(&f);
|
||||
for(i=0; i<snarfbuf.nc; i+=n){
|
||||
n = snarfbuf.nc-i;
|
||||
if(n >= NSnarf)
|
||||
n = NSnarf;
|
||||
bufread(&snarfbuf, i, snarfrune, n);
|
||||
if(fprint(fd, "%.*S", n, snarfrune) < 0)
|
||||
if(fmtprint(&f, "%.*S", n, snarfrune) < 0)
|
||||
break;
|
||||
}
|
||||
close(fd);
|
||||
s = fmtstrflush(&f);
|
||||
if(s && s[0])
|
||||
putsnarf(s);
|
||||
free(s);
|
||||
}
|
||||
|
||||
void
|
||||
acmegetsnarf()
|
||||
acmegetsnarf(void)
|
||||
{
|
||||
int nulls;
|
||||
char *s;
|
||||
int nb, nr, nulls, len;
|
||||
Rune *r;
|
||||
|
||||
if(snarfbuf.nc > MAXSNARF)
|
||||
s = getsnarf();
|
||||
if(s == nil || s[0]==0){
|
||||
free(s);
|
||||
return;
|
||||
if(snarffd < 0)
|
||||
return;
|
||||
seek(snarffd, 0, 0);
|
||||
}
|
||||
|
||||
len = strlen(s);
|
||||
r = runemalloc(len+1);
|
||||
cvttorunes(s, len, r, &nb, &nr, &nulls);
|
||||
bufreset(&snarfbuf);
|
||||
bufload(&snarfbuf, 0, snarffd, &nulls);
|
||||
bufinsert(&snarfbuf, 0, r, nr);
|
||||
free(r);
|
||||
free(s);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -232,6 +232,7 @@ struct Window
|
|||
uchar isscratch;
|
||||
uchar filemenu;
|
||||
uchar dirty;
|
||||
uchar autoindent;
|
||||
int id;
|
||||
Range addr;
|
||||
Range limit;
|
||||
|
|
@ -486,6 +487,7 @@ enum /* editing */
|
|||
Collecting,
|
||||
};
|
||||
|
||||
uint globalincref;
|
||||
uint seq;
|
||||
uint maxtab; /* size of a tab, in units of the '0' character */
|
||||
|
||||
|
|
@ -524,10 +526,11 @@ Image *tagcols[NCOL];
|
|||
Image *textcols[NCOL];
|
||||
int plumbsendfd;
|
||||
int plumbeditfd;
|
||||
extern char wdir[];
|
||||
extern char wdir[]; /* must use extern because no dimension given */
|
||||
int editing;
|
||||
int erroutfd;
|
||||
int messagesize; /* negotiated in 9P version setup */
|
||||
int globalautoindent;
|
||||
|
||||
Channel *ckeyboard; /* chan(Rune)[10] */
|
||||
Channel *cplumb; /* chan(Plumbmsg*) */
|
||||
|
|
|
|||
|
|
@ -596,7 +596,7 @@ runpipe(Text *t, int cmd, Rune *cr, int ncr, int state)
|
|||
|
||||
r = skipbl(cr, ncr, &n);
|
||||
if(n == 0)
|
||||
editerror("no command specified for >");
|
||||
editerror("no command specified for %c", cmd);
|
||||
w = nil;
|
||||
if(state == Inserting){
|
||||
w = t->w;
|
||||
|
|
@ -949,12 +949,15 @@ filelooper(Cmd *cp, int XY)
|
|||
/*
|
||||
* add a ref to all windows to keep safe windows accessed by X
|
||||
* that would not otherwise have a ref to hold them up during
|
||||
* the shenanigans.
|
||||
* the shenanigans. note this with globalincref so that any
|
||||
* newly created windows start with an extra reference.
|
||||
*/
|
||||
allwindows(alllocker, (void*)1);
|
||||
globalincref = 1;
|
||||
for(i=0; i<loopstruct.nw; i++)
|
||||
cmdexec(&loopstruct.w[i]->body, cp->u.cmd);
|
||||
allwindows(alllocker, (void*)0);
|
||||
globalincref = 0;
|
||||
free(loopstruct.w);
|
||||
loopstruct.w = nil;
|
||||
|
||||
|
|
|
|||
|
|
@ -462,7 +462,7 @@ getname(Text *t, Text *argt, Rune *arg, int narg, int isput)
|
|||
dir.nr = 0;
|
||||
if(n>0 && arg[0]!='/'){
|
||||
dir = dirname(t, nil, 0);
|
||||
if(n==1 && dir.r[0]=='.'){ /* sigh */
|
||||
if(dir.nr==1 && dir.r[0]=='.'){ /* sigh */
|
||||
free(dir.r);
|
||||
dir.r = nil;
|
||||
dir.nr = 0;
|
||||
|
|
@ -606,15 +606,15 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
|
|||
f->qidpath = d->qid.path;
|
||||
f->mtime = d->mtime;
|
||||
if(f->unread)
|
||||
warningew(w, nil, "%s not written; file already exists\n", name);
|
||||
warning(nil, "%s not written; file already exists\n", name);
|
||||
else
|
||||
warningew(w, nil, "%s modified%s%s since last read\n", name, d->muid[0]?" by ":"", d->muid);
|
||||
warning(nil, "%s modified%s%s since last read\n", name, d->muid[0]?" by ":"", d->muid);
|
||||
goto Rescue1;
|
||||
}
|
||||
}
|
||||
fd = create(name, OWRITE, 0666);
|
||||
if(fd < 0){
|
||||
warningew(w, nil, "can't create file %s: %r\n", name);
|
||||
warning(nil, "can't create file %s: %r\n", name);
|
||||
goto Rescue1;
|
||||
}
|
||||
r = fbufalloc();
|
||||
|
|
@ -623,7 +623,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
|
|||
d = dirfstat(fd);
|
||||
isapp = (d!=nil && d->length>0 && (d->qid.type&QTAPPEND));
|
||||
if(isapp){
|
||||
warningew(w, nil, "%s not written; file is append only\n", name);
|
||||
warning(nil, "%s not written; file is append only\n", name);
|
||||
goto Rescue2;
|
||||
}
|
||||
|
||||
|
|
@ -634,7 +634,7 @@ putfile(File *f, int q0, int q1, Rune *namer, int nname)
|
|||
bufread(&f->b, q, r, n);
|
||||
m = snprint(s, BUFSIZE+1, "%.*S", n, r);
|
||||
if(write(fd, s, m) != m){
|
||||
warningew(w, nil, "can't write file %s: %r\n", name);
|
||||
warning(nil, "can't write file %s: %r\n", name);
|
||||
goto Rescue2;
|
||||
}
|
||||
}
|
||||
|
|
@ -701,7 +701,7 @@ put(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg)
|
|||
f = w->body.file;
|
||||
name = getname(&w->body, argt, arg, narg, TRUE);
|
||||
if(name == nil){
|
||||
warningew(w, nil, "no file name\n");
|
||||
warning(nil, "no file name\n");
|
||||
return;
|
||||
}
|
||||
namer = bytetorune(name, &nname);
|
||||
|
|
@ -1163,6 +1163,58 @@ incl(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg)
|
|||
}
|
||||
}
|
||||
|
||||
static Rune LON[] = { 'O', 'N', 0 };
|
||||
static Rune LOFF[] = { 'O', 'F', 'F', 0 };
|
||||
static Rune Lon[] = { 'o', 'n', 0 };
|
||||
|
||||
static int
|
||||
indentval(Rune *s, int n)
|
||||
{
|
||||
if(n < 2)
|
||||
return -1;
|
||||
if(runestrncmp(s, LON, n) == 0){
|
||||
globalautoindent = TRUE;
|
||||
warning(nil, "Indent ON\n");
|
||||
return -2;
|
||||
}
|
||||
if(runestrncmp(s, LOFF, n) == 0){
|
||||
globalautoindent = FALSE;
|
||||
warning(nil, "Indent OFF\n");
|
||||
return -2;
|
||||
}
|
||||
return runestrncmp(s, Lon, n) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
indent(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg)
|
||||
{
|
||||
Rune *a, *r;
|
||||
Window *w;
|
||||
int na, len, autoindent;
|
||||
|
||||
USED(_0);
|
||||
USED(_1);
|
||||
USED(_2);
|
||||
|
||||
if(et==nil || et->w==nil)
|
||||
return;
|
||||
w = et->w;
|
||||
autoindent = -1;
|
||||
getarg(argt, FALSE, TRUE, &r, &len);
|
||||
if(r!=nil && len>0)
|
||||
autoindent = indentval(r, len);
|
||||
else{
|
||||
a = findbl(arg, narg, &na);
|
||||
if(a != arg)
|
||||
autoindent = indentval(arg, narg-na);
|
||||
}
|
||||
if(autoindent >= 0)
|
||||
w->autoindent = autoindent;
|
||||
if(autoindent != 2)
|
||||
warning(nil, "%.*S: Indent %s\n", w->body.file->nname, w->body.file->name,
|
||||
w->autoindent ? "on" : "off");
|
||||
}
|
||||
|
||||
void
|
||||
tab(Text *et, Text *_0, Text *argt, int _1, int _2, Rune *arg, int narg)
|
||||
{
|
||||
|
|
@ -1375,7 +1427,7 @@ runproc(void *argvp)
|
|||
av[ac++] = arg;
|
||||
av[ac] = nil;
|
||||
c->av = av;
|
||||
procexec(cpid, sfd, av[0], av);
|
||||
threadexec(cpid, sfd, av[0], av);
|
||||
/* libthread uses execvp so no need to do this */
|
||||
#if 0
|
||||
e = av[0];
|
||||
|
|
@ -1419,10 +1471,10 @@ Hard:
|
|||
c->text = news;
|
||||
}
|
||||
}
|
||||
procexecl(cpid, sfd, "rc", "rc", "-c", t, nil);
|
||||
threadexecl(cpid, sfd, "rc", "rc", "-c", t, nil);
|
||||
|
||||
Fail:
|
||||
/* procexec hasn't happened, so send a zero */
|
||||
/* threadexec hasn't happened, so send a zero */
|
||||
close(sfd[0]);
|
||||
close(sfd[1]);
|
||||
if(sfd[2] != sfd[1])
|
||||
|
|
@ -1482,7 +1534,7 @@ run(Window *win, char *s, Rune *rdir, int ndir, int newns, char *argaddr, char *
|
|||
arg[7] = c;
|
||||
arg[8] = cpid;
|
||||
arg[9] = (void*)iseditcmd;
|
||||
proccreate(runproc, arg, STACK);
|
||||
threadcreate(runproc, arg, STACK);
|
||||
/* mustn't block here because must be ready to answer mount() call in run() */
|
||||
arg = emalloc(2*sizeof(void*));
|
||||
arg[0] = c;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ void clearmouse(void);
|
|||
void allwindows(void(*)(Window*, void*), void*);
|
||||
uint loadfile(int, uint, int*, int(*)(void*, uint, Rune*, int), void*);
|
||||
|
||||
Window* errorwin(Mntdir*, int, Window*);
|
||||
Window* errorwin(Mntdir*, int);
|
||||
Runestr cleanrname(Runestr);
|
||||
void run(Window*, char*, Rune*, int, int, char*, char*, int);
|
||||
void fsysclose(void);
|
||||
|
|
@ -85,7 +85,8 @@ Window* makenewwindow(Text *t);
|
|||
int expand(Text*, uint, uint, Expand*);
|
||||
Rune* skipbl(Rune*, int, int*);
|
||||
Rune* findbl(Rune*, int, int*);
|
||||
char* edittext(Window*, int, Rune*, int);
|
||||
char* edittext(Window*, int, Rune*, int);
|
||||
void flushwarnings(int);
|
||||
|
||||
#define runemalloc(a) (Rune*)emalloc((a)*sizeof(Rune))
|
||||
#define runerealloc(a, b) (Rune*)erealloc((a), (b)*sizeof(Rune))
|
||||
|
|
|
|||
|
|
@ -111,8 +111,7 @@ void
|
|||
fsysinit(void)
|
||||
{
|
||||
int p[2];
|
||||
int n, fd;
|
||||
char buf[256], *u;
|
||||
char *u;
|
||||
|
||||
if(pipe(p) < 0)
|
||||
error("can't create pipe");
|
||||
|
|
@ -122,7 +121,7 @@ fsysinit(void)
|
|||
fmtinstall('F', fcallfmt);
|
||||
if((u = getuser()) != nil)
|
||||
user = estrdup(u);
|
||||
proccreate(fsysproc, nil, STACK);
|
||||
threadcreate(fsysproc, nil, STACK);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -138,7 +137,7 @@ fsysproc(void *v)
|
|||
x = nil;
|
||||
for(;;){
|
||||
buf = emalloc(messagesize+UTFmax); /* overflow for appending partial rune in xfidwrite */
|
||||
n = read9pmsg(sfd, buf, messagesize);
|
||||
n = threadread9pmsg(sfd, buf, messagesize);
|
||||
if(n <= 0){
|
||||
if(closing)
|
||||
break;
|
||||
|
|
@ -255,7 +254,11 @@ respond(Xfid *x, Fcall *t, char *err)
|
|||
x->buf = emalloc(messagesize);
|
||||
n = convS2M(t, x->buf, messagesize);
|
||||
if(n <= 0)
|
||||
{
|
||||
fprint(2, "convert error (n=%d, msgsize %d): have %F\n", n, messagesize, &x->fcall);
|
||||
fprint(2, "\tresponse: %F\n", t);
|
||||
error("convert error in convS2M");
|
||||
}
|
||||
if(write(sfd, x->buf, n) != n)
|
||||
error("write error in respond");
|
||||
free(x->buf);
|
||||
|
|
|
|||
|
|
@ -320,60 +320,18 @@ isfilec(Rune r)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Runestr wrapper for cleanname */
|
||||
Runestr
|
||||
cleanrname(Runestr rs)
|
||||
{
|
||||
int i, j, found;
|
||||
Rune *b;
|
||||
int n;
|
||||
static Rune Lslashdotdot[] = { '/', '.', '.', 0 };
|
||||
char *s;
|
||||
int nb, nulls;
|
||||
|
||||
b = rs.r;
|
||||
n = rs.nr;
|
||||
|
||||
/* compress multiple slashes */
|
||||
for(i=0; i<n-1; i++)
|
||||
if(b[i]=='/' && b[i+1]=='/'){
|
||||
runemove(b+i, b+i+1, n-i-1);
|
||||
--n;
|
||||
--i;
|
||||
}
|
||||
/* eliminate ./ */
|
||||
for(i=0; i<n-1; i++)
|
||||
if(b[i]=='.' && b[i+1]=='/' && (i==0 || b[i-1]=='/')){
|
||||
runemove(b+i, b+i+2, n-i-2);
|
||||
n -= 2;
|
||||
--i;
|
||||
}
|
||||
/* eliminate trailing . */
|
||||
if(n>=2 && b[n-2]=='/' && b[n-1]=='.')
|
||||
--n;
|
||||
do{
|
||||
/* compress xx/.. */
|
||||
found = FALSE;
|
||||
for(i=1; i<=n-3; i++)
|
||||
if(runeeq(b+i, 3, Lslashdotdot, 3)){
|
||||
if(i==n-3 || b[i+3]=='/'){
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
for(j=i-1; j>=0; --j)
|
||||
if(j==0 || b[j-1]=='/'){
|
||||
i += 3; /* character beyond .. */
|
||||
if(i<n && b[i]=='/')
|
||||
++i;
|
||||
runemove(b+j, b+i, n-i);
|
||||
n -= (i-j);
|
||||
break;
|
||||
}
|
||||
}while(found);
|
||||
if(n == 0){
|
||||
*b = '.';
|
||||
n = 1;
|
||||
}
|
||||
return (Runestr){b, n};
|
||||
s = runetobyte(rs.r, rs.nr);
|
||||
cleanname(s);
|
||||
cvttorunes(s, strlen(s), rs.r, &nb, &rs.nr, &nulls);
|
||||
free(s);
|
||||
return rs;
|
||||
}
|
||||
|
||||
Runestr
|
||||
|
|
@ -407,6 +365,11 @@ includename(Text *t, Rune *r, int n)
|
|||
Window *w;
|
||||
char buf[128];
|
||||
Rune Lsysinclude[] = { '/', 's', 'y', 's', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 };
|
||||
Rune Lusrinclude[] = { '/', 'u', 's', 'r', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 };
|
||||
Rune Lusrlocalinclude[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l',
|
||||
'/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 };
|
||||
Rune Lusrlocalplan9include[] = { '/', 'u', 's', 'r', '/', 'l', 'o', 'c', 'a', 'l',
|
||||
'/', 'p', 'l', 'a', 'n', '9', '/', 'i', 'n', 'c', 'l', 'u', 'd', 'e', 0 };
|
||||
Runestr file;
|
||||
int i;
|
||||
|
||||
|
|
@ -429,6 +392,12 @@ includename(Text *t, Rune *r, int n)
|
|||
|
||||
if(file.r == nil)
|
||||
file = includefile(Lsysinclude, r, n);
|
||||
if(file.r == nil)
|
||||
file = includefile(Lusrlocalplan9include, r, n);
|
||||
if(file.r == nil)
|
||||
file = includefile(Lusrlocalinclude, r, n);
|
||||
if(file.r == nil)
|
||||
file = includefile(Lusrinclude, r, n);
|
||||
if(file.r==nil && objdir!=nil)
|
||||
file = includefile(objdir, r, n);
|
||||
if(file.r == nil)
|
||||
|
|
@ -702,13 +671,16 @@ openfile(Text *t, Expand *e)
|
|||
t->w->dirty = FALSE;
|
||||
winsettag(t->w);
|
||||
textsetselect(&t->w->tag, t->w->tag.file->b.nc, t->w->tag.file->b.nc);
|
||||
if(ow != nil)
|
||||
if(ow != nil){
|
||||
for(i=ow->nincl; --i>=0; ){
|
||||
n = runestrlen(ow->incl[i]);
|
||||
rp = runemalloc(n);
|
||||
runemove(rp, ow->incl[i], n);
|
||||
winaddincl(w, rp, n);
|
||||
}
|
||||
w->autoindent = ow->autoindent;
|
||||
}else
|
||||
w->autoindent = globalautoindent;
|
||||
}
|
||||
if(e->a1 == e->a0)
|
||||
eval = FALSE;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
# Acme is up-to-date w.r.t. sources as of 29 February 2004
|
||||
|
||||
PLAN9=../../..
|
||||
<$PLAN9/src/mkhdr
|
||||
|
||||
|
|
@ -36,6 +38,6 @@ UPDATE=\
|
|||
|
||||
<$PLAN9/src/mkone
|
||||
|
||||
LDFLAGS=$LDFLAGS -lcomplete -lplumb -lfs -lmux -lthread -lframe -ldraw -lbio -l9 -lfmt -lutf -L$X11/lib -lX11
|
||||
LDFLAGS=$LDFLAGS -lcomplete -lplumb -lfs -lmux -lthread -lframe -ldraw -lbio -l9 -L$X11/lib -lX11
|
||||
|
||||
edit.$O ecmd.$O elog.$O: edit.h
|
||||
|
|
|
|||
|
|
@ -537,7 +537,7 @@ textfilewidth(Text *t, uint q0, int oneelement)
|
|||
q = q0;
|
||||
while(q > 0){
|
||||
r = textreadc(t, q-1);
|
||||
if(r<=' ')
|
||||
if(r <= ' ')
|
||||
break;
|
||||
if(oneelement && r=='/')
|
||||
break;
|
||||
|
|
@ -608,10 +608,11 @@ textcomplete(Text *t)
|
|||
}
|
||||
|
||||
if(!c->advance){
|
||||
warning(nil, "%.*S%s%.*S*\n",
|
||||
warning(nil, "%.*S%s%.*S*%s\n",
|
||||
dir.nr, dir.r,
|
||||
dir.nr>0 && dir.r[dir.nr-1]!='/' ? "/" : "",
|
||||
nstr, str);
|
||||
nstr, str,
|
||||
c->nmatch ? "" : ": no matches in:");
|
||||
for(i=0; i<c->nfile; i++)
|
||||
warning(nil, " %s\n", c->filename[i]);
|
||||
}
|
||||
|
|
@ -643,25 +644,45 @@ texttype(Text *t, Rune r)
|
|||
rp = &r;
|
||||
switch(r){
|
||||
case Kleft:
|
||||
if(t->q0 > 0)
|
||||
if(t->q0 > 0){
|
||||
textcommit(t, TRUE);
|
||||
textshow(t, t->q0-1, t->q0-1, TRUE);
|
||||
}
|
||||
return;
|
||||
case Kright:
|
||||
if(t->q1 < t->file->b.nc)
|
||||
if(t->q1 < t->file->b.nc){
|
||||
textcommit(t, TRUE);
|
||||
textshow(t, t->q1+1, t->q1+1, TRUE);
|
||||
}
|
||||
return;
|
||||
case Kdown:
|
||||
n = t->fr.maxlines/3;
|
||||
goto case_Down;
|
||||
case Kpgdown:
|
||||
n = t->fr.maxlines/2;
|
||||
n = 2*t->fr.maxlines/3;
|
||||
case_Down:
|
||||
q0 = t->org+frcharofpt(&t->fr, Pt(t->fr.r.min.x, t->fr.r.min.y+n*t->fr.font->height));
|
||||
textsetorigin(t, q0, FALSE);
|
||||
return;
|
||||
case Kup:
|
||||
n = t->fr.maxlines/3;
|
||||
goto case_Up;
|
||||
case Kpgup:
|
||||
n = t->fr.maxlines/2;
|
||||
n = 2*t->fr.maxlines/3;
|
||||
case_Up:
|
||||
q0 = textbacknl(t, t->org, n);
|
||||
textsetorigin(t, q0, FALSE);
|
||||
return;
|
||||
case Khome:
|
||||
textshow(t, 0, 0, FALSE);
|
||||
return;
|
||||
case Kend:
|
||||
if(t->w)
|
||||
wincommit(t->w, t);
|
||||
else
|
||||
textcommit(t, TRUE);
|
||||
textshow(t, t->file->b.nc, t->file->b.nc, FALSE);
|
||||
return;
|
||||
}
|
||||
if(t->what == Body){
|
||||
seq++;
|
||||
|
|
@ -734,6 +755,21 @@ texttype(Text *t, Rune r)
|
|||
for(i=0; i<t->file->ntext; i++)
|
||||
textfill(t->file->text[i]);
|
||||
return;
|
||||
case '\n':
|
||||
if(t->w->autoindent){
|
||||
/* find beginning of previous line using backspace code */
|
||||
nnb = textbswidth(t, 0x15); /* ^U case */
|
||||
rp = runemalloc(nnb + 1);
|
||||
nr = 0;
|
||||
rp[nr++] = r;
|
||||
for(i=0; i<nnb; i++){
|
||||
r = textreadc(t, t->q0-nnb+i);
|
||||
if(r != ' ' && r != '\t')
|
||||
break;
|
||||
rp[nr++] = r;
|
||||
}
|
||||
}
|
||||
break; /* fall through to normal code */
|
||||
}
|
||||
/* otherwise ordinary character; just insert, typically in caches of all texts */
|
||||
for(i=0; i<t->file->ntext; i++){
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ timerproc(void *v)
|
|||
nt = 0;
|
||||
old = msec();
|
||||
for(;;){
|
||||
sleep(1); /* will sleep minimum incr */
|
||||
threadsleep(1); /* will sleep minimum incr */
|
||||
new = msec();
|
||||
dt = new-old;
|
||||
old = new;
|
||||
|
|
@ -98,7 +98,7 @@ void
|
|||
timerinit(void)
|
||||
{
|
||||
ctimer = chancreate(sizeof(Timer*), 100);
|
||||
proccreate(timerproc, nil, STACK);
|
||||
threadcreate(timerproc, nil, STACK);
|
||||
}
|
||||
|
||||
Timer*
|
||||
|
|
|
|||
|
|
@ -62,9 +62,11 @@ errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
|
|||
int i, n;
|
||||
static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 };
|
||||
|
||||
r = runemalloc(ndir+7);
|
||||
if(n = ndir) /* assign = */
|
||||
r = runemalloc(ndir+8);
|
||||
if(n = ndir){ /* assign = */
|
||||
runemove(r, dir, ndir);
|
||||
r[n++] = L'/';
|
||||
}
|
||||
runemove(r+n, Lpluserrors, 7);
|
||||
n += 7;
|
||||
w = lookfile(r, n);
|
||||
|
|
@ -83,12 +85,13 @@ errorwin1(Rune *dir, int ndir, Rune **incl, int nincl)
|
|||
runemove(r, incl[i], n);
|
||||
winaddincl(w, r, n);
|
||||
}
|
||||
w->autoindent = globalautoindent;
|
||||
return w;
|
||||
}
|
||||
|
||||
/* make new window, if necessary; return with it locked */
|
||||
Window*
|
||||
errorwin(Mntdir *md, int owner, Window *e)
|
||||
errorwin(Mntdir *md, int owner)
|
||||
{
|
||||
Window *w;
|
||||
|
||||
|
|
@ -97,51 +100,100 @@ errorwin(Mntdir *md, int owner, Window *e)
|
|||
w = errorwin1(nil, 0, nil, 0);
|
||||
else
|
||||
w = errorwin1(md->dir, md->ndir, md->incl, md->nincl);
|
||||
if(w != e)
|
||||
winlock(w, owner);
|
||||
winlock(w, owner);
|
||||
if(w->col != nil)
|
||||
break;
|
||||
/* window was deleted too fast */
|
||||
if(w != e)
|
||||
winunlock(w);
|
||||
winunlock(w);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
static void
|
||||
printwarning(Window *ew, Mntdir *md, Rune *r)
|
||||
typedef struct Warning Warning;
|
||||
|
||||
struct Warning{
|
||||
Mntdir *md;
|
||||
Buffer buf;
|
||||
Warning *next;
|
||||
};
|
||||
|
||||
static Warning *warnings;
|
||||
|
||||
static
|
||||
void
|
||||
addwarningtext(Mntdir *md, Rune *r, int nr)
|
||||
{
|
||||
int nr, q0, owner;
|
||||
Warning *warn;
|
||||
|
||||
for(warn = warnings; warn; warn=warn->next){
|
||||
if(warn->md == md){
|
||||
bufinsert(&warn->buf, warn->buf.nc, r, nr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
warn = emalloc(sizeof(Warning));
|
||||
warn->next = warnings;
|
||||
warnings = warn;
|
||||
bufinsert(&warn->buf, 0, r, nr);
|
||||
}
|
||||
|
||||
void
|
||||
flushwarnings(int dolock)
|
||||
{
|
||||
Warning *warn, *next;
|
||||
Window *w;
|
||||
Text *t;
|
||||
int owner, nr, q0, n;
|
||||
Rune *r;
|
||||
|
||||
if(r == nil)
|
||||
error("runevsmprint failed");
|
||||
nr = runestrlen(r);
|
||||
|
||||
if(dolock)
|
||||
qlock(&row.lk);
|
||||
if(row.ncol == 0){ /* really early error */
|
||||
rowinit(&row, screen->clipr);
|
||||
rowadd(&row, nil, -1);
|
||||
rowadd(&row, nil, -1);
|
||||
if(row.ncol == 0)
|
||||
error("initializing columns in warning()");
|
||||
error("initializing columns in flushwarnings()");
|
||||
}
|
||||
|
||||
w = errorwin(md, 'E', ew);
|
||||
t = &w->body;
|
||||
owner = w->owner;
|
||||
if(owner == 0)
|
||||
w->owner = 'E';
|
||||
wincommit(w, t);
|
||||
q0 = textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr);
|
||||
textshow(t, q0, q0+nr, 1);
|
||||
winsettag(t->w);
|
||||
textscrdraw(t);
|
||||
w->owner = owner;
|
||||
w->dirty = FALSE;
|
||||
if(ew != w)
|
||||
for(warn=warnings; warn; warn=next) {
|
||||
w = errorwin(warn->md, 'E');
|
||||
t = &w->body;
|
||||
owner = w->owner;
|
||||
if(owner == 0)
|
||||
w->owner = 'E';
|
||||
wincommit(w, t);
|
||||
/*
|
||||
* Most commands don't generate much output. For instance,
|
||||
* Edit ,>cat goes through /dev/cons and is already in blocks
|
||||
* because of the i/o system, but a few can. Edit ,p will
|
||||
* put the entire result into a single hunk. So it's worth doing
|
||||
* this in blocks (and putting the text in a buffer in the first
|
||||
* place), to avoid a big memory footprint.
|
||||
*/
|
||||
r = fbufalloc();
|
||||
q0 = t->file->b.nc;
|
||||
for(n = 0; n < warn->buf.nc; n += nr){
|
||||
nr = warn->buf.nc - n;
|
||||
if(nr > RBUFSIZE)
|
||||
nr = RBUFSIZE;
|
||||
bufread(&warn->buf, n, r, nr);
|
||||
textbsinsert(t, t->file->b.nc, r, nr, TRUE, &nr);
|
||||
}
|
||||
textshow(t, q0, t->file->b.nc, 1);
|
||||
free(r);
|
||||
winsettag(t->w);
|
||||
textscrdraw(t);
|
||||
w->owner = owner;
|
||||
w->dirty = FALSE;
|
||||
winunlock(w);
|
||||
free(r);
|
||||
bufclose(&warn->buf);
|
||||
next = warn->next;
|
||||
free(warn);
|
||||
}
|
||||
warnings = nil;
|
||||
if(dolock)
|
||||
qunlock(&row.lk);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -153,23 +205,9 @@ warning(Mntdir *md, char *s, ...)
|
|||
va_start(arg, s);
|
||||
r = runevsmprint(s, arg);
|
||||
va_end(arg);
|
||||
printwarning(nil, md, r);
|
||||
}
|
||||
|
||||
/*
|
||||
* Warningew is like warning but avoids locking the error window
|
||||
* if it's already locked by checking that ew!=error window.
|
||||
*/
|
||||
void
|
||||
warningew(Window *ew, Mntdir *md, char *s, ...)
|
||||
{
|
||||
Rune *r;
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, s);
|
||||
r = runevsmprint(s, arg);
|
||||
va_end(arg);
|
||||
printwarning(ew, md, r);
|
||||
if(r == nil)
|
||||
error("runevsmprint failed");
|
||||
addwarningtext(md, r, runestrlen(r));
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ wininit(Window *w, Window *clone, Rectangle r)
|
|||
w->body.w = w;
|
||||
w->id = ++winid;
|
||||
incref(&w->ref);
|
||||
if(globalincref)
|
||||
incref(&w->ref);
|
||||
w->ctlfid = ~0;
|
||||
w->utflastqid = -1;
|
||||
r1 = r;
|
||||
|
|
@ -141,7 +143,7 @@ winlock(Window *w, int owner)
|
|||
int i;
|
||||
File *f;
|
||||
|
||||
fprint(2, "winlock %p %d %lux\n", w, owner, getcallerpc(&w));
|
||||
//fprint(2, "winlock %p %d %lux\n", w, owner, getcallerpc(&w));
|
||||
f = w->body.file;
|
||||
for(i=0; i<f->ntext; i++)
|
||||
winlock1(f->text[i]->w, owner);
|
||||
|
|
@ -153,7 +155,7 @@ winunlock(Window *w)
|
|||
int i;
|
||||
File *f;
|
||||
|
||||
fprint(2, "winunlock %p %lux\n", w, getcallerpc(&w));
|
||||
//fprint(2, "winunlock %p %lux\n", w, getcallerpc(&w));
|
||||
f = w->body.file;
|
||||
for(i=0; i<f->ntext; i++){
|
||||
w = f->text[i]->w;
|
||||
|
|
|
|||
|
|
@ -383,7 +383,7 @@ xfidwrite(Xfid *x)
|
|||
x->fcall.data[x->fcall.count] = 0;
|
||||
switch(qid){
|
||||
case Qcons:
|
||||
w = errorwin(x->f->mntdir, 'X', nil);
|
||||
w = errorwin(x->f->mntdir, 'X');
|
||||
t=&w->body;
|
||||
goto BodyTag;
|
||||
|
||||
|
|
@ -543,6 +543,7 @@ xfidwrite(Xfid *x)
|
|||
}
|
||||
if(w)
|
||||
winunlock(w);
|
||||
flushwarnings(1);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -813,6 +814,7 @@ xfideventwrite(Xfid *x, Window *w)
|
|||
qunlock(&row.lk);
|
||||
goto Rescue;
|
||||
}
|
||||
flushwarnings(0);
|
||||
qunlock(&row.lk);
|
||||
|
||||
}
|
||||
|
|
@ -1030,6 +1032,7 @@ xfidindexread(Xfid *x)
|
|||
b[n++] = '\n';
|
||||
}
|
||||
}
|
||||
flushwarnings(0);
|
||||
qunlock(&row.lk);
|
||||
off = x->fcall.offset;
|
||||
cnt = x->fcall.count;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ PLAN9=../..
|
|||
<$PLAN9/src/mkhdr
|
||||
|
||||
TARG=`ls *.c | sed 's/\.c//'`
|
||||
LDFLAGS=$LDFLAGS -lthread -lsec -lfs -lmux -lregexp9 -lbio -l9 -lfmt -lutf
|
||||
LDFLAGS=$LDFLAGS -lthread -lsec -lfs -lmux -lregexp9 -lbio -l9
|
||||
|
||||
<$PLAN9/src/mkmany
|
||||
|
||||
|
|
|
|||
|
|
@ -99,10 +99,11 @@ extproc(void *argv)
|
|||
c = arg[0];
|
||||
fd = (int)arg[1];
|
||||
|
||||
threadfdnoblock(fd);
|
||||
i = 0;
|
||||
for(;;){
|
||||
i = 1-i; /* toggle */
|
||||
n = read(fd, plumbbuf[i].data, sizeof plumbbuf[i].data);
|
||||
n = threadread(fd, plumbbuf[i].data, sizeof plumbbuf[i].data);
|
||||
if(n <= 0){
|
||||
fprint(2, "samterm: extern read error: %r\n");
|
||||
threadexits("extern"); /* not a fatal error */
|
||||
|
|
@ -165,7 +166,7 @@ extstart(void)
|
|||
plumbc = chancreate(sizeof(int), 0);
|
||||
arg[0] = plumbc;
|
||||
arg[1] = (void*)fd;
|
||||
proccreate(extproc, arg, STACK);
|
||||
threadcreate(extproc, arg, STACK);
|
||||
atexit(removeextern);
|
||||
}
|
||||
|
||||
|
|
@ -226,9 +227,10 @@ plumbproc(void *argv)
|
|||
fdp = arg[1];
|
||||
|
||||
i = 0;
|
||||
threadfdnoblock(*fdp);
|
||||
for(;;){
|
||||
i = 1-i; /* toggle */
|
||||
n = read(*fdp, plumbbuf[i].data, READBUFSIZE);
|
||||
n = threadread(*fdp, plumbbuf[i].data, READBUFSIZE);
|
||||
if(n <= 0){
|
||||
fprint(2, "samterm: plumb read error: %r\n");
|
||||
threadexits("plumb"); /* not a fatal error */
|
||||
|
|
@ -258,7 +260,7 @@ plumbstart(void)
|
|||
}
|
||||
arg[0] =plumbc;
|
||||
arg[1] = &fd;
|
||||
proccreate(plumbproc, arg, STACK);
|
||||
threadcreate(plumbproc, arg, STACK);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -278,9 +280,10 @@ hostproc(void *arg)
|
|||
c = arg;
|
||||
|
||||
i = 0;
|
||||
threadfdnoblock(hostfd[0]);
|
||||
for(;;){
|
||||
i = 1-i; /* toggle */
|
||||
n = read(hostfd[0], hostbuf[i].data, sizeof hostbuf[i].data);
|
||||
n = threadread(hostfd[0], hostbuf[i].data, sizeof hostbuf[i].data);
|
||||
if(n <= 0){
|
||||
fprint(2, "samterm: host read error: %r\n");
|
||||
threadexitsall("host");
|
||||
|
|
@ -295,5 +298,5 @@ void
|
|||
hoststart(void)
|
||||
{
|
||||
hostc = chancreate(sizeof(int), 0);
|
||||
proccreate(hostproc, hostc, STACK);
|
||||
threadcreate(hostproc, hostc, STACK);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue