diff options
author | rsc <devnull@localhost> | 2004-02-29 22:10:26 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-02-29 22:10:26 +0000 |
commit | 5a8e63b2f016735364d17866d5e2bcb35d20c78b (patch) | |
tree | d5d0ce11e087efaf81c77311bac9d30aed41783d /src/cmd | |
parent | d51419bf4397cf13d0c50bf84c125477c6bed307 (diff) | |
download | plan9port-5a8e63b2f016735364d17866d5e2bcb35d20c78b.tar.gz plan9port-5a8e63b2f016735364d17866d5e2bcb35d20c78b.tar.bz2 plan9port-5a8e63b2f016735364d17866d5e2bcb35d20c78b.zip |
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.
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/9pserve.c | 184 | ||||
-rw-r--r-- | src/cmd/acme/acme.c | 62 | ||||
-rw-r--r-- | src/cmd/acme/dat.h | 5 | ||||
-rw-r--r-- | src/cmd/acme/ecmd.c | 7 | ||||
-rw-r--r-- | src/cmd/acme/exec.c | 74 | ||||
-rw-r--r-- | src/cmd/acme/fns.h | 5 | ||||
-rw-r--r-- | src/cmd/acme/fsys.c | 11 | ||||
-rw-r--r-- | src/cmd/acme/look.c | 76 | ||||
-rw-r--r-- | src/cmd/acme/mkfile | 4 | ||||
-rw-r--r-- | src/cmd/acme/text.c | 50 | ||||
-rw-r--r-- | src/cmd/acme/time.c | 4 | ||||
-rw-r--r-- | src/cmd/acme/util.c | 130 | ||||
-rw-r--r-- | src/cmd/acme/wind.c | 6 | ||||
-rw-r--r-- | src/cmd/acme/xfid.c | 5 | ||||
-rw-r--r-- | src/cmd/mkfile | 2 | ||||
-rw-r--r-- | src/cmd/samterm/plan9.c | 15 |
16 files changed, 364 insertions, 276 deletions
diff --git a/src/cmd/9pserve.c b/src/cmd/9pserve.c index eb2df758..16fca61e 100644 --- a/src/cmd/9pserve.c +++ b/src/cmd/9pserve.c @@ -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; } diff --git a/src/cmd/acme/acme.c b/src/cmd/acme/acme.c index 0ac66e12..87924caa 100644 --- a/src/cmd/acme/acme.c +++ b/src/cmd/acme/acme.c @@ -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) - return; - if(snarffd < 0) + s = getsnarf(); + if(s == nil || s[0]==0){ + free(s); 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); } diff --git a/src/cmd/acme/dat.h b/src/cmd/acme/dat.h index b2a443da..9101ca34 100644 --- a/src/cmd/acme/dat.h +++ b/src/cmd/acme/dat.h @@ -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*) */ diff --git a/src/cmd/acme/ecmd.c b/src/cmd/acme/ecmd.c index 677bafb1..0dfae90a 100644 --- a/src/cmd/acme/ecmd.c +++ b/src/cmd/acme/ecmd.c @@ -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; diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c index 9c29dc1a..d81153ec 100644 --- a/src/cmd/acme/exec.c +++ b/src/cmd/acme/exec.c @@ -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; diff --git a/src/cmd/acme/fns.h b/src/cmd/acme/fns.h index 69bbbb3b..a73a7ec0 100644 --- a/src/cmd/acme/fns.h +++ b/src/cmd/acme/fns.h @@ -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)) diff --git a/src/cmd/acme/fsys.c b/src/cmd/acme/fsys.c index d220bdef..f178f864 100644 --- a/src/cmd/acme/fsys.c +++ b/src/cmd/acme/fsys.c @@ -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); diff --git a/src/cmd/acme/look.c b/src/cmd/acme/look.c index 9f54f9e4..ca7eba42 100644 --- a/src/cmd/acme/look.c +++ b/src/cmd/acme/look.c @@ -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 }; - - 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}; + char *s; + int nb, nulls; + + 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; diff --git a/src/cmd/acme/mkfile b/src/cmd/acme/mkfile index cb72fea0..86a3fbde 100644 --- a/src/cmd/acme/mkfile +++ b/src/cmd/acme/mkfile @@ -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 diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c index 0b9f7cc6..8bdf0b78 100644 --- a/src/cmd/acme/text.c +++ b/src/cmd/acme/text.c @@ -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++){ diff --git a/src/cmd/acme/time.c b/src/cmd/acme/time.c index b281d68d..f80891a4 100644 --- a/src/cmd/acme/time.c +++ b/src/cmd/acme/time.c @@ -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* diff --git a/src/cmd/acme/util.c b/src/cmd/acme/util.c index 8e3cfa29..180b2bd2 100644 --- a/src/cmd/acme/util.c +++ b/src/cmd/acme/util.c @@ -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 diff --git a/src/cmd/acme/wind.c b/src/cmd/acme/wind.c index 06a815e9..90c44070 100644 --- a/src/cmd/acme/wind.c +++ b/src/cmd/acme/wind.c @@ -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; diff --git a/src/cmd/acme/xfid.c b/src/cmd/acme/xfid.c index 13af7395..b3bef2cd 100644 --- a/src/cmd/acme/xfid.c +++ b/src/cmd/acme/xfid.c @@ -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; diff --git a/src/cmd/mkfile b/src/cmd/mkfile index f6365ac0..6e4c218b 100644 --- a/src/cmd/mkfile +++ b/src/cmd/mkfile @@ -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 diff --git a/src/cmd/samterm/plan9.c b/src/cmd/samterm/plan9.c index f49393e6..60ef5c0e 100644 --- a/src/cmd/samterm/plan9.c +++ b/src/cmd/samterm/plan9.c @@ -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); } |