From 8ad517944e46710ab832350c0dc3fc4e9239f7e2 Mon Sep 17 00:00:00 2001 From: rsc Date: Thu, 25 Mar 2004 23:03:57 +0000 Subject: Today's changes. More changes. --- src/cmd/9pserve.c | 2 +- src/cmd/9term/9term.c | 456 +++++++++++++++---------- src/cmd/9term/9term.h | 21 +- src/cmd/9term/FreeBSD.c | 40 ++- src/cmd/9term/Linux.c | 48 ++- src/cmd/9term/SunOS.c | 37 ++- src/cmd/9term/mkfile | 8 +- src/cmd/9term/rcstart.c | 51 +++ src/cmd/9term/term.h | 5 + src/cmd/9term/win.c | 693 ++++++++++++++++++++++++++++++++++++++ src/cmd/acme/acme.c | 24 +- src/cmd/acme/dat.h | 1 + src/cmd/acme/ecmd.c | 2 +- src/cmd/acme/exec.c | 4 +- src/cmd/acme/fns.h | 5 +- src/cmd/acme/fsys.c | 44 ++- src/cmd/acme/look.c | 12 +- src/cmd/acme/text.c | 2 +- src/cmd/acme/util.c | 23 +- src/cmd/acme/xfid.c | 3 - src/cmd/dict/dict.c | 2 + src/cmd/diff/diff.h | 2 + src/cmd/diff/main.c | 2 + src/cmd/fortune.c | 8 +- src/cmd/grep/comp.c | 277 ++++++++++++++++ src/cmd/grep/grep.h | 125 +++++++ src/cmd/grep/grep.y | 226 +++++++++++++ src/cmd/grep/main.c | 260 +++++++++++++++ src/cmd/grep/mkfile | 20 ++ src/cmd/grep/sub.c | 317 ++++++++++++++++++ src/cmd/mkfile | 4 +- src/cmd/plumb/fsys.c | 1 + src/cmd/plumb/plumber.c | 7 +- src/cmd/plumb/rules.c | 2 +- src/cmd/rc/plan9ish.c | 14 +- src/cmd/rio/Imakefile | 27 ++ src/cmd/rio/color.c | 2 +- src/cmd/rio/main.c | 13 +- src/cmd/rio/mkfile | 5 + src/cmd/spell/sprog.c | 3 + src/cmd/win.c | 717 ---------------------------------------- src/cmd/yacc.c | 2 +- src/lib9/_p9translate.c | 4 +- src/lib9/access.c | 19 -- src/lib9/announce.c | 5 +- src/lib9/create.c | 10 +- src/lib9/ctime.c | 7 + src/lib9/date.c | 12 +- src/lib9/dirread.c | 4 +- src/lib9/errstr.c | 3 +- src/lib9/ffork-OpenBSD.c | 1 + src/lib9/getuser.c | 3 +- src/lib9/lock.c | 3 +- src/lib9/mallocz.c | 3 +- src/lib9/mkfile | 4 +- src/lib9/notify.c | 3 +- src/lib9/open.c | 9 +- src/lib9/rendez-Linux.c | 2 + src/lib9/rendez-OpenBSD.c | 1 + src/lib9/rendez-pthread.c | 3 +- src/lib9/time.c | 4 +- src/libdraw/openfont.c | 4 +- src/libdraw/x11-init.c | 23 +- src/libdraw/x11-itrans.c | 3 + src/libplumb/mesg.c | 1 - src/libthread/asm-OpenBSD-386.s | 49 +++ src/libthread/exec-unix.c | 41 ++- src/libthread/label.h | 2 +- src/mkfile | 2 +- 69 files changed, 2650 insertions(+), 1092 deletions(-) create mode 100644 src/cmd/9term/rcstart.c create mode 100644 src/cmd/9term/term.h create mode 100644 src/cmd/9term/win.c create mode 100644 src/cmd/grep/comp.c create mode 100644 src/cmd/grep/grep.h create mode 100644 src/cmd/grep/grep.y create mode 100644 src/cmd/grep/main.c create mode 100644 src/cmd/grep/mkfile create mode 100644 src/cmd/grep/sub.c create mode 100644 src/cmd/rio/Imakefile delete mode 100644 src/cmd/win.c delete mode 100644 src/lib9/access.c create mode 100644 src/lib9/ffork-OpenBSD.c create mode 100644 src/lib9/rendez-OpenBSD.c create mode 100644 src/libthread/asm-OpenBSD-386.s (limited to 'src') diff --git a/src/cmd/9pserve.c b/src/cmd/9pserve.c index 8acd5524..644385c1 100644 --- a/src/cmd/9pserve.c +++ b/src/cmd/9pserve.c @@ -1150,7 +1150,7 @@ rewritehdr(Fcall *f, uchar *pkt) } } -#ifdef _LIB9_H_ +#ifdef _LIBC_H_ /* unix select-based polling */ struct Ioproc { diff --git a/src/cmd/9term/9term.c b/src/cmd/9term/9term.c index c5a2c424..50c0cfc9 100644 --- a/src/cmd/9term/9term.c +++ b/src/cmd/9term/9term.c @@ -1,15 +1,24 @@ -#include "9term.h" - -#define fatal sysfatal +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "term.h" typedef struct Text Text; typedef struct Readbuf Readbuf; enum { - /* these are chosen to use malloc()'s properties well */ HiWater = 640000, /* max size of history */ - LoWater = 330000, /* min size of history after max'ed */ + LoWater = 400000, /* min size of history after max'ed */ + MinWater = 20000, }; /* various geometric paramters */ @@ -30,21 +39,22 @@ enum Scroll, }; - -#define SCROLLKEY Kdown #define ESC 0x1B -#define CUT 0x18 /* ctrl-x */ -#define COPY 0x03 /* crtl-c */ -#define PASTE 0x16 /* crtl-v */ -#define BACKSCROLLKEY Kup +#define CUT 0x18 /* ctrl-x */ +#define COPY 0x03 /* crtl-c */ +#define PASTE 0x16 /* crtl-v */ #define READBUFSIZE 8192 +#define TRUE 1 +#define FALSE 0 + struct Text { Frame *f; /* frame ofr terminal */ Mouse m; uint nr; /* num of runes in term */ + uint maxr; /* max num of runes in r */ Rune *r; /* runes for term */ uint nraw; /* num of runes in raw buffer */ Rune *raw; /* raw buffer */ @@ -72,7 +82,6 @@ void fill(void); void tcheck(void); void updatesel(void); void doreshape(void); -void rcstart(int fd[2], int, char**); void runewrite(Rune*, int); void consread(void); void conswrite(char*, int); @@ -99,11 +108,10 @@ void scrdraw(void); void scroll(int); void hostproc(void *arg); void hoststart(void); -int getchildwd(int, char*, int); void plumbstart(void); void plumb(uint, uint); void plumbclick(uint*, uint*); -int getpts(int fd[], char *slave); +uint insert(Rune*, int, uint, int); #define runemalloc(n) malloc((n)*sizeof(Rune)) #define runerealloc(a, n) realloc(a, (n)*sizeof(Rune)) @@ -115,7 +123,7 @@ int rawon; /* raw mode */ int scrolling; /* window scrolls */ int clickmsec; /* time of last click */ uint clickq0; /* point of last click */ -int rcfd[2]; +int rcfd; int rcpid; int maxtab; int use9wm; @@ -211,7 +219,7 @@ threadmain(int argc, char *argv[]) mc = initmouse(nil, screen); kc = initkeyboard(nil); - rcstart(rcfd, argc, argv); + rcpid = rcstart(argc, argv, &rcfd); hoststart(); plumbstart(); @@ -265,8 +273,9 @@ hostproc(void *arg) i = 0; for(;;){ + /* Let typing have a go -- maybe there's a rubout waiting. */ i = 1-i; /* toggle */ - n = threadread(rcfd[0], rcbuf[i].data, sizeof rcbuf[i].data); + n = threadread(rcfd, rcbuf[i].data, sizeof rcbuf[i].data); if(n <= 0){ if(n < 0) fprint(2, "9term: host read error: %r\n"); @@ -308,7 +317,7 @@ loop(void) a[2].op = CHANNOP;; switch(alt(a)) { default: - fatal("impossible"); + sysfatal("impossible"); case 0: t.m = mc->m; mouse(); @@ -330,23 +339,23 @@ void doreshape(void) { if(getwindow(display, Refnone) < 0) - fatal("can't reattach to window"); + sysfatal("can't reattach to window"); draw(screen, screen->r, cols[BACK], nil, ZP); geom(); scrdraw(); } -struct winsize ows; - void geom(void) { - struct winsize ws; Point p; Rectangle r; r = screen->r; - scrollr = screen->r; + r.min.y++; + r.max.y--; + + scrollr = r; scrollr.max.x = r.min.x+Scrollwid; lastsr = Rect(0,0,0,0); @@ -362,13 +371,7 @@ geom(void) if(p.x == 0 || p.y == 0) return; - ws.ws_row = Dy(r)/p.y; - ws.ws_col = Dx(r)/p.x; - ws.ws_xpixel = Dx(r); - ws.ws_ypixel = Dy(r); - if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col) - if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0) - fprint(2, "ioctl: %r\n"); + updatewinsize(Dy(r)/p.y, Dx(r)/p.x, Dx(r), Dy(r)); } void @@ -585,7 +588,10 @@ domenu2(int but) show(t.q0); break; case Send: - snarf(); + if(t.q0 != t.q1) + snarf(); + else + snarfupdate(); t.q0 = t.q1 = t.nr; updatesel(); paste(t.snarf, t.nsnarf, 1); @@ -605,37 +611,182 @@ domenu2(int but) plumb(t.q0, t.q1); break; default: - fatal("bad menu item"); + sysfatal("bad menu item"); + } +} + +int +windfilewidth(uint q0, int oneelement) +{ + uint q; + Rune r; + + q = q0; + while(q > 0){ + r = t.r[q-1]; + if(r<=' ') + break; + if(oneelement && r=='/') + break; + --q; + } + return q0-q; +} + +void +showcandidates(Completion *c) +{ + int i; + Fmt f; + Rune *rp; + uint nr, qline, q0; + char *s; + + runefmtstrinit(&f); + if (c->nmatch == 0) + s = "[no matches in "; + else + s = "["; + if(c->nfile > 32) + fmtprint(&f, "%s%d files]\n", s, c->nfile); + else{ + fmtprint(&f, "%s", s); + for(i=0; infile; i++){ + if(i > 0) + fmtprint(&f, " "); + fmtprint(&f, "%s", c->filename[i]); + } + fmtprint(&f, "]\n"); + } + /* place text at beginning of line before host point */ + qline = t.qh; + while(qline>0 && t.r[qline-1] != '\n') + qline--; + + rp = runefmtstrflush(&f); + nr = runestrlen(rp); + + q0 = t.q0; + q0 += insert(rp, nr, qline, 0) - qline; + free(rp); + t.q0 = q0+nr; + t.q1 = q0+nr; + updatesel(); +} + +Rune* +namecomplete(void) +{ + int nstr, npath; + Rune *rp, *path, *str; + Completion *c; + char *s, *dir, *root; + + /* control-f: filename completion; works back to white space or / */ + if(t.q0' ') /* must be at end of word */ + return nil; + nstr = windfilewidth(t.q0, TRUE); + str = runemalloc(nstr); + runemove(str, t.r+(t.q0-nstr), nstr); + npath = windfilewidth(t.q0-nstr, FALSE); + path = runemalloc(npath); + runemove(path, t.r+(t.q0-nstr-npath), npath); + rp = nil; + + /* is path rooted? if not, we need to make it relative to window path */ + if(npath>0 && path[0]=='/'){ + dir = malloc(UTFmax*npath+1); + sprint(dir, "%.*S", npath, path); + }else{ + if(strcmp(wdir, "") == 0) + root = "."; + else + root = wdir; + dir = malloc(strlen(root)+1+UTFmax*npath+1); + sprint(dir, "%s/%.*S", root, npath, path); } + dir = cleanname(dir); + + s = smprint("%.*S", nstr, str); + c = complete(dir, s); + free(s); + if(c == nil) + goto Return; + + if(!c->advance) + showcandidates(c); + + if(c->advance) + rp = runesmprint("%s", c->string); + + Return: + freecompletion(c); + free(dir); + free(path); + free(str); + return rp; } void key(Rune r) { - uint sig; + Rune *rp; + int nr; if(r == 0) return; - if(r==SCROLLKEY){ /* scroll key */ + switch(r){ + case Kpgup: + setorigin(backnl(t.org, t.f->maxlines*2/3), 1); + return; + case Kpgdown: setorigin(line2q(t.f->maxlines*2/3), 1); if(t.qh<=t.org+t.f->nchars) consread(); return; - }else if(r == BACKSCROLLKEY){ - setorigin(backnl(t.org, t.f->maxlines*2/3), 1); + case Kup: + setorigin(backnl(t.org, t.f->maxlines/3), 1); + return; + case Kdown: + setorigin(line2q(t.f->maxlines/3), 1); + if(t.qh<=t.org+t.f->nchars) + consread(); return; - }else if(r == CUT){ + case Kleft: + if(t.q0 > 0){ + t.q0--; + t.q1 = t.q0; + updatesel(); + show(t.q0); + } + return; + case Kright: + if(t.q1 < t.nr){ + t.q1++; + t.q0 = t.q1; + updatesel(); + show(t.q1); + } + return; + case Khome: + show(0); + return; + case Kend: + case 0x05: + show(t.nr); + return; + case CUT: snarf(); cut(); if(scrolling) show(t.q0); return; - }else if(r == COPY){ + case COPY: snarf(); if(scrolling) show(t.q0); return; - }else if(r == PASTE){ + case PASTE: snarfupdate(); paste(t.snarf, t.nsnarf, 0); if(scrolling) @@ -661,19 +812,21 @@ key(Rune r) snarf(); switch(r) { + case 0x03: /* ^C: send interrupt */ case 0x7F: /* DEL: send interrupt */ t.qh = t.q0 = t.q1 = t.nr; show(t.q0); - goto Default; -fprint(2, "send interrupt to %d group\n", rcpid); -#ifdef TIOCSIG - sig = 2; /* SIGINT */ - if(ioctl(rcfd[0], TIOCSIG, &sig) < 0) - fprint(2, "sending interrupt: %r\n"); -#else - postnote(PNGROUP, rcpid, "interrupt"); -#endif + write(rcfd, "\x7F", 1); break; + case 0x06: /* ^F: file name completion */ + case Kins: /* Insert: file name completion */ + rp = namecomplete(); + if(rp == nil) + return; + nr = runestrlen(rp); + paste(rp, nr, 1); + free(rp); + return; case 0x08: /* ^H: erase character */ case 0x15: /* ^U: erase line */ case 0x17: /* ^W: erase word */ @@ -682,7 +835,6 @@ fprint(2, "send interrupt to %d group\n", rcpid); cut(); break; default: - Default: paste(&r, 1, 1); break; } @@ -773,7 +925,7 @@ consread(void) } /* take out control-d when not doing a zero length write */ n = p-buf; - if(write(rcfd[1], buf, n) < 0) + if(write(rcfd, buf, n) < 0) exits(0); /* mallocstats(); */ } @@ -833,7 +985,6 @@ conswrite(char *p, int n) void runewrite(Rune *r, int n) { - uint m; int i; uint initial; uint q0, q1; @@ -896,37 +1047,7 @@ runewrite(Rune *r, int n) updatesel(); } - if(t.nr>HiWater && t.qh>=t.org){ - m = HiWater-LoWater; - if(m > t.org); - m = t.org; - t.org -= m; - t.qh -= m; - if(t.q0 > m) - t.q0 -= m; - else - t.q0 = 0; - if(t.q1 > m) - t.q1 -= m; - else - t.q1 = 0; - t.nr -= m; - runemove(t.r, t.r+m, t.nr); - } - t.r = runerealloc(t.r, t.nr+n); - runemove(t.r+t.qh+n, t.r+t.qh, t.nr-t.qh); - runemove(t.r+t.qh, r, n); - t.nr += n; - if(t.qh < t.org) - t.org += n; - else if(t.qh <= t.f->nchars+t.org) - frinsert(t.f, r, r+n, t.qh-t.org); - if (t.qh <= t.q0) - t.q0 += n; - if (t.qh <= t.q1) - t.q1 += n; - t.qh += n; - updatesel(); + insert(r, n, t.qh, 1); } @@ -1009,12 +1130,83 @@ snarf(void) putsnarf(sbuf); } +uint +min(uint x, uint y) +{ + if(x < y) + return x; + return y; +} + +uint +max(uint x, uint y) +{ + if(x > y) + return x; + return y; +} + +uint +insert(Rune *r, int n, uint q0, int hostwrite) +{ + uint m; + + if(n == 0) + return q0; + if(t.nr+n>HiWater && q0>=t.org && q0>=t.qh){ + m = min(HiWater-LoWater, min(t.org, t.qh)); + t.org -= m; + t.qh -= m; + if(t.q0 > m) + t.q0 -= m; + else + t.q0 = 0; + if(t.q1 > m) + t.q1 -= m; + else + t.q1 = 0; + t.nr -= m; + runemove(t.r, t.r+m, t.nr); + q0 -= m; + } + if(t.nr+n > t.maxr){ + /* + * Minimize realloc breakage: + * Allocate at least MinWater + * Double allocation size each time + * But don't go much above HiWater + */ + m = max(min(2*(t.nr+n), HiWater), t.nr+n)+MinWater; + if(m > HiWater) + m = max(HiWater+MinWater, t.nr+n); + if(m > t.maxr){ + t.r = runerealloc(t.r, m); + t.maxr = m; + } + } + runemove(t.r+q0+n, t.r+q0, t.nr-q0); + runemove(t.r+q0, r, n); + t.nr += n; + /* if output touches, advance selection, not qh; works best for keyboard and output */ + if(q0 <= t.q1) + t.q1 += n; + if(q0 <= t.q0) + t.q0 += n; + if(q0 < t.qh || (q0==t.qh && hostwrite)) + t.qh += n; + else + consread(); + if(q0 < t.org) + t.org += n; + else if(q0 <= t.org+t.f->nchars) + frinsert(t.f, r, r+n, q0-t.org); + return q0; +} + void paste(Rune *r, int n, int advance) { Rune *rbuf; - uint m; - uint q0; if(rawon && t.q0==t.nr){ addraw(r, n); @@ -1024,6 +1216,7 @@ paste(Rune *r, int n, int advance) cut(); if(n == 0) return; + /* * if this is a button2 execute then we might have been passed * runes inside the buffer. must save them before realloc. @@ -1035,36 +1228,7 @@ paste(Rune *r, int n, int advance) r = rbuf; } - if(t.nr>HiWater && t.q0>=t.org && t.q0>=t.qh){ - m = HiWater-LoWater; - if(m > t.org) - m = t.org; - if(m > t.qh); - m = t.qh; - t.org -= m; - t.qh -= m; - t.q0 -= m; - t.q1 -= m; - t.nr -= m; - runemove(t.r, t.r+m, t.nr); - } - - t.r = runerealloc(t.r, t.nr+n); - q0 = t.q0; - runemove(t.r+q0+n, t.r+q0, t.nr-q0); - runemove(t.r+q0, r, n); - t.nr += n; - if(q0 < t.qh) - t.qh += n; - else - consread(); - if(q0 < t.org) - t.org += n; - else if(q0 <= t.f->nchars+t.org) - frinsert(t.f, r, r+n, q0-t.org); - if(advance) - t.q0 += n; - t.q1 += n; + insert(r, n, t.q0, 0); updatesel(); free(rbuf); } @@ -1321,61 +1485,6 @@ clickmatch(int cl, int cr, int dir, uint *q) return cl=='\n' && nest==1; } -void -rcstart(int fd[2], int argc, char **argv) -{ - int pid; - char *xargv[3]; - char slave[256]; - int sfd; - - if(argc == 0){ - argc = 2; - argv = xargv; - argv[0] = getenv("SHELL"); - if(argv[0] == 0) - argv[0] = "rc"; - argv[1] = "-i"; - argv[2] = 0; - } - /* - * fd0 is slave (tty), fd1 is master (pty) - */ - fd[0] = fd[1] = -1; - if(getpts(fd, slave) < 0) - fprint(2, "getpts: %r\n"); - - switch(pid = fork()) { - case 0: - putenv("TERM", "9term"); - close(fd[1]); - setsid(); -// tcsetpgrp(0, pid); - sfd = open(slave, ORDWR); - if(sfd < 0) - fprint(2, "open %s: %r\n", slave); - if(ioctl(sfd, TIOCSCTTY, 0) < 0) - fprint(2, "ioctl TIOCSCTTY: %r\n"); -// ioctl(sfd, I_PUSH, "ptem"); -// ioctl(sfd, I_PUSH, "ldterm"); - dup(sfd, 0); - dup(sfd, 1); - dup(sfd, 2); - system("stty tabs -onlcr -echo erase ^h intr ^?"); - execvp(argv[0], argv); - fprint(2, "exec %s failed: %r\n", argv[0]); - _exits("oops"); - break; - case -1: - fatal("proc failed: %r"); - break; - } - close(fd[0]); - fd[0] = fd[1]; - - rcpid = pid; -} - void tcheck(void) { @@ -1421,7 +1530,7 @@ scrdraw(void) freeimage(scrx); scrx = allocimage(display, Rect(0, 0, 32, r.max.y), screen->chan, 1, DPaleyellow); if(scrx == 0) - fatal("scroll balloc"); + sysfatal("scroll balloc"); } r1.min.x = 0; r1.max.x = Dx(r); @@ -1525,16 +1634,11 @@ plumb(uint q0, uint q1) char *p; int i, p0, n; char cbuf[100]; - char *w; - if(getchildwd(rcpid, childwdir, sizeof childwdir) == 0) - w = childwdir; - else - w = wdir; pm = malloc(sizeof(Plumbmsg)); pm->src = strdup("9term"); pm->dst = 0; - pm->wdir = strdup(w); + pm->wdir = strdup(wdir); pm->type = strdup("text"); pm->data = nil; if(q1 > q0) diff --git a/src/cmd/9term/9term.h b/src/cmd/9term/9term.h index 4e8d61f3..57a8359e 100644 --- a/src/cmd/9term/9term.h +++ b/src/cmd/9term/9term.h @@ -1,19 +1,4 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __linux__ -#include -#endif - -extern int getchildwd(int, char*, int); extern int getpts(int[], char*); - +extern int childpty(int[], char*); +extern void updatewinsize(int, int, int, int); +extern int rcfd[]; diff --git a/src/cmd/9term/FreeBSD.c b/src/cmd/9term/FreeBSD.c index e8b894dc..7022d4d9 100644 --- a/src/cmd/9term/FreeBSD.c +++ b/src/cmd/9term/FreeBSD.c @@ -1,17 +1,43 @@ #include "9term.h" +#include +#include #include int -getchildwd(int pid, char *wdir, int bufn) +getpts(int fd[], char *slave) { - USED(pid); - USED(wdir); - USED(bufn); - return -1; + return openpty(&fd[1], &fd[0], slave, 0, 0); } int -getpts(int fd[], char *slave) +childpty(int fd[], char *slave) { - return openpty(&fd[1], &fd[0], slave, 0, 0); + int sfd; + + close(fd[1]); + setsid(); + sfd = open(slave, ORDWR); + if(sfd < 0) + sysfatal("open %s: %r\n", slave); + if(ioctl(sfd, TIOCSCTTY, 0) < 0) + fprint(2, "ioctl TIOCSCTTY: %r\n"); + return sfd; } + +struct winsize ows; + +void +updatewinsize(int row, int col, int dx, int dy) +{ + struct winsize ws; + + ws.ws_row = row; + ws.ws_col = col; + ws.ws_xpixel = dx; + ws.ws_ypixel = dy; + if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col) + if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0) + fprint(2, "ioctl: %r\n"); + ows = ws; +} + diff --git a/src/cmd/9term/Linux.c b/src/cmd/9term/Linux.c index 7dd22371..872417e6 100644 --- a/src/cmd/9term/Linux.c +++ b/src/cmd/9term/Linux.c @@ -1,22 +1,46 @@ +#include +#include +#include +#include +#include #include "9term.h" int -getchildwd(int pid, char *wdir, int bufn) +getpts(int fd[], char *slave) { - char path[256]; - int n; - - snprint(path, sizeof path, "/proc/%d/cwd", pid); - n = readlink(path, wdir, bufn); - if(n < 0) - return -1; - wdir[n] = '\0'; + openpty(&fd[1], &fd[0], slave, 0, 0); return 0; } int -getpts(int fd[], char *slave) +childpty(int fd[], char *slave) { - openpty(&fd[1], &fd[0], slave, 0, 0); - return 0; + int sfd; + + close(fd[1]); + setsid(); + sfd = open(slave, ORDWR); + if(sfd < 0) + sysfatal("open %s: %r\n", slave); + if(ioctl(sfd, TIOCSCTTY, 0) < 0) + fprint(2, "ioctl TIOCSCTTY: %r\n"); + return sfd; } + +struct winsize ows; + +void +updatewinsize(int row, int col, int dx, int dy) +{ + struct winsize ws; + + ws.ws_row = row; + ws.ws_col = col; + ws.ws_xpixel = dx; + ws.ws_ypixel = dy; + if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col) + if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0) + fprint(2, "ioctl: %r\n"); + ows = ws; +} + diff --git a/src/cmd/9term/SunOS.c b/src/cmd/9term/SunOS.c index 6a37ab33..d7db9fc5 100644 --- a/src/cmd/9term/SunOS.c +++ b/src/cmd/9term/SunOS.c @@ -1,21 +1,6 @@ #include "9term.h" - -int -getchildwd(int pid, char *wdir, int bufn) -{ - char path[256]; - char cwd[256]; - - if(getcwd(cwd, sizeof cwd) < 0) - return -1; - snprint(path, sizeof path, "/proc/%d/cwd", pid); - if(chdir(path) < 0) - return -1; - if(getcwd(wdir, bufn) < 0) - return -1; - chdir(cwd); - return 0; -} +#include +#include int getpts(int fd[], char *slave) @@ -28,3 +13,21 @@ getpts(int fd[], char *slave) fd[0] = open(slave, OREAD); return 0; } + +struct winsize ows; + +void +updatewinsize(int row, int col, int dx, int dy) +{ + struct winsize ws; + + ws.ws_row = row; + ws.ws_col = col; + ws.ws_xpixel = dx; + ws.ws_ypixel = dy; + if(ws.ws_row != ows.ws_row || ws.ws_col != ows.ws_col) + if(ioctl(rcfd[0], TIOCSWINSZ, &ws) < 0) + fprint(2, "ioctl: %r\n"); + ows = ws; +} + diff --git a/src/cmd/9term/mkfile b/src/cmd/9term/mkfile index d0d5ca72..8701ad9c 100644 --- a/src/cmd/9term/mkfile +++ b/src/cmd/9term/mkfile @@ -1,15 +1,15 @@ PLAN9=../../.. <$PLAN9/src/mkhdr -TARG=9term +TARG=9term win OFILES=\ - 9term.$O\ + rcstart.$O\ $SYSNAME.$O\ -SHORTLIB=frame draw plumb fs mux thread 9 +SHORTLIB=complete frame draw plumb fs mux thread 9 -<$PLAN9/src/mkone +<$PLAN9/src/mkmany LDFLAGS=-L$X11/lib -lX11 -lutil diff --git a/src/cmd/9term/rcstart.c b/src/cmd/9term/rcstart.c new file mode 100644 index 00000000..7596bc41 --- /dev/null +++ b/src/cmd/9term/rcstart.c @@ -0,0 +1,51 @@ +#include +#include +#include "term.h" + +int +rcstart(int argc, char **argv, int *pfd) +{ + int pid; + int fd[2]; + char *xargv[3]; + char slave[256]; + int sfd; + + if(argc == 0){ + argc = 2; + argv = xargv; + argv[0] = getenv("SHELL"); + if(argv[0] == 0) + argv[0] = "rc"; + argv[1] = "-i"; + argv[2] = 0; + } + /* + * fd0 is slave (tty), fd1 is master (pty) + */ + fd[0] = fd[1] = -1; + if(getpts(fd, slave) < 0) + fprint(2, "getpts: %r\n"); + + + switch(pid = fork()) { + case 0: + putenv("TERM", "9term"); + sfd = childpty(fd, slave); + dup(sfd, 0); + dup(sfd, 1); + dup(sfd, 2); + system("stty tabs -onlcr -echo erase ^h intr ^?"); + execvp(argv[0], argv); + fprint(2, "exec %s failed: %r\n", argv[0]); + _exits("oops"); + break; + case -1: + sysfatal("proc failed: %r"); + break; + } + close(fd[0]); + *pfd = fd[1]; + return pid; +} + diff --git a/src/cmd/9term/term.h b/src/cmd/9term/term.h new file mode 100644 index 00000000..a608b7ed --- /dev/null +++ b/src/cmd/9term/term.h @@ -0,0 +1,5 @@ +extern int getpts(int[], char*); +extern int childpty(int[], char*); +extern void updatewinsize(int, int, int, int); +extern int rcfd; +extern int rcstart(int, char*[], int*); diff --git a/src/cmd/9term/win.c b/src/cmd/9term/win.c new file mode 100644 index 00000000..95d84a32 --- /dev/null +++ b/src/cmd/9term/win.c @@ -0,0 +1,693 @@ +#include +#include +#include +#include +#include +#include "term.h" + +#define EVENTSIZE 256 +#define STACK 32768 + +typedef struct Event Event; +typedef struct Q Q; + +struct Event +{ + int c1; + int c2; + int q0; + int q1; + int flag; + int nb; + int nr; + char b[EVENTSIZE*UTFmax+1]; + Rune r[EVENTSIZE+1]; +}; + +Event blank = { + 'M', + 'X', + 0, 0, 0, 1, 1, + { ' ', 0 }, + { ' ', 0 }, +}; + +struct Q +{ + QLock lk; + int p; + int k; +}; + +Q q; + +Fid *eventfd; +Fid *addrfd; +Fid *datafd; +Fid *ctlfd; +// int bodyfd; + +char *typing; +int ntypeb; +int ntyper; +int ntypebreak; +int debug; +int rcfd; + +char *name; + +char **prog; +Channel *cwait; +int pid = -1; + +int label(char*, int); +void error(char*); +void stdinproc(void*); +void stdoutproc(void*); +void type(Event*, int, Fid*, Fid*); +void sende(Event*, int, Fid*, Fid*, Fid*, int); +char *onestring(int, char**); +int delete(Event*); +void deltype(uint, uint); +void runproc(void*); + +int +fsfidprint(Fid *fid, char *fmt, ...) +{ + char buf[256]; + va_list arg; + int n; + + va_start(arg, fmt); + n = vsnprint(buf, sizeof buf, fmt, arg); + va_end(arg); + return fswrite(fid, buf, n); +} + +void +usage(void) +{ + fprint(2, "usage: win cmd args...\n"); + threadexitsall("usage"); +} + +int +nopipes(void *v, char *msg) +{ + USED(v); + if(strcmp(msg, "sys: write on closed pipe") == 0) + return 1; + return 0; +} + +void +waitthread(void *v) +{ + recvp(cwait); + threadexitsall(nil); +} + +void +threadmain(int argc, char **argv) +{ + int fd, id; + char buf[256]; + char buf1[128]; + Fsys *fs; + + ARGBEGIN{ + case 'd': + debug = 1; + break; + default: + usage(); + }ARGEND + + prog = argv; + + if(argc > 0){ + name = argv[0]; + argc--; + argv++; + }else + name = "gnot"; + + threadnotify(nopipes, 1); + if((fs = nsmount("acme", "")) < 0) + sysfatal("nsmount acme: %r"); + ctlfd = fsopen(fs, "new/ctl", ORDWR|OCEXEC); + if(ctlfd < 0 || fsread(ctlfd, buf, 12) != 12) + sysfatal("ctl: %r"); + id = atoi(buf); + sprint(buf, "%d/tag", id); + fd = fsopenfd(fs, buf, OWRITE|OCEXEC); + write(fd, " Send Delete", 12); + close(fd); + sprint(buf, "%d/event", id); + eventfd = fsopen(fs, buf, ORDWR|OCEXEC); + sprint(buf, "%d/addr", id); + addrfd = fsopen(fs, buf, ORDWR|OCEXEC); + sprint(buf, "%d/data", id); + datafd = fsopen(fs, buf, ORDWR|OCEXEC); + sprint(buf, "%d/body", id); +/* bodyfd = fsopenfd(fs, buf, ORDWR|OCEXEC); */ + if(eventfd==nil || addrfd==nil || datafd==nil) + sysfatal("data files: %r"); +/* + if(eventfd<0 || addrfd<0 || datafd<0 || bodyfd<0) + sysfatal("data files: %r"); +*/ + fsunmount(fs); + + cwait = threadwaitchan(); + threadcreate(waitthread, nil, STACK); + pid = rcstart(argc, argv, &rcfd); + if(pid == -1) + sysfatal("exec failed"); + + getwd(buf1, sizeof buf1); + sprint(buf, "name %s/-%s\n0\n", buf1, name); + fswrite(ctlfd, buf, strlen(buf)); + sprint(buf, "dumpdir %s/\n", buf1); + fswrite(ctlfd, buf, strlen(buf)); + sprint(buf, "dump %s\n", onestring(argc, argv)); + fswrite(ctlfd, buf, strlen(buf)); + + threadcreate(stdoutproc, nil, STACK); + stdinproc(nil); +} + +void +error(char *s) +{ + if(s) + fprint(2, "win: %s: %r\n", s); + else + s = "kill"; + if(pid != -1) + postnote(PNGROUP, pid, "hangup"); + threadexitsall(s); +} + +char* +onestring(int argc, char **argv) +{ + char *p; + int i, n; + static char buf[1024]; + + if(argc == 0) + return ""; + p = buf; + for(i=0; i= buf+sizeof buf) + break; + memmove(p, argv[i], n); + p += n; + *p++ = ' '; + } + p[-1] = 0; + return buf; +} + +int +getec(Fid *efd) +{ + static char buf[8192]; + static char *bufp; + static int nbuf; + + if(nbuf == 0){ + nbuf = fsread(efd, buf, sizeof buf); + if(nbuf <= 0) + error(nil); + bufp = buf; + } + --nbuf; + return *bufp++; +} + +int +geten(Fid *efd) +{ + int n, c; + + n = 0; + while('0'<=(c=getec(efd)) && c<='9') + n = n*10+(c-'0'); + if(c != ' ') + error("event number syntax"); + return n; +} + +int +geter(Fid *efd, char *buf, int *nb) +{ + Rune r; + int n; + + r = getec(efd); + buf[0] = r; + n = 1; + if(r < Runeself) + goto Return; + while(!fullrune(buf, n)) + buf[n++] = getec(efd); + chartorune(&r, buf); + Return: + *nb = n; + return r; +} + +void +gete(Fid *efd, Event *e) +{ + int i, nb; + + e->c1 = getec(efd); + e->c2 = getec(efd); + e->q0 = geten(efd); + e->q1 = geten(efd); + e->flag = geten(efd); + e->nr = geten(efd); + if(e->nr > EVENTSIZE) + error("event string too long"); + e->nb = 0; + for(i=0; inr; i++){ + e->r[i] = geter(efd, e->b+e->nb, &nb); + e->nb += nb; + } + e->r[e->nr] = 0; + e->b[e->nb] = 0; + if(getec(efd) != '\n') + error("event syntax 2"); +} + +int +nrunes(char *s, int nb) +{ + int i, n; + Rune r; + + n = 0; + for(i=0; i0 && (buf[n-1]&0xC0)){ + --n; + npart++; + if((buf[n]&0xC0)!=0x80){ + if(fullrune(buf+n, npart)){ + w = chartorune(&r, buf+n); + n += w; + npart -= w; + } + break; + } + } + if(n > 0){ + memmove(hold, buf+n, npart); + buf[n] = 0; + n = label(buf, n); + buf[n] = 0; + qlock(&q.lk); + m = sprint(x, "#%d", q.p); + if(fswrite(afd, x, m) != m) + error("stdout writing address"); + if(fswrite(dfd, buf, n) != n) + error("stdout writing body"); + q.p += nrunes(buf, n); + qunlock(&q.lk); + memmove(buf, hold, npart); + } + } +} + +char wdir[256]; +int +label(char *sr, int n) +{ + char *sl, *el, *er, *r; + + er = sr+n; + for(r=er-1; r>=sr; r--) + if(*r == '\007') + break; + if(r < sr) + return n; + + el = r+1; + if(el-sr > sizeof wdir) + sr = el - sizeof wdir; + for(sl=el-3; sl>=sr; sl--) + if(sl[0]=='\033' && sl[1]==']' && sl[2]==';') + break; + if(sl < sr) + return n; + + *r = 0; + snprint(wdir, sizeof wdir, "name %s/-%s\n0\n", sl+3, name); + fswrite(ctlfd, wdir, strlen(wdir)); + + memmove(sl, el, er-el); + n -= (el-sl); + return n; +} + +int +delete(Event *e) +{ + uint q0, q1; + int deltap; + + q0 = e->q0; + q1 = e->q1; + if(q1 <= q.p) + return e->q1-e->q0; + if(q0 >= q.p+ntyper) + return 0; + deltap = 0; + if(q0 < q.p){ + deltap = q.p-q0; + q0 = 0; + }else + q0 -= q.p; + if(q1 > q.p+ntyper) + q1 = ntyper; + else + q1 -= q.p; + deltype(q0, q1); + return deltap; +} + +void +addtype(int c, uint p0, char *b, int nb, int nr) +{ + int i, w; + Rune r; + uint p; + char *b0; + + for(i=0; inr > 0) + addtype(e->c1, e->q0-q.p, e->b, e->nb, e->nr); + else{ + m = e->q0; + while(m < e->q1){ + n = sprint(buf, "#%d", m); + fswrite(afd, buf, n); + n = fsread(dfd, buf, sizeof buf); + nr = nrunes(buf, n); + while(m+nr > e->q1){ + do; while(n>0 && (buf[--n]&0xC0)==0x80); + --nr; + } + if(n == 0) + break; + addtype(e->c1, m-q.p, buf, n, nr); + m += nr; + } + } + sendtype(fd0); +} + +void +sende(Event *e, int fd0, Fid *cfd, Fid *afd, Fid *dfd, int donl) +{ + int l, m, n, nr, lastc, end; + char abuf[16], buf[128]; + + end = q.p+ntyper; + l = sprint(abuf, "#%d", end); + fswrite(afd, abuf, l); + if(e->nr > 0){ + fswrite(dfd, e->b, e->nb); + addtype(e->c1, ntyper, e->b, e->nb, e->nr); + lastc = e->r[e->nr-1]; + }else{ + m = e->q0; + lastc = 0; + while(m < e->q1){ + n = sprint(buf, "#%d", m); + fswrite(afd, buf, n); + n = fsread(dfd, buf, sizeof buf); + nr = nrunes(buf, n); + while(m+nr > e->q1){ + do; while(n>0 && (buf[--n]&0xC0)==0x80); + --nr; + } + if(n == 0) + break; + l = sprint(abuf, "#%d", end); + fswrite(afd, abuf, l); + fswrite(dfd, buf, n); + addtype(e->c1, ntyper, buf, n, nr); + lastc = buf[n-1]; + m += nr; + end += nr; + } + } + if(donl && lastc!='\n'){ + fswrite(dfd, "\n", 1); + addtype(e->c1, ntyper, "\n", 1, 1); + } + fswrite(cfd, "dot=addr", 8); + sendtype(fd0); +} diff --git a/src/cmd/acme/acme.c b/src/cmd/acme/acme.c index d4b4cad8..9636beab 100644 --- a/src/cmd/acme/acme.c +++ b/src/cmd/acme/acme.c @@ -161,7 +161,8 @@ threadmain(int argc, char *argv[]) cerr = chancreate(sizeof(char*), 0); cedit = chancreate(sizeof(int), 0); cexit = chancreate(sizeof(int), 0); - if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil){ + cwarn = chancreate(sizeof(void*), 1); + if(cwait==nil || ccommand==nil || ckill==nil || cxfidalloc==nil || cxfidfree==nil || cerr==nil || cexit==nil || cwarn==nil){ fprint(2, "acme: can't create initial channels: %r\n"); exits("channels"); } @@ -251,7 +252,7 @@ readfile(Column *c, char *s) w = coladd(c, nil, nil, -1); cvttorunes(s, strlen(s), rb, &nb, &nr, nil); - rs = cleanrname((Runestr){rb, nr}); + rs = cleanrname(runestr(rb, nr)); winsetname(w, rs.r, rs.nr); textload(&w->body, 0, s, 1); w->body.file->mod = FALSE; @@ -403,7 +404,6 @@ keyboardthread(void *v) winlock(t->w, 'K'); wincommit(t->w, t); winunlock(t->w); - flushwarnings(1); flushimage(display, 1); } alts[KTimer].c = nil; @@ -430,7 +430,6 @@ keyboardthread(void *v) } if(nbrecv(keyboardctl->c, &r) > 0) goto casekeyboard; - flushwarnings(1); flushimage(display, 1); break; } @@ -447,7 +446,7 @@ mousethread(void *v) Plumbmsg *pm; Mouse m; char *act; - enum { MResize, MMouse, MPlumb, NMALT }; + enum { MResize, MMouse, MPlumb, MWarnings, NMALT }; static Alt alts[NMALT+1]; USED(v); @@ -461,11 +460,18 @@ mousethread(void *v) alts[MPlumb].c = cplumb; alts[MPlumb].v = ± alts[MPlumb].op = CHANRCV; + alts[MWarnings].c = cwarn; + alts[MWarnings].v = nil; + alts[MWarnings].op = CHANRCV; if(cplumb == nil) alts[MPlumb].op = CHANNOP; alts[NMALT].op = CHANEND; for(;;){ + qlock(&row.lk); + flushwarnings(); + qunlock(&row.lk); + flushimage(display, 1); switch(alt(alts)){ case MResize: if(getwindow(display, Refnone) < 0) @@ -473,8 +479,6 @@ mousethread(void *v) draw(screen, screen->r, display->white, nil, ZP); scrlresize(); rowresize(&row, screen->clipr); - flushwarnings(1); - flushimage(display, 1); break; case MPlumb: if(strcmp(pm->type, "text") == 0){ @@ -484,10 +488,10 @@ mousethread(void *v) else if(strcmp(act, "showdata")==0) plumbshow(pm); } - flushwarnings(1); - flushimage(display, 1); plumbfree(pm); break; + case MWarnings: + break; case MMouse: /* * Make a copy so decisions are consistent; mousectl changes @@ -570,8 +574,6 @@ mousethread(void *v) goto Continue; } Continue: - flushwarnings(0); - flushimage(display, 1); qunlock(&row.lk); break; } diff --git a/src/cmd/acme/dat.h b/src/cmd/acme/dat.h index 94cfa383..338a1ff8 100644 --- a/src/cmd/acme/dat.h +++ b/src/cmd/acme/dat.h @@ -543,5 +543,6 @@ Channel *mouseexit1; /* chan(int) */ Channel *cexit; /* chan(int) */ Channel *cerr; /* chan(char*) */ Channel *cedit; /* chan(int) */ +Channel *cwarn; /* chan(void*)[1] (really chan(unit)[1]) */ #define STACK 32768 diff --git a/src/cmd/acme/ecmd.c b/src/cmd/acme/ecmd.c index 0dfae90a..7ccb9427 100644 --- a/src/cmd/acme/ecmd.c +++ b/src/cmd/acme/ecmd.c @@ -268,7 +268,7 @@ D_cmd(Text *t, Cmd *cp) runemove(n, dir.r, dir.nr); n[dir.nr] = '/'; runemove(n+dir.nr+1, r, nn); - rs = cleanrname((Runestr){n, dir.nr+1+nn}); + rs = cleanrname(runestr(n, dir.nr+1+nn)); } w = lookfile(rs.r, rs.nr); if(w == nil){ diff --git a/src/cmd/acme/exec.c b/src/cmd/acme/exec.c index 74f9f47c..0e3389d6 100644 --- a/src/cmd/acme/exec.c +++ b/src/cmd/acme/exec.c @@ -25,6 +25,7 @@ void fontx(Text*, Text*, Text*, int, int, Rune*, int); void get(Text*, Text*, Text*, int, int, Rune*, int); void id(Text*, Text*, Text*, int, int, Rune*, int); void incl(Text*, Text*, Text*, int, int, Rune*, int); +void indent(Text*, Text*, Text*, int, int, Rune*, int); void xkill(Text*, Text*, Text*, int, int, Rune*, int); void local(Text*, Text*, Text*, int, int, Rune*, int); void look(Text*, Text*, Text*, int, int, Rune*, int); @@ -58,6 +59,7 @@ static Rune LFont[] = { 'F', 'o', 'n', 't', 0 }; static Rune LGet[] = { 'G', 'e', 't', 0 }; static Rune LID[] = { 'I', 'D', 0 }; static Rune LIncl[] = { 'I', 'n', 'c', 'l', 0 }; +static Rune LIndent[] = { 'I', 'n', 'd', 'e', 'n', 't', 0 }; static Rune LKill[] = { 'K', 'i', 'l', 'l', 0 }; static Rune LLoad[] = { 'L', 'o', 'a', 'd', 0 }; static Rune LLocal[] = { 'L', 'o', 'c', 'a', 'l', 0 }; @@ -87,6 +89,7 @@ Exectab exectab[] = { { LGet, get, FALSE, TRUE, XXX }, { LID, id, FALSE, XXX, XXX }, { LIncl, incl, FALSE, XXX, XXX }, + { LIndent, indent, FALSE, XXX, XXX }, { LKill, xkill, FALSE, XXX, XXX }, { LLoad, dump, FALSE, FALSE, XXX }, { LLocal, local, FALSE, XXX, XXX }, @@ -1443,7 +1446,6 @@ runproc(void *argvp) goto Fail; Hard: - /* * ugly: set path = (. $cputype /bin) * should honor $path if unusual. diff --git a/src/cmd/acme/fns.h b/src/cmd/acme/fns.h index 9fba7d7a..c164bb3b 100644 --- a/src/cmd/acme/fns.h +++ b/src/cmd/acme/fns.h @@ -69,6 +69,7 @@ Rune* bytetorune(char*, int*); void fsysinit(void); Mntdir* fsysmount(Rune*, int, Rune**, int); void fsysdelid(Mntdir*); +void fsysincid(Mntdir*); Xfid* respond(Xfid*, Fcall*, char*); int rxcompile(Rune*); int rgetc(void*, uint); @@ -86,9 +87,11 @@ int expand(Text*, uint, uint, Expand*); Rune* skipbl(Rune*, int, int*); Rune* findbl(Rune*, int, int*); char* edittext(Window*, int, Rune*, int); -void flushwarnings(int); +void flushwarnings(void); void startplumbing(void); +Runestr runestr(Rune*, uint); + #define runemalloc(a) (Rune*)emalloc((a)*sizeof(Rune)) #define runerealloc(a, b) (Rune*)erealloc((a), (b)*sizeof(Rune)) #define runemove(a, b, c) memmove((a), (b), (c)*sizeof(Rune)) diff --git a/src/cmd/acme/fsys.c b/src/cmd/acme/fsys.c index f178f864..af4255c8 100644 --- a/src/cmd/acme/fsys.c +++ b/src/cmd/acme/fsys.c @@ -37,22 +37,25 @@ static Xfid* fsysremove(Xfid*, Fid*); static Xfid* fsysstat(Xfid*, Fid*); static Xfid* fsyswstat(Xfid*, Fid*); -Xfid* (*fcall[Tmax])(Xfid*, Fid*) = +Xfid* (*fcall[Tmax])(Xfid*, Fid*); + +static void +initfcall(void) { - [Tflush] = fsysflush, - [Tversion] = fsysversion, - [Tauth] = fsysauth, - [Tattach] = fsysattach, - [Twalk] = fsyswalk, - [Topen] = fsysopen, - [Tcreate] = fsyscreate, - [Tread] = fsysread, - [Twrite] = fsyswrite, - [Tclunk] = fsysclunk, - [Tremove]= fsysremove, - [Tstat] = fsysstat, - [Twstat] = fsyswstat, -}; + fcall[Tflush] = fsysflush; + fcall[Tversion] = fsysversion; + fcall[Tauth] = fsysauth; + fcall[Tattach] = fsysattach; + fcall[Twalk] = fsyswalk; + fcall[Topen] = fsysopen; + fcall[Tcreate] = fsyscreate; + fcall[Tread] = fsysread; + fcall[Twrite] = fsyswrite; + fcall[Tclunk] = fsysclunk; + fcall[Tremove]= fsysremove; + fcall[Tstat] = fsysstat; + fcall[Twstat] = fsyswstat; +} char Eperm[] = "permission denied"; char Eexist[] = "file does not exist"; @@ -113,6 +116,7 @@ fsysinit(void) int p[2]; char *u; + initfcall(); if(pipe(p) < 0) error("can't create pipe"); if(post9pservice(p[0], "acme") < 0) @@ -186,6 +190,14 @@ fsysaddid(Rune *dir, int ndir, Rune **incl, int nincl) return m; } +void +fsysincid(Mntdir *m) +{ + qlock(&mnt.lk); + m->ref++; + qunlock(&mnt.lk); +} + void fsysdelid(Mntdir *idm) { @@ -331,7 +343,7 @@ fsysattach(Xfid *x, Fid *f) m->ref++; break; } - if(m == nil){ + if(m == nil && x->fcall.aname[0]){ snprint(buf, sizeof buf, "unknown id '%s' in attach", x->fcall.aname); sendp(cerr, estrdup(buf)); } diff --git a/src/cmd/acme/look.c b/src/cmd/acme/look.c index f6c4d4ee..70233826 100644 --- a/src/cmd/acme/look.c +++ b/src/cmd/acme/look.c @@ -259,7 +259,7 @@ plumbshow(Plumbmsg *m) } cvttorunes(name, strlen(name), rb, &nb, &nr, nil); free(p); - rs = cleanrname((Runestr){rb, nr}); + rs = cleanrname(runestr(rb, nr)); winsetname(w, rs.r, rs.nr); r = runemalloc(m->ndata); cvttorunes(m->data, m->ndata, r, &nb, &nr, nil); @@ -385,13 +385,13 @@ includefile(Rune *dir, Rune *file, int nfile) n = access(a, 0); free(a); if(n < 0) - return (Runestr){nil, 0}; + return runestr(nil, 0); r = runemalloc(m+1+nfile); runemove(r, dir, m); runemove(r+m, Lslash, 1); runemove(r+m+1, file, nfile); free(file); - return cleanrname((Runestr){r, m+1+nfile}); + return cleanrname(runestr(r, m+1+nfile)); } static Rune *objdir; @@ -442,7 +442,7 @@ includename(Text *t, Rune *r, int n) return file; Rescue: - return (Runestr){r, n}; + return runestr(r, n); } Runestr @@ -475,11 +475,11 @@ dirname(Text *t, Rune *r, int n) goto Rescue; runemove(b+slash+1, r, n); free(r); - return cleanrname((Runestr){b, slash+1+n}); + return cleanrname(runestr(b, slash+1+n)); Rescue: free(b); - tmp = (Runestr){r, n}; + tmp = runestr(r, n); if(r) return cleanrname(tmp); return tmp; diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c index 8bdf0b78..c0cd7ec1 100644 --- a/src/cmd/acme/text.c +++ b/src/cmd/acme/text.c @@ -578,7 +578,7 @@ textcomplete(Text *t) path[i] = textreadc(t, q++); /* is path rooted? if not, we need to make it relative to window path */ if(npath>0 && path[0]=='/') - dir = (Runestr){path, npath}; + dir = runestr(path, npath); else{ dir = dirname(t, nil, 0); if(dir.nr + 1 + npath > nelem(tmp)){ diff --git a/src/cmd/acme/util.c b/src/cmd/acme/util.c index de71107a..a7307e06 100644 --- a/src/cmd/acme/util.c +++ b/src/cmd/acme/util.c @@ -14,6 +14,16 @@ static Point prevmouse; static Window *mousew; +Runestr +runestr(Rune *r, uint n) +{ + Runestr rs; + + rs.r = r; + rs.nr = n; + return rs; +} + void cvttorunes(char *p, int n, Rune *r, int *nb, int *nr, int *nulls) { @@ -133,12 +143,17 @@ addwarningtext(Mntdir *md, Rune *r, int nr) } warn = emalloc(sizeof(Warning)); warn->next = warnings; + warn->md = md; + if(md) + fsysincid(md); warnings = warn; bufinsert(&warn->buf, 0, r, nr); + nbsendp(cwarn, 0); } +/* called while row is locked */ void -flushwarnings(int dolock) +flushwarnings(void) { Warning *warn, *next; Window *w; @@ -146,8 +161,6 @@ flushwarnings(int dolock) int owner, nr, q0, n; Rune *r; - if(dolock) - qlock(&row.lk); if(row.ncol == 0){ /* really early error */ rowinit(&row, screen->clipr); rowadd(&row, nil, -1); @@ -189,11 +202,11 @@ flushwarnings(int dolock) winunlock(w); bufclose(&warn->buf); next = warn->next; + if(warn->md) + fsysdelid(warn->md); free(warn); } warnings = nil; - if(dolock) - qunlock(&row.lk); } void diff --git a/src/cmd/acme/xfid.c b/src/cmd/acme/xfid.c index b3bef2cd..839308ee 100644 --- a/src/cmd/acme/xfid.c +++ b/src/cmd/acme/xfid.c @@ -543,7 +543,6 @@ xfidwrite(Xfid *x) } if(w) winunlock(w); - flushwarnings(1); } void @@ -814,7 +813,6 @@ xfideventwrite(Xfid *x, Window *w) qunlock(&row.lk); goto Rescue; } - flushwarnings(0); qunlock(&row.lk); } @@ -1032,7 +1030,6 @@ xfidindexread(Xfid *x) b[n++] = '\n'; } } - flushwarnings(0); qunlock(&row.lk); off = x->fcall.offset; cnt = x->fcall.count; diff --git a/src/cmd/dict/dict.c b/src/cmd/dict/dict.c index 8cbf6aac..a3ddd890 100644 --- a/src/cmd/dict/dict.c +++ b/src/cmd/dict/dict.c @@ -119,6 +119,8 @@ main(int argc, char **argv) line = malloc(strlen(p)+5); sprint(line, "/%s/P\n", p); } + dict->path = unsharp(dict->path); + dict->indexpath = unsharp(dict->indexpath); bdict = Bopen(dict->path, OREAD); if(!bdict) { err("can't open dictionary %s", dict->path); diff --git a/src/cmd/diff/diff.h b/src/cmd/diff/diff.h index 8e56765f..c809ae81 100644 --- a/src/cmd/diff/diff.h +++ b/src/cmd/diff/diff.h @@ -1,3 +1,5 @@ +#define stdout bstdout + char mode; /* '\0', 'e', 'f', 'h' */ char bflag; /* ignore multiple and trailing blanks */ char rflag; /* recurse down directory trees */ diff --git a/src/cmd/diff/main.c b/src/cmd/diff/main.c index 43eb6dd1..00f69a3e 100644 --- a/src/cmd/diff/main.c +++ b/src/cmd/diff/main.c @@ -26,6 +26,8 @@ void done(int status) { rmtmpfiles(); +Bflush(&stdout); +Bterm(&stdout); switch(status) { case 0: diff --git a/src/cmd/fortune.c b/src/cmd/fortune.c index f3acfca2..4aa895fe 100644 --- a/src/cmd/fortune.c +++ b/src/cmd/fortune.c @@ -4,8 +4,8 @@ #define index findex char choice[2048]; -char index[] = "/sys/games/lib/fortunes.index"; -char fortunes[] = "/sys/games/lib/fortunes"; +char *index = "#9/lib/fortunes.index"; +char *fortunes = "#9/lib/fortunes"; #define lrand rand @@ -21,6 +21,9 @@ main(int argc, char *argv[]) Dir *fbuf, *ixbuf; Biobuf *f, g; + index = unsharp(index); + fortunes = unsharp(index); + newindex = 0; oldindex = 0; ix = offs = 0; @@ -55,6 +58,7 @@ main(int argc, char *argv[]) } } if(oldindex){ + srand(getpid()); seek(ix, lrand()%(ixbuf->length/sizeof(offs))*sizeof(offs), 0); read(ix, off, sizeof(off)); Bseek(f, off[0]|(off[1]<<8)|(off[2]<<16)|(off[3]<<24), 0); diff --git a/src/cmd/grep/comp.c b/src/cmd/grep/comp.c new file mode 100644 index 00000000..4a3f3e8f --- /dev/null +++ b/src/cmd/grep/comp.c @@ -0,0 +1,277 @@ +#include "grep.h" + +/* + * incremental compiler. + * add the branch c to the + * state s. + */ +void +increment(State *s, int c) +{ + int i; + State *t, **tt; + Re *re1, *re2; + + nfollow = 0; + gen++; + matched = 0; + for(i=0; icount; i++) + fol1(s->re[i], c); + qsort(follow, nfollow, sizeof(*follow), fcmp); + for(tt=&state0; t = *tt;) { + if(t->count > nfollow) { + tt = &t->linkleft; + goto cont; + } + if(t->count < nfollow) { + tt = &t->linkright; + goto cont; + } + for(i=0; ire[i]; + re2 = follow[i]; + if(re1 > re2) { + tt = &t->linkleft; + goto cont; + } + if(re1 < re2) { + tt = &t->linkright; + goto cont; + } + } + if(!!matched && !t->match) { + tt = &t->linkleft; + goto cont; + } + if(!matched && !!t->match) { + tt = &t->linkright; + goto cont; + } + s->next[c] = t; + return; + cont:; + } + + t = sal(nfollow); + *tt = t; + for(i=0; ire[i] = re1; + } + s->next[c] = t; + t->match = matched; +} + +int +fcmp(const void *va, const void *vb) +{ + Re **aa, **bb; + Re *a, *b; + + aa = (Re**)va; + bb = (Re**)vb; + a = *aa; + b = *bb; + if(a > b) + return 1; + if(a < b) + return -1; + return 0; +} + +void +fol1(Re *r, int c) +{ + Re *r1; + +loop: + if(r->gen == gen) + return; + if(nfollow >= maxfollow) + error("nfollow"); + r->gen = gen; + switch(r->type) { + default: + error("fol1"); + + case Tcase: + if(c >= 0 && c < 256) + if(r1 = r->cases[c]) + follow[nfollow++] = r1; + if(r = r->next) + goto loop; + break; + + case Talt: + case Tor: + fol1(r->alt, c); + r = r->next; + goto loop; + + case Tbegin: + if(c == '\n' || c == Cbegin) + follow[nfollow++] = r->next; + break; + + case Tend: + if(c == '\n') + matched = 1; + break; + + case Tclass: + if(c >= r->lo && c <= r->hi) + follow[nfollow++] = r->next; + break; + } +} + +Rune tab1[] = +{ + 0x007f, + 0x07ff, +}; +Rune tab2[] = +{ + 0x003f, + 0x0fff, +}; + +Re2 +rclass(Rune p0, Rune p1) +{ + char xc0[6], xc1[6]; + int i, n, m; + Re2 x; + + if(p0 > p1) + return re2char(0xff, 0xff); // no match + + /* + * bust range into same length + * character sequences + */ + for(i=0; i m) + return re2or(rclass(p0, m), rclass(m+1, p1)); + } + + /* + * bust range into part of a single page + * or into full pages + */ + for(i=0; i p[1]) + continue; + if(p[0] > q[1] || p[1] < q[0]) { + q[2] = p[0]; + q[3] = p[1]; + q += 2; + continue; + } + if(p[0] < q[0]) + q[0] = p[0]; + if(p[1] > q[1]) + q[1] = p[1]; + } + q[2] = 0; + + p = pairs; + if(nc) { + x = rclass(0, p[0]-1); + ov = p[1]+1; + for(p+=2; *p; p+=2) { + x = re2or(x, rclass(ov, p[0]-1)); + ov = p[1]+1; + } + x = re2or(x, rclass(ov, 0xffff)); + } else { + x = rclass(p[0], p[1]); + for(p+=2; *p; p+=2) + x = re2or(x, rclass(p[0], p[1])); + } + return x; +} diff --git a/src/cmd/grep/grep.h b/src/cmd/grep/grep.h new file mode 100644 index 00000000..8445df54 --- /dev/null +++ b/src/cmd/grep/grep.h @@ -0,0 +1,125 @@ +#include +#include +#include + +#ifndef EXTERN +#define EXTERN extern +#endif + +typedef struct Re Re; +typedef struct Re2 Re2; +typedef struct State State; + +struct State +{ + int count; + int match; + Re** re; + State* linkleft; + State* linkright; + State* next[256]; +}; +struct Re2 +{ + Re* beg; + Re* end; +}; +struct Re +{ + uchar type; + ushort gen; + union + { + Re* alt; /* Talt */ + Re** cases; /* case */ + struct /* class */ + { + Rune lo; + Rune hi; + }; + Rune val; /* char */ + }; + Re* next; +}; + +enum +{ + Talt = 1, + Tbegin, + Tcase, + Tclass, + Tend, + Tor, + + Caselim = 7, + Nhunk = 1<<16, + Cbegin = 0x10000, + Flshcnt = (1<<9)-1, + + Cflag = 1<<0, + Hflag = 1<<1, + Iflag = 1<<2, + Llflag = 1<<3, + LLflag = 1<<4, + Nflag = 1<<5, + Sflag = 1<<6, + Vflag = 1<<7, + Bflag = 1<<8 +}; + +EXTERN union +{ + char string[16*1024]; + struct + { + /* + * if a line requires multiple reads, we keep shifting + * buf down into pre and then do another read into + * buf. so you'll get the last 16-32k of the matching line. + * if pre were smaller than buf you'd get a suffix of the + * line with a hole cut out. + */ + uchar pre[16*1024]; /* to save to previous '\n' */ + uchar buf[16*1024]; /* input buffer */ + }; +} u; + +EXTERN char *filename; +EXTERN Biobuf bout; +EXTERN char flags[256]; +EXTERN Re** follow; +EXTERN ushort gen; +EXTERN char* input; +EXTERN long lineno; +EXTERN int literal; +EXTERN int matched; +EXTERN long maxfollow; +EXTERN long nfollow; +EXTERN int peekc; +EXTERN Biobuf* rein; +EXTERN State* state0; +EXTERN Re2 topre; + +extern Re* addcase(Re*); +extern void appendnext(Re*, Re*); +extern void error(char*); +extern int fcmp(const void*, const void*); /* (Re**, Re**) */ +extern void fol1(Re*, int); +extern int getrec(void); +extern void increment(State*, int); +#define initstate grepinitstate +extern State* initstate(Re*); +extern void* mal(int); +extern void patchnext(Re*, Re*); +extern Re* ral(int); +extern Re2 re2cat(Re2, Re2); +extern Re2 re2class(char*); +extern Re2 re2or(Re2, Re2); +extern Re2 re2char(int, int); +extern Re2 re2star(Re2); +extern State* sal(int); +extern int search(char*, int); +extern void str2top(char*); +extern int yyparse(void); +extern void reprint(char*, Re*); +extern void yyerror(char*, ...); diff --git a/src/cmd/grep/grep.y b/src/cmd/grep/grep.y new file mode 100644 index 00000000..94a744cf --- /dev/null +++ b/src/cmd/grep/grep.y @@ -0,0 +1,226 @@ +%{ +#include "grep.h" +%} + +%union +{ + int val; + char* str; + Re2 re; +} + +%type expr prog +%type expr0 expr1 expr2 expr3 expr4 +%token LCLASS +%token LCHAR +%token LLPAREN LRPAREN LALT LSTAR LPLUS LQUES +%token LBEGIN LEND LDOT LBAD LNEWLINE +%% + +prog: + expr newlines + { + $$.beg = ral(Tend); + $$.end = $$.beg; + $$ = re2cat(re2star(re2or(re2char(0x00, '\n'-1), re2char('\n'+1, 0xff))), $$); + $$ = re2cat($1, $$); + $$ = re2cat(re2star(re2char(0x00, 0xff)), $$); + topre = $$; + } + +expr: + expr0 +| expr newlines expr0 + { + $$ = re2or($1, $3); + } + +expr0: + expr1 +| LSTAR { literal = 1; } expr1 + { + $$ = $3; + } + +expr1: + expr2 +| expr1 LALT expr2 + { + $$ = re2or($1, $3); + } + +expr2: + expr3 +| expr2 expr3 + { + $$ = re2cat($1, $2); + } + +expr3: + expr4 +| expr3 LSTAR + { + $$ = re2star($1); + } +| expr3 LPLUS + { + $$.beg = ral(Talt); + patchnext($1.end, $$.beg); + $$.beg->alt = $1.beg; + $$.end = $$.beg; + $$.beg = $1.beg; + } +| expr3 LQUES + { + $$.beg = ral(Talt); + $$.beg->alt = $1.beg; + $$.end = $1.end; + appendnext($$.end, $$.beg); + } + +expr4: + LCHAR + { + $$.beg = ral(Tclass); + $$.beg->lo = $1; + $$.beg->hi = $1; + $$.end = $$.beg; + } +| LBEGIN + { + $$.beg = ral(Tbegin); + $$.end = $$.beg; + } +| LEND + { + $$.beg = ral(Tend); + $$.end = $$.beg; + } +| LDOT + { + $$ = re2class("^\n"); + } +| LCLASS + { + $$ = re2class($1); + } +| LLPAREN expr1 LRPAREN + { + $$ = $2; + } + +newlines: + LNEWLINE +| newlines LNEWLINE +%% + +void +yyerror(char *e, ...) +{ + if(filename) + fprint(2, "grep: %s:%ld: %s\n", filename, lineno, e); + else + fprint(2, "grep: %s\n", e); + exits("syntax"); +} + +long +yylex(void) +{ + char *q, *eq; + int c, s; + + if(peekc) { + s = peekc; + peekc = 0; + return s; + } + c = getrec(); + if(literal) { + if(c != 0 && c != '\n') { + yylval.val = c; + return LCHAR; + } + literal = 0; + } + switch(c) { + default: + yylval.val = c; + s = LCHAR; + break; + case '\\': + c = getrec(); + yylval.val = c; + s = LCHAR; + if(c == '\n') + s = LNEWLINE; + break; + case '[': + goto getclass; + case '(': + s = LLPAREN; + break; + case ')': + s = LRPAREN; + break; + case '|': + s = LALT; + break; + case '*': + s = LSTAR; + break; + case '+': + s = LPLUS; + break; + case '?': + s = LQUES; + break; + case '^': + s = LBEGIN; + break; + case '$': + s = LEND; + break; + case '.': + s = LDOT; + break; + case 0: + peekc = -1; + case '\n': + s = LNEWLINE; + break; + } + return s; + +getclass: + q = u.string; + eq = q + nelem(u.string) - 5; + c = getrec(); + if(c == '^') { + q[0] = '^'; + q[1] = '\n'; + q[2] = '-'; + q[3] = '\n'; + q += 4; + c = getrec(); + } + for(;;) { + if(q >= eq) + error("class too long"); + if(c == ']' || c == 0) + break; + if(c == '\\') { + *q++ = c; + c = getrec(); + if(c == 0) + break; + } + *q++ = c; + c = getrec(); + } + *q = 0; + if(c == 0) + return LBAD; + yylval.str = u.string; + return LCLASS; +} diff --git a/src/cmd/grep/main.c b/src/cmd/grep/main.c new file mode 100644 index 00000000..f2a6e040 --- /dev/null +++ b/src/cmd/grep/main.c @@ -0,0 +1,260 @@ +#define EXTERN +#include "grep.h" + +char *validflags = "bchiLlnsv"; +void +usage(void) +{ + fprint(2, "usage: grep [-%s] [-f file] [-e expr] [file ...]\n", validflags); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + int i, status; + + ARGBEGIN { + default: + if(utfrune(validflags, ARGC()) == nil) + usage(); + flags[ARGC()]++; + break; + + case 'e': + flags['e']++; + lineno = 0; + str2top(ARGF()); + break; + + case 'f': + flags['f']++; + filename = ARGF(); + rein = Bopen(filename, OREAD); + if(rein == 0) { + fprint(2, "grep: can't open %s: %r\n", filename); + exits("open"); + } + lineno = 1; + str2top(filename); + break; + } ARGEND + + if(flags['f'] == 0 && flags['e'] == 0) { + if(argc <= 0) + usage(); + str2top(argv[0]); + argc--; + argv++; + } + + follow = mal(maxfollow*sizeof(*follow)); + state0 = initstate(topre.beg); + + Binit(&bout, 1, OWRITE); + switch(argc) { + case 0: + status = search(0, 0); + break; + case 1: + status = search(argv[0], 0); + break; + default: + status = 0; + for(i=0; i sizeof(u.pre)) + n = sizeof(u.pre); + memmove(u.buf-n, bol, n); + bol = u.buf-n; + n = read(fid, u.buf, sizeof(u.buf)); + /* if file has no final newline, simulate one to emit matches to last line */ + if(n > 0) { + empty = 0; + nl = u.buf[n-1]=='\n'; + } else { + if(n < 0){ + fprint(2, "grep: read error on %s: %r\n", file); + return count != 0; + } + if(!eof && !nl && !empty) { + u.buf[0] = '\n'; + n = 1; + eof = 1; + } + } + if(n <= 0) { + close(fid); + if(flag & Cflag) { + if(flag & Hflag) + Bprint(&bout, "%s:", file); + Bprint(&bout, "%ld\n", count); + } + if(((flag&Llflag) && count != 0) || ((flag&LLflag) && count == 0)) + Bprint(&bout, "%s\n", file); + Bflush(&bout); + return count != 0; + } + lp = u.buf; + elp = lp+n; + if(flag & Iflag) + goto loopi; + +/* + * normal character loop + */ +loop: + c = *lp; + ns = s->next[c]; + if(ns == 0) { + increment(s, c); + goto loop; + } +// if(flags['2']) +// if(s->match) +// print("%d: %.2x**\n", s, c); +// else +// print("%d: %.2x\n", s, c); + lp++; + s = ns; + if(c == '\n') { + lineno++; + if(!!s->match == !(flag&Vflag)) { + count++; + if(flag & (Cflag|Sflag|Llflag|LLflag)) + goto cont; + if(flag & Hflag) + Bprint(&bout, "%s:", file); + if(flag & Nflag) + Bprint(&bout, "%ld: ", lineno); + /* suppress extra newline at EOF unless we are labeling matches with file name */ + Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag))); + if(flag & Bflag) + Bflush(&bout); + } + if((lineno & Flshcnt) == 0) + Bflush(&bout); + cont: + bol = lp; + } + if(lp != elp) + goto loop; + goto loop0; + +/* + * character loop for -i flag + * for speed + */ +loopi: + c = *lp; + if(c >= 'A' && c <= 'Z') + c += 'a'-'A'; + ns = s->next[c]; + if(ns == 0) { + increment(s, c); + goto loopi; + } + lp++; + s = ns; + if(c == '\n') { + lineno++; + if(!!s->match == !(flag&Vflag)) { + count++; + if(flag & (Cflag|Sflag|Llflag|LLflag)) + goto conti; + if(flag & Hflag) + Bprint(&bout, "%s:", file); + if(flag & Nflag) + Bprint(&bout, "%ld: ", lineno); + /* suppress extra newline at EOF unless we are labeling matches with file name */ + Bwrite(&bout, bol, lp-bol-(eof && !(flag&Hflag))); + if(flag & Bflag) + Bflush(&bout); + } + if((lineno & Flshcnt) == 0) + Bflush(&bout); + conti: + bol = lp; + } + if(lp != elp) + goto loopi; + goto loop0; +} + +State* +initstate(Re *r) +{ + State *s; + int i; + + addcase(r); + if(flags['1']) + reprint("r", r); + nfollow = 0; + gen++; + fol1(r, Cbegin); + follow[nfollow++] = r; + qsort(follow, nfollow, sizeof(*follow), fcmp); + + s = sal(nfollow); + for(i=0; ire[i] = follow[i]; + return s; +} diff --git a/src/cmd/grep/mkfile b/src/cmd/grep/mkfile new file mode 100644 index 00000000..fd17abdd --- /dev/null +++ b/src/cmd/grep/mkfile @@ -0,0 +1,20 @@ +PLAN9=../../.. +<$PLAN9/src/mkhdr + +# Calling this grep breaks a LOT. Like egrep on Linux. +# And probably configure. + +TARG=9grep +HFILES=\ + grep.h\ + +OFILES=\ + y.tab.$O\ + main.$O\ + comp.$O\ + sub.$O\ + +YFILES=grep.y\ + +SHORTLIB=bio 9 +<$PLAN9/src/mkone diff --git a/src/cmd/grep/sub.c b/src/cmd/grep/sub.c new file mode 100644 index 00000000..be2acee3 --- /dev/null +++ b/src/cmd/grep/sub.c @@ -0,0 +1,317 @@ +#include "grep.h" + +void* +mal(int n) +{ + static char *s; + static int m = 0; + void *v; + + n = (n+3) & ~3; + if(m < n) { + if(n > Nhunk) { + v = sbrk(n); + memset(v, 0, n); + return v; + } + s = sbrk(Nhunk); + m = Nhunk; + } + v = s; + s += n; + m -= n; + memset(v, 0, n); + return v; +} + +State* +sal(int n) +{ + State *s; + + s = mal(sizeof(*s)); +// s->next = mal(256*sizeof(*s->next)); + s->count = n; + s->re = mal(n*sizeof(*state0->re)); + return s; +} + +Re* +ral(int type) +{ + Re *r; + + r = mal(sizeof(*r)); + r->type = type; + maxfollow++; + return r; +} + +void +error(char *s) +{ + fprint(2, "grep: internal error: %s\n", s); + exits(s); +} + +int +countor(Re *r) +{ + int n; + + n = 0; +loop: + switch(r->type) { + case Tor: + n += countor(r->alt); + r = r->next; + goto loop; + case Tclass: + return n + r->hi - r->lo + 1; + } + return n; +} + +Re* +oralloc(int t, Re *r, Re *b) +{ + Re *a; + + if(b == 0) + return r; + a = ral(t); + a->alt = r; + a->next = b; + return a; +} + +void +case1(Re *c, Re *r) +{ + int n; + +loop: + switch(r->type) { + case Tor: + case1(c, r->alt); + r = r->next; + goto loop; + + case Tclass: /* add to character */ + for(n=r->lo; n<=r->hi; n++) + c->cases[n] = oralloc(Tor, r->next, c->cases[n]); + break; + + default: /* add everything unknown to next */ + c->next = oralloc(Talt, r, c->next); + break; + } +} + +Re* +addcase(Re *r) +{ + int i, n; + Re *a; + + if(r->gen == gen) + return r; + r->gen = gen; + switch(r->type) { + default: + error("addcase"); + + case Tor: + n = countor(r); + if(n >= Caselim) { + a = ral(Tcase); + a->cases = mal(256*sizeof(*a->cases)); + case1(a, r); + for(i=0; i<256; i++) + if(a->cases[i]) { + r = a->cases[i]; + if(countor(r) < n) + a->cases[i] = addcase(r); + } + return a; + } + return r; + + case Talt: + r->next = addcase(r->next); + r->alt = addcase(r->alt); + return r; + + case Tbegin: + case Tend: + case Tclass: + return r; + } +} + +void +str2top(char *p) +{ + Re2 oldtop; + + oldtop = topre; + input = p; + topre.beg = 0; + topre.end = 0; + yyparse(); + gen++; + if(topre.beg == 0) + yyerror("syntax"); + if(oldtop.beg) + topre = re2or(oldtop, topre); +} + +void +appendnext(Re *a, Re *b) +{ + Re *n; + + while(n = a->next) + a = n; + a->next = b; +} + +void +patchnext(Re *a, Re *b) +{ + Re *n; + + while(a) { + n = a->next; + a->next = b; + a = n; + } +} + +int +getrec(void) +{ + int c; + + if(flags['f']) { + c = Bgetc(rein); + if(c <= 0) + return 0; + } else + c = *input++ & 0xff; + if(flags['i'] && c >= 'A' && c <= 'Z') + c += 'a'-'A'; + if(c == '\n') + lineno++; + return c; +} + +Re2 +re2cat(Re2 a, Re2 b) +{ + Re2 c; + + c.beg = a.beg; + c.end = b.end; + patchnext(a.end, b.beg); + return c; +} + +Re2 +re2star(Re2 a) +{ + Re2 c; + + c.beg = ral(Talt); + c.beg->alt = a.beg; + patchnext(a.end, c.beg); + c.end = c.beg; + return c; +} + +Re2 +re2or(Re2 a, Re2 b) +{ + Re2 c; + + c.beg = ral(Tor); + c.beg->alt = b.beg; + c.beg->next = a.beg; + c.end = b.end; + appendnext(c.end, a.end); + return c; +} + +Re2 +re2char(int c0, int c1) +{ + Re2 c; + + c.beg = ral(Tclass); + c.beg->lo = c0 & 0xff; + c.beg->hi = c1 & 0xff; + c.end = c.beg; + return c; +} + +void +reprint1(Re *a) +{ + int i, j; + +loop: + if(a == 0) + return; + if(a->gen == gen) + return; + a->gen = gen; + print("%p: ", a); + switch(a->type) { + default: + print("type %d\n", a->type); + error("print1 type"); + + case Tcase: + print("case ->%p\n", a->next); + for(i=0; i<256; i++) + if(a->cases[i]) { + for(j=i+1; j<256; j++) + if(a->cases[i] != a->cases[j]) + break; + print(" [%.2x-%.2x] ->%p\n", i, j-1, a->cases[i]); + i = j-1; + } + for(i=0; i<256; i++) + reprint1(a->cases[i]); + break; + + case Tbegin: + print("^ ->%p\n", a->next); + break; + + case Tend: + print("$ ->%p\n", a->next); + break; + + case Tclass: + print("[%.2x-%.2x] ->%p\n", a->lo, a->hi, a->next); + break; + + case Tor: + case Talt: + print("| %p ->%p\n", a->alt, a->next); + reprint1(a->alt); + break; + } + a = a->next; + goto loop; +} + +void +reprint(char *s, Re *r) +{ + print("%s:\n", s); + gen++; + reprint1(r); + print("\n\n"); +} diff --git a/src/cmd/mkfile b/src/cmd/mkfile index 3ad7ea7a..292c051b 100644 --- a/src/cmd/mkfile +++ b/src/cmd/mkfile @@ -3,11 +3,11 @@ PLAN9=../.. TARG=`ls *.c | sed 's/\.c//'` LDFLAGS=$LDFLAGS -SHORTLIB=sec fs mux regexp9 thread bio 9 +SHORTLIB=mach sec fs mux regexp9 thread bio 9 <$PLAN9/src/mkmany -BUGGERED='CVS|9term|faces|factotum|htmlfmt|mk|rio|upas|vac|venti' +BUGGERED='CVS|faces|factotum|htmlfmt|mk|upas|vac|venti' DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "^($BUGGERED)$"` <$PLAN9/src/mkdirs diff --git a/src/cmd/plumb/fsys.c b/src/cmd/plumb/fsys.c index 4776d127..33a4458e 100644 --- a/src/cmd/plumb/fsys.c +++ b/src/cmd/plumb/fsys.c @@ -97,6 +97,7 @@ static Dirtab dir[NDIR] = static int ndir = NQID; static int srvfd; +#define clock plumbclock /* SunOS name clash */ static int clock; static Fid *fids[Nhash]; static QLock readlock; diff --git a/src/cmd/plumb/plumber.c b/src/cmd/plumb/plumber.c index 80a57af3..bf7afa3f 100644 --- a/src/cmd/plumb/plumber.c +++ b/src/cmd/plumb/plumber.c @@ -54,9 +54,10 @@ threadmain(int argc, char *argv[]) error("can't initialize $user or $home: %r"); if(plumbfile == nil){ sprint(buf, "%s/lib/plumbing", home); - if(access(buf, 0) < 0) - sprint(buf, "#9/plumb/initial.plumbing"); - plumbfile = estrdup(buf); + if(access(buf, 0) >= 0) + plumbfile = estrdup(buf); + else + plumbfile = unsharp("#9/plumb/initial.plumbing"); } fd = open(plumbfile, OREAD); diff --git a/src/cmd/plumb/rules.c b/src/cmd/plumb/rules.c index 689edf59..ab27787d 100644 --- a/src/cmd/plumb/rules.c +++ b/src/cmd/plumb/rules.c @@ -415,7 +415,7 @@ include(char *s) fd = open(t, OREAD); if(fd<0 && t[0]!='/' && strncmp(t, "./", 2)!=0 && strncmp(t, "../", 3)!=0){ snprint(buf, sizeof buf, "#9/plumb/%s", t); - t = buf; + t = unsharp(buf); fd = open(t, OREAD); } if(fd < 0) diff --git a/src/cmd/rc/plan9ish.c b/src/cmd/rc/plan9ish.c index eb93a4f5..6b32a227 100644 --- a/src/cmd/rc/plan9ish.c +++ b/src/cmd/rc/plan9ish.c @@ -27,20 +27,10 @@ char *syssigname[]={ char* Rcmain(void) { - return "#9/rcmain"; -/* - static char buf[256]; - char *root; - - root = getenv("PLAN9"); - if(root == nil) - root = "/usr/local/plan9"; - snprint(buf, sizeof buf, "%s/rcmain", root); - return buf; -*/ + return unsharp("#9/rcmain"); } -char Fdprefix[]="#d/"; +char Fdprefix[]="/dev/fd/"; void execfinit(void); void execbind(void); void execmount(void); diff --git a/src/cmd/rio/Imakefile b/src/cmd/rio/Imakefile new file mode 100644 index 00000000..43a78931 --- /dev/null +++ b/src/cmd/rio/Imakefile @@ -0,0 +1,27 @@ +INCLUDES = -I$(TOP) +DEPLIBS = $(DEPXLIB) +LOCAL_LIBRARIES = $(XLIB) +DEFINES = -DSHAPE # -g3 -DDEBUG -DDEBUG_EV +SRCS = main.c event.c manage.c menu.c client.c grab.c cursor.c error.c color.c +OBJS = main.o event.o manage.o menu.o client.o grab.o cursor.o error.o color.o +HFILES = dat.h fns.h patchlevel.h +MFILES = README 9wm.man Imakefile Makefile.no-imake + +ComplexProgramTarget(rio) + +bun: + bundle $(MFILES) $(SRCS) $(HFILES) >bun + +dist: + bundle $(MFILES) main.c event.c manage.c >bun1 + bundle menu.c client.c grab.c cursor.c error.c $(HFILES) >bun2 + +trout: 9wm.man + troff -man 9wm.man >trout + +vu: trout + xditview trout + +clean:: + $(RM) bun bun[12] trout core + diff --git a/src/cmd/rio/color.c b/src/cmd/rio/color.c index 8c534660..0e3c8d89 100644 --- a/src/cmd/rio/color.c +++ b/src/cmd/rio/color.c @@ -8,7 +8,7 @@ #include "fns.h" unsigned long -colorpixel(Display *dpy, int depth, ulong rgb) +colorpixel(Display *dpy, int depth, unsigned long rgb) { int r, g, b; diff --git a/src/cmd/rio/main.c b/src/cmd/rio/main.c index 0953f1bd..02929773 100644 --- a/src/cmd/rio/main.c +++ b/src/cmd/rio/main.c @@ -9,6 +9,9 @@ #include #include #include +#ifdef SHAPE +#include +#endif #include "dat.h" #include "fns.h" #include "patchlevel.h" @@ -70,12 +73,15 @@ main(int argc, char *argv[]) int i, background, do_exit, do_restart; char *fname; int shape_event; +#ifdef SHAPE + int dummy; +#endif shape_event = 0; myargv = argv; /* for restart */ do_exit = do_restart = 0; - background = 1; + background = 0; font = 0; fname = 0; for (i = 1; i < argc; i++) @@ -289,12 +295,11 @@ initscreen(ScreenInfo *s, int i, int background) XSync(dpy, False); if (background) { -/* XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap); XClearWindow(dpy, s->root); -*/ + } else system("xsetroot -solid grey30"); - } + s->menuwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 2, colorpixel(dpy, s->depth, 0x88CC88), colorpixel(dpy, s->depth, 0xE9FFE9)); s->sweepwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 4, s->red, colorpixel(dpy, s->depth, 0xEEEEEE)); } diff --git a/src/cmd/rio/mkfile b/src/cmd/rio/mkfile index 8881190c..b5e8b110 100644 --- a/src/cmd/rio/mkfile +++ b/src/cmd/rio/mkfile @@ -1,3 +1,4 @@ +PLAN9=../../.. <$PLAN9/src/mkhdr OFILES=\ @@ -18,3 +19,7 @@ TARG=rio LDFLAGS=-L$X11/lib -lXext -lX11 <$PLAN9/src/mkone + +CFLAGS=$CFLAGS -DSHAPE -I$X11/include + + diff --git a/src/cmd/spell/sprog.c b/src/cmd/spell/sprog.c index e63fbb87..8d5519ef 100644 --- a/src/cmd/spell/sprog.c +++ b/src/cmd/spell/sprog.c @@ -460,6 +460,9 @@ main(int argc, char *argv[]) int low; Bits h; + codefile = unsharp(codefile); + brfile = unsharp(brfile); + Binit(&bin, 0, OREAD); Binit(&bout, 1, OWRITE); for(i=0; c = "aeiouyAEIOUY"[i]; i++) diff --git a/src/cmd/win.c b/src/cmd/win.c deleted file mode 100644 index 7f15f057..00000000 --- a/src/cmd/win.c +++ /dev/null @@ -1,717 +0,0 @@ -#include -#include -#include -#include -#include - -#define EVENTSIZE 256 -#define STACK 32768 - -typedef struct Event Event; -typedef struct Q Q; - -struct Event -{ - int c1; - int c2; - int q0; - int q1; - int flag; - int nb; - int nr; - char b[EVENTSIZE*UTFmax+1]; - Rune r[EVENTSIZE+1]; -}; - -Event blank = { - 'M', - 'X', - 0, 0, 0, 1, 1, - { ' ', 0 }, - { ' ', 0 }, -}; - -struct Q -{ - QLock lk; - int p; - int k; -}; - -Q q; - -Fid *eventfd; -Fid *addrfd; -Fid *datafd; -Fid *ctlfd; -// int bodyfd; - -char *typing; -int ntypeb; -int ntyper; -int ntypebreak; -int debug; -char *name; - -char **prog; -int p[2]; -Channel *cpid; -Channel *cwait; -int pid = -1; - -int label(char*, int); -void error(char*); -void stdinproc(void*); -void stdoutproc(void*); -void type(Event*, int, Fid*, Fid*); -void sende(Event*, int, Fid*, Fid*, Fid*, int); -char *onestring(int, char**); -int delete(Event*); -void deltype(uint, uint); -void runproc(void*); - -int -fsfidprint(Fid *fid, char *fmt, ...) -{ - char buf[256]; - va_list arg; - int n; - - va_start(arg, fmt); - n = vsnprint(buf, sizeof buf, fmt, arg); - va_end(arg); - return fswrite(fid, buf, n); -} - -void -usage(void) -{ - fprint(2, "usage: win cmd args...\n"); - threadexitsall("usage"); -} - -int -nopipes(void *v, char *msg) -{ - USED(v); - if(strcmp(msg, "sys: write on closed pipe") == 0) - return 1; - return 0; -} - -void -waitthread(void *v) -{ - recvp(cwait); - threadexitsall(nil); -} - -void -threadmain(int argc, char **argv) -{ - int fd, id; - char buf[256]; - char buf1[128]; - Fsys *fs; - - ARGBEGIN{ - case 'd': - debug = 1; - break; - default: - usage(); - }ARGEND - - prog = argv; - - if(argc > 0) - name = argv[0]; - else - name = "gnot"; - - threadnotify(nopipes, 1); - if((fs = nsmount("acme", "")) < 0) - sysfatal("nsmount acme: %r"); - ctlfd = fsopen(fs, "new/ctl", ORDWR|OCEXEC); - if(ctlfd < 0 || fsread(ctlfd, buf, 12) != 12) - sysfatal("ctl: %r"); - id = atoi(buf); - sprint(buf, "%d/tag", id); - fd = fsopenfd(fs, buf, OWRITE|OCEXEC); - write(fd, " Send Delete", 12); - close(fd); - sprint(buf, "%d/event", id); - eventfd = fsopen(fs, buf, ORDWR|OCEXEC); - sprint(buf, "%d/addr", id); - addrfd = fsopen(fs, buf, ORDWR|OCEXEC); - sprint(buf, "%d/data", id); - datafd = fsopen(fs, buf, ORDWR|OCEXEC); - sprint(buf, "%d/body", id); -/* bodyfd = fsopenfd(fs, buf, ORDWR|OCEXEC); */ - if(eventfd==nil || addrfd==nil || datafd==nil) - sysfatal("data files: %r"); -/* - if(eventfd<0 || addrfd<0 || datafd<0 || bodyfd<0) - sysfatal("data files: %r"); -*/ - fsunmount(fs); - - if(pipe(p) < 0) - sysfatal("pipe: %r"); - - cpid = chancreate(sizeof(ulong), 1); - cwait = threadwaitchan(); - threadcreate(waitthread, nil, STACK); - threadcreate(runproc, nil, STACK); - pid = recvul(cpid); - if(pid == -1) - sysfatal("exec failed"); - - getwd(buf1, sizeof buf1); - sprint(buf, "name %s/-%s\n0\n", buf1, name); - fswrite(ctlfd, buf, strlen(buf)); - sprint(buf, "dumpdir %s/\n", buf1); - fswrite(ctlfd, buf, strlen(buf)); - sprint(buf, "dump %s\n", onestring(argc, argv)); - fswrite(ctlfd, buf, strlen(buf)); - - threadcreate(stdoutproc, nil, STACK); - stdinproc(nil); -} - -char *shell[] = { "rc", "-i", 0 }; -void -runproc(void *v) -{ - int fd[3]; - char *sh; - - USED(v); - - fd[0] = p[1]; -// fd[1] = bodyfd; -// fd[2] = bodyfd; - fd[1] = p[1]; - fd[2] = p[1]; - - if(prog[0] == nil){ - prog = shell; - if((sh = getenv("SHELL")) != nil) - shell[0] = sh; - } - threadexec(cpid, fd, prog[0], prog); - threadexits(nil); -} - -void -error(char *s) -{ - if(s) - fprint(2, "win: %s: %r\n", s); - else - s = "kill"; - if(pid != -1) - postnote(PNGROUP, pid, "hangup"); - threadexitsall(s); -} - -char* -onestring(int argc, char **argv) -{ - char *p; - int i, n; - static char buf[1024]; - - if(argc == 0) - return ""; - p = buf; - for(i=0; i= buf+sizeof buf) - break; - memmove(p, argv[i], n); - p += n; - *p++ = ' '; - } - p[-1] = 0; - return buf; -} - -int -getec(Fid *efd) -{ - static char buf[8192]; - static char *bufp; - static int nbuf; - - if(nbuf == 0){ - nbuf = fsread(efd, buf, sizeof buf); - if(nbuf <= 0) - error(nil); - bufp = buf; - } - --nbuf; - return *bufp++; -} - -int -geten(Fid *efd) -{ - int n, c; - - n = 0; - while('0'<=(c=getec(efd)) && c<='9') - n = n*10+(c-'0'); - if(c != ' ') - error("event number syntax"); - return n; -} - -int -geter(Fid *efd, char *buf, int *nb) -{ - Rune r; - int n; - - r = getec(efd); - buf[0] = r; - n = 1; - if(r < Runeself) - goto Return; - while(!fullrune(buf, n)) - buf[n++] = getec(efd); - chartorune(&r, buf); - Return: - *nb = n; - return r; -} - -void -gete(Fid *efd, Event *e) -{ - int i, nb; - - e->c1 = getec(efd); - e->c2 = getec(efd); - e->q0 = geten(efd); - e->q1 = geten(efd); - e->flag = geten(efd); - e->nr = geten(efd); - if(e->nr > EVENTSIZE) - error("event string too long"); - e->nb = 0; - for(i=0; inr; i++){ - e->r[i] = geter(efd, e->b+e->nb, &nb); - e->nb += nb; - } - e->r[e->nr] = 0; - e->b[e->nb] = 0; - if(getec(efd) != '\n') - error("event syntax 2"); -} - -int -nrunes(char *s, int nb) -{ - int i, n; - Rune r; - - n = 0; - for(i=0; i0 && (buf[n-1]&0xC0)){ - --n; - npart++; - if((buf[n]&0xC0)!=0x80){ - if(fullrune(buf+n, npart)){ - w = chartorune(&r, buf+n); - n += w; - npart -= w; - } - break; - } - } - if(n > 0){ - memmove(hold, buf+n, npart); - buf[n] = 0; - n = label(buf, n); - buf[n] = 0; - qlock(&q.lk); - m = sprint(x, "#%d", q.p); - if(fswrite(afd, x, m) != m) - error("stdout writing address"); - if(fswrite(dfd, buf, n) != n) - error("stdout writing body"); - q.p += nrunes(buf, n); - qunlock(&q.lk); - memmove(buf, hold, npart); - } - } -} - -char wdir[256]; -int -label(char *sr, int n) -{ - char *sl, *el, *er, *r; - - er = sr+n; - for(r=er-1; r>=sr; r--) - if(*r == '\007') - break; - if(r < sr) - return n; - - el = r+1; - if(el-sr > sizeof wdir) - sr = el - sizeof wdir; - for(sl=el-3; sl>=sr; sl--) - if(sl[0]=='\033' && sl[1]==']' && sl[2]==';') - break; - if(sl < sr) - return n; - - *r = 0; - snprint(wdir, sizeof wdir, "name %s/-%s\n0\n", sl+3, name); - fswrite(ctlfd, wdir, strlen(wdir)); - - memmove(sl, el, er-el); - n -= (el-sl); - return n; -} - -int -delete(Event *e) -{ - uint q0, q1; - int deltap; - - q0 = e->q0; - q1 = e->q1; - if(q1 <= q.p) - return e->q1-e->q0; - if(q0 >= q.p+ntyper) - return 0; - deltap = 0; - if(q0 < q.p){ - deltap = q.p-q0; - q0 = 0; - }else - q0 -= q.p; - if(q1 > q.p+ntyper) - q1 = ntyper; - else - q1 -= q.p; - deltype(q0, q1); - return deltap; -} - -void -addtype(int c, uint p0, char *b, int nb, int nr) -{ - int i, w; - Rune r; - uint p; - char *b0; - - for(i=0; inr > 0) - addtype(e->c1, e->q0-q.p, e->b, e->nb, e->nr); - else{ - m = e->q0; - while(m < e->q1){ - n = sprint(buf, "#%d", m); - fswrite(afd, buf, n); - n = fsread(dfd, buf, sizeof buf); - nr = nrunes(buf, n); - while(m+nr > e->q1){ - do; while(n>0 && (buf[--n]&0xC0)==0x80); - --nr; - } - if(n == 0) - break; - addtype(e->c1, m-q.p, buf, n, nr); - m += nr; - } - } - sendtype(fd0); -} - -void -sende(Event *e, int fd0, Fid *cfd, Fid *afd, Fid *dfd, int donl) -{ - int l, m, n, nr, lastc, end; - char abuf[16], buf[128]; - - end = q.p+ntyper; - l = sprint(abuf, "#%d", end); - fswrite(afd, abuf, l); - if(e->nr > 0){ - fswrite(dfd, e->b, e->nb); - addtype(e->c1, ntyper, e->b, e->nb, e->nr); - lastc = e->r[e->nr-1]; - }else{ - m = e->q0; - lastc = 0; - while(m < e->q1){ - n = sprint(buf, "#%d", m); - fswrite(afd, buf, n); - n = fsread(dfd, buf, sizeof buf); - nr = nrunes(buf, n); - while(m+nr > e->q1){ - do; while(n>0 && (buf[--n]&0xC0)==0x80); - --nr; - } - if(n == 0) - break; - l = sprint(abuf, "#%d", end); - fswrite(afd, abuf, l); - fswrite(dfd, buf, n); - addtype(e->c1, ntyper, buf, n, nr); - lastc = buf[n-1]; - m += nr; - end += nr; - } - } - if(donl && lastc!='\n'){ - fswrite(dfd, "\n", 1); - addtype(e->c1, ntyper, "\n", 1, 1); - } - fswrite(cfd, "dot=addr", 8); - sendtype(fd0); -} diff --git a/src/cmd/yacc.c b/src/cmd/yacc.c index 0ff114bd..6614414d 100644 --- a/src/cmd/yacc.c +++ b/src/cmd/yacc.c @@ -399,7 +399,7 @@ others(void) { int c, i, j; - finput = Bopen(parser, OREAD); + finput = Bopen(unsharp(parser), OREAD); if(finput == 0) error("cannot open parser %s: %r", parser); warray("yyr1", levprd, nprod); diff --git a/src/lib9/_p9translate.c b/src/lib9/_p9translate.c index 4eb6eac9..84cd65ca 100644 --- a/src/lib9/_p9translate.c +++ b/src/lib9/_p9translate.c @@ -14,7 +14,7 @@ static struct { }; char* -_p9translate(char *old) +plan9translate(char *old) { char *new; int i, olen, nlen, len; @@ -36,7 +36,7 @@ _p9translate(char *old) len = strlen(old)+nlen-olen; new = malloc(len+1); if(new == nil) - return nil; + return ""; strcpy(new, replace[i].new); strcpy(new+nlen, old+olen); assert(strlen(new) == len); diff --git a/src/lib9/access.c b/src/lib9/access.c deleted file mode 100644 index 20b00c32..00000000 --- a/src/lib9/access.c +++ /dev/null @@ -1,19 +0,0 @@ -#include -#define NOPLAN9DEFINES -#include - -char *_p9translate(char*); - -int -p9access(char *xname, int what) -{ - int ret; - char *name; - - if((name = _p9translate(xname)) == nil) - return -1; - ret = access(name, what); - if(name != xname) - free(name); - return ret; -} diff --git a/src/lib9/announce.c b/src/lib9/announce.c index 9f07bd22..8fdf1d40 100644 --- a/src/lib9/announce.c +++ b/src/lib9/announce.c @@ -40,7 +40,8 @@ p9announce(char *addr, char *dir) char *net; u32int host; int port, s; - int n, sn; + int n; + socklen_t sn; struct sockaddr_in sa; struct sockaddr_un sun; @@ -72,7 +73,7 @@ p9announce(char *addr, char *dir) if((s = socket(AF_INET, proto, 0)) < 0) return -1; sn = sizeof n; - if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (char*)&n, &sn) >= 0 + if(port && getsockopt(s, SOL_SOCKET, SO_TYPE, (void*)&n, &sn) >= 0 && n == SOCK_STREAM){ n = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&n, sizeof n); diff --git a/src/lib9/create.c b/src/lib9/create.c index bdad5f6a..97f6e7e2 100644 --- a/src/lib9/create.c +++ b/src/lib9/create.c @@ -3,16 +3,10 @@ #include #include -extern char *_p9translate(char*); - int -p9create(char *xpath, int mode, ulong perm) +p9create(char *path, int mode, ulong perm) { int fd, cexec, umode, rclose; - char *path; - - if((path = _p9translate(xpath)) == nil) - return -1; cexec = mode&OCEXEC; rclose = mode&ORCLOSE; @@ -48,7 +42,5 @@ out: if(rclose) remove(path); } - if(path != xpath) - free(path); return fd; } diff --git a/src/lib9/ctime.c b/src/lib9/ctime.c index e9d971bf..0782d099 100644 --- a/src/lib9/ctime.c +++ b/src/lib9/ctime.c @@ -15,6 +15,7 @@ ct_numb(char *cp, int n) char* asctime(Tm *t) { + int i; char *ncp; static char cbuf[30]; @@ -32,6 +33,12 @@ asctime(Tm *t) ct_numb(cbuf+14, t->min+100); ct_numb(cbuf+17, t->sec+100); ncp = t->zone; + for(i=0; i<3; i++) + if(ncp[i] == 0) + break; + for(; i<3; i++) + ncp[i] = '?'; + ncp = t->zone; cbuf[20] = *ncp++; cbuf[21] = *ncp++; cbuf[22] = *ncp; diff --git a/src/lib9/date.c b/src/lib9/date.c index 8ece0c68..8f852de2 100644 --- a/src/lib9/date.c +++ b/src/lib9/date.c @@ -1,6 +1,5 @@ -#include /* setenv etc. */ - #include +#include /* setenv etc. */ #define NOPLAN9DEFINES #include #include @@ -25,6 +24,8 @@ static Tm bigtm; static void tm2Tm(struct tm *tm, Tm *bigtm) { + char *s; + memset(bigtm, 0, sizeof *bigtm); bigtm->sec = tm->tm_sec; bigtm->min = tm->tm_min; @@ -39,6 +40,13 @@ tm2Tm(struct tm *tm, Tm *bigtm) #ifdef _HAVETZOFF bigtm->tzoff = tm->tm_gmtoff; #endif + if(bigtm->zone[0] == 0){ + s = getenv("TIMEZONE"); + if(s){ + strecpy(bigtm->zone, bigtm->zone+4, tm->tm_zone); + free(s); + } + } } static void diff --git a/src/lib9/dirread.c b/src/lib9/dirread.c index aef0102f..0a72d62e 100644 --- a/src/lib9/dirread.c +++ b/src/lib9/dirread.c @@ -18,7 +18,7 @@ mygetdents(int fd, struct dirent *buf, int n) nn = getdirentries(fd, (void*)buf, n, &off); return nn; } -#elif defined(__APPLE__) || defined(__FreeBSD__) +#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) static int mygetdents(int fd, struct dirent *buf, int n) { @@ -171,7 +171,7 @@ dirreadall(int fd, Dir **d) ts += n; } if(ts >= 0) - ts = dirpackage(fd, buf, ts, d); + ts = dirpackage(fd, (char*)buf, ts, d); free(buf); if(ts == 0 && n < 0) return -1; diff --git a/src/lib9/errstr.c b/src/lib9/errstr.c index 0c6ab315..578f4895 100644 --- a/src/lib9/errstr.c +++ b/src/lib9/errstr.c @@ -5,9 +5,10 @@ * okay. */ +#include #include #include -#include +#include enum { diff --git a/src/lib9/ffork-OpenBSD.c b/src/lib9/ffork-OpenBSD.c new file mode 100644 index 00000000..5e677f72 --- /dev/null +++ b/src/lib9/ffork-OpenBSD.c @@ -0,0 +1 @@ +#include "ffork-pthread.c" diff --git a/src/lib9/getuser.c b/src/lib9/getuser.c index b53a3892..09c07041 100644 --- a/src/lib9/getuser.c +++ b/src/lib9/getuser.c @@ -1,6 +1,5 @@ -#include - #include +#include #include char* diff --git a/src/lib9/lock.c b/src/lib9/lock.c index 5d6f2f3e..e97b967f 100644 --- a/src/lib9/lock.c +++ b/src/lib9/lock.c @@ -1,6 +1,7 @@ +#include #include #include -#include +#include int _ntas; static int diff --git a/src/lib9/mallocz.c b/src/lib9/mallocz.c index c6313008..a3e91510 100644 --- a/src/lib9/mallocz.c +++ b/src/lib9/mallocz.c @@ -1,6 +1,7 @@ +#include #include #include -#include +#include void* mallocz(unsigned long n, int clr) diff --git a/src/lib9/mkfile b/src/lib9/mkfile index d388d224..4dda2e19 100644 --- a/src/lib9/mkfile +++ b/src/lib9/mkfile @@ -69,8 +69,6 @@ LIB9OFILES=\ _p9dialparse.$O\ _p9dir.$O\ _p9proc.$O\ - _p9translate.$O\ - access.$O\ announce.$O\ argv0.$O\ atexit.$O\ @@ -100,6 +98,7 @@ LIB9OFILES=\ exec.$O\ fcallfmt.$O\ ffork-$SYSNAME.$O\ + get9root.$O\ getcallerpc-$OBJTYPE.$O\ getenv.$O\ getfields.$O\ @@ -142,6 +141,7 @@ LIB9OFILES=\ u16.$O\ u32.$O\ u64.$O\ + unsharp.$O\ wait.$O\ waitpid.$O\ diff --git a/src/lib9/notify.c b/src/lib9/notify.c index 2e589de7..4d2a79ef 100644 --- a/src/lib9/notify.c +++ b/src/lib9/notify.c @@ -1,6 +1,5 @@ -#include - #include +#include #define NOPLAN9DEFINES #include #include "9proc.h" diff --git a/src/lib9/open.c b/src/lib9/open.c index bb597e8f..0356a7da 100644 --- a/src/lib9/open.c +++ b/src/lib9/open.c @@ -2,12 +2,9 @@ #define NOPLAN9DEFINES #include -extern char* _p9translate(char*); - int -p9open(char *xname, int mode) +p9open(char *name, int mode) { - char *name; int cexec, rclose; int fd, umode; @@ -23,8 +20,6 @@ p9open(char *xname, int mode) werrstr("mode not supported"); return -1; } - if((name = _p9translate(xname)) == nil) - return -1; fd = open(name, umode); if(fd >= 0){ if(cexec) @@ -32,7 +27,5 @@ p9open(char *xname, int mode) if(rclose) remove(name); } - if(name != xname) - free(name); return fd; } diff --git a/src/lib9/rendez-Linux.c b/src/lib9/rendez-Linux.c index 05c52ae7..673818e0 100644 --- a/src/lib9/rendez-Linux.c +++ b/src/lib9/rendez-Linux.c @@ -1 +1,3 @@ +/* Could use futex(2) here instead of signals? */ + #include "rendez-signal.c" diff --git a/src/lib9/rendez-OpenBSD.c b/src/lib9/rendez-OpenBSD.c new file mode 100644 index 00000000..05c52ae7 --- /dev/null +++ b/src/lib9/rendez-OpenBSD.c @@ -0,0 +1 @@ +#include "rendez-signal.c" diff --git a/src/lib9/rendez-pthread.c b/src/lib9/rendez-pthread.c index b4b95f21..fe930cef 100644 --- a/src/lib9/rendez-pthread.c +++ b/src/lib9/rendez-pthread.c @@ -32,9 +32,10 @@ * shared memory and mutexes. */ +#include #include #include -#include +#include enum { diff --git a/src/lib9/time.c b/src/lib9/time.c index 169a82f5..36706367 100644 --- a/src/lib9/time.c +++ b/src/lib9/time.c @@ -1,7 +1,7 @@ +#include #include +#include #include - -#include #define NOPLAN9DEFINES #include diff --git a/src/libdraw/openfont.c b/src/libdraw/openfont.c index a359327b..05370eac 100644 --- a/src/libdraw/openfont.c +++ b/src/libdraw/openfont.c @@ -16,10 +16,12 @@ openfont(Display *d, char *name) if(fd < 0 && strncmp(name, "/lib/font/bit/", 14) == 0){ nambuf = smprint("#9/font/%s", name+14); + if(nambuf == nil) + return 0; + nambuf = unsharp(nambuf); if(nambuf == nil) return 0; if((fd = open(nambuf, OREAD)) < 0){ -fprint(2, "failed at %s\n", nambuf); free(nambuf); return 0; } diff --git a/src/libdraw/x11-init.c b/src/libdraw/x11-init.c index 1283f430..c959eee4 100644 --- a/src/libdraw/x11-init.c +++ b/src/libdraw/x11-init.c @@ -185,26 +185,22 @@ xattach(char *label) /* * Figure out underlying screen format. */ - _x.depth = DefaultDepth(_x.display, xrootid); if(XMatchVisualInfo(_x.display, xrootid, 16, TrueColor, &xvi) || XMatchVisualInfo(_x.display, xrootid, 16, DirectColor, &xvi)){ _x.vis = xvi.visual; _x.depth = 16; - _x.usetable = 1; } else if(XMatchVisualInfo(_x.display, xrootid, 15, TrueColor, &xvi) || XMatchVisualInfo(_x.display, xrootid, 15, DirectColor, &xvi)){ _x.vis = xvi.visual; _x.depth = 15; - _x.usetable = 1; } else if(XMatchVisualInfo(_x.display, xrootid, 24, TrueColor, &xvi) || XMatchVisualInfo(_x.display, xrootid, 24, DirectColor, &xvi)){ _x.vis = xvi.visual; _x.depth = 24; - _x.usetable = 1; } else if(XMatchVisualInfo(_x.display, xrootid, 8, PseudoColor, &xvi) @@ -218,6 +214,7 @@ xattach(char *label) _x.depth = 8; } else{ + _x.depth = DefaultDepth(_x.display, xrootid); if(_x.depth != 8){ werrstr("can't understand depth %d screen", _x.depth); goto err0; @@ -225,6 +222,9 @@ xattach(char *label) _x.vis = DefaultVisual(_x.display, xrootid); } + if(DefaultDepth(_x.display, xrootid) == _x.depth) + _x.usetable = 1; + /* * _x.depth is only the number of significant pixel bits, * not the total number of pixel bits. We need to walk the @@ -298,7 +298,7 @@ xattach(char *label) Dx(r), /* width */ Dy(r), /* height */ 0, /* border width */ - DefaultDepthOfScreen(xscreen), /* depth */ + _x.depth, /* depth */ InputOutput, /* class */ _x.vis, /* visual */ /* valuemask */ @@ -562,6 +562,18 @@ setupcmap(XWindow w) return 0; if(_x.depth >= 24) { + /* + * This is needed for SunOS. Ask Axel Belinfante. + */ + if(_x.usetable == 0){ + _x.cmap = XCreateColormap(_x.display, w, _x.vis, AllocAll); + XStoreColors(_x.display, _x.cmap, _x.map, 256); + for(i = 0; i < 256; i++){ + _x.tox11[i] = i; + _x.toplan9[i] = i; + } + } + /* * The pixel value returned from XGetPixel needs to * be converted to RGB so we can call rgb2cmap() @@ -573,7 +585,6 @@ setupcmap(XWindow w) * some displays say MSB even though they run on LSB. * Besides, this is more anal. */ - c = _x.map[19]; /* known to have different R, G, B values */ if(!XAllocColor(_x.display, _x.cmap, &c)){ werrstr("XAllocColor: %r"); diff --git a/src/libdraw/x11-itrans.c b/src/libdraw/x11-itrans.c index 8e72b011..509b55cf 100644 --- a/src/libdraw/x11-itrans.c +++ b/src/libdraw/x11-itrans.c @@ -11,6 +11,9 @@ #include #include "x11-memdraw.h" +#undef time + + static int __xtoplan9kbd(XEvent *e) { diff --git a/src/libplumb/mesg.c b/src/libplumb/mesg.c index c4094fa4..4b278695 100755 --- a/src/libplumb/mesg.c +++ b/src/libplumb/mesg.c @@ -68,7 +68,6 @@ plumbsendtofid(Fid *fid, Plumbmsg *m) if(buf == nil) return -1; n = fswrite(fid, buf, n); -fprint(2, "fswrite %d\n", n); free(buf); return n; } diff --git a/src/libthread/asm-OpenBSD-386.s b/src/libthread/asm-OpenBSD-386.s new file mode 100644 index 00000000..35e2ab6f --- /dev/null +++ b/src/libthread/asm-OpenBSD-386.s @@ -0,0 +1,49 @@ +.globl _setlabel +.type _setlabel,@function + +_setlabel: + movl 4(%esp), %eax + movl 0(%esp), %edx + movl %edx, 0(%eax) + movl %ebx, 4(%eax) + movl %esp, 8(%eax) + movl %ebp, 12(%eax) + movl %esi, 16(%eax) + movl %edi, 20(%eax) + xorl %eax, %eax + ret + +.globl _gotolabel +.type _gotolabel,@function + +_gotolabel: + movl 4(%esp), %edx + movl 0(%edx), %ecx + movl 4(%edx), %ebx + movl 8(%edx), %esp + movl 12(%edx), %ebp + movl 16(%edx), %esi + movl 20(%edx), %edi + xorl %eax, %eax + incl %eax + movl %ecx, 0(%esp) + ret + + +# .globl _xinc +# _xinc: +# movl 4(%esp), %eax +# lock incl 0(%eax) +# ret +# +# .globl _xdec +# _xdec: +# movl 4(%esp), %eax +# lock decl 0(%eax) +# jz iszero +# movl $1, %eax +# ret +# iszero: +# movl $0, %eax +# ret +# diff --git a/src/libthread/exec-unix.c b/src/libthread/exec-unix.c index bfffa14d..eb31e99e 100644 --- a/src/libthread/exec-unix.c +++ b/src/libthread/exec-unix.c @@ -3,8 +3,8 @@ #include "threadimpl.h" static void efork(int[3], int[2], char*, char**); -void -threadexec(Channel *pidc, int fd[3], char *prog, char *args[]) +static void +_threadexec(Channel *pidc, int fd[3], char *prog, char *args[], int freeargs) { int pfd[2]; int n, pid; @@ -40,6 +40,8 @@ threadexec(Channel *pidc, int fd[3], char *prog, char *args[]) efork(fd, pfd, prog, args); _exit(0); default: + if(freeargs) + free(args); break; } @@ -68,10 +70,43 @@ Bad: sendul(pidc, ~0); } +void +threadexec(Channel *pidc, int fd[3], char *prog, char *args[]) +{ + _threadexec(pidc, fd, prog, args, 0); +} + +/* + * The &f+1 trick doesn't work on SunOS, so we might + * as well bite the bullet and do this correctly. + */ void threadexecl(Channel *pidc, int fd[3], char *f, ...) { - threadexec(pidc, fd, f, &f+1); + char **args, *s; + int n; + va_list arg; + + va_start(arg, f); + for(n=0; va_arg(arg, char*) != 0; n++) + ; + n++; + va_end(arg); + + args = malloc(n*sizeof(args[0])); + if(args == nil){ + if(pidc) + sendul(pidc, ~0); + return; + } + + va_start(arg, f); + for(n=0; (s=va_arg(arg, char*)) != 0; n++) + args[n] = s; + args[n] = 0; + va_end(arg); + + _threadexec(pidc, fd, f, args, 1); } static void diff --git a/src/libthread/label.h b/src/libthread/label.h index 874fb070..5161e373 100644 --- a/src/libthread/label.h +++ b/src/libthread/label.h @@ -7,7 +7,7 @@ typedef struct Label Label; #define LABELDPC 0 -#if defined (__i386__) && (defined(__FreeBSD__) || defined(__linux__)) +#if defined (__i386__) && (defined(__FreeBSD__) || defined(__linux__) || defined(__OpenBSD__)) struct Label { ulong pc; diff --git a/src/mkfile b/src/mkfile index 45683608..a81246cd 100644 --- a/src/mkfile +++ b/src/mkfile @@ -1,6 +1,6 @@