aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-02-29 22:10:26 +0000
committerrsc <devnull@localhost>2004-02-29 22:10:26 +0000
commit5a8e63b2f016735364d17866d5e2bcb35d20c78b (patch)
treed5d0ce11e087efaf81c77311bac9d30aed41783d /src/cmd
parentd51419bf4397cf13d0c50bf84c125477c6bed307 (diff)
downloadplan9port-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.c184
-rw-r--r--src/cmd/acme/acme.c62
-rw-r--r--src/cmd/acme/dat.h5
-rw-r--r--src/cmd/acme/ecmd.c7
-rw-r--r--src/cmd/acme/exec.c74
-rw-r--r--src/cmd/acme/fns.h5
-rw-r--r--src/cmd/acme/fsys.c11
-rw-r--r--src/cmd/acme/look.c76
-rw-r--r--src/cmd/acme/mkfile4
-rw-r--r--src/cmd/acme/text.c50
-rw-r--r--src/cmd/acme/time.c4
-rw-r--r--src/cmd/acme/util.c130
-rw-r--r--src/cmd/acme/wind.c6
-rw-r--r--src/cmd/acme/xfid.c5
-rw-r--r--src/cmd/mkfile2
-rw-r--r--src/cmd/samterm/plan9.c15
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);
}