Today's changes.
More changes.
This commit is contained in:
parent
cb27443abf
commit
8ad517944e
73 changed files with 2865 additions and 1293 deletions
|
|
@ -1150,7 +1150,7 @@ rewritehdr(Fcall *f, uchar *pkt)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef _LIB9_H_
|
||||
#ifdef _LIBC_H_
|
||||
/* unix select-based polling */
|
||||
struct Ioproc
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,15 +1,24 @@
|
|||
#include "9term.h"
|
||||
|
||||
#define fatal sysfatal
|
||||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <ctype.h>
|
||||
#include <draw.h>
|
||||
#include <thread.h>
|
||||
#include <mouse.h>
|
||||
#include <cursor.h>
|
||||
#include <keyboard.h>
|
||||
#include <frame.h>
|
||||
#include <plumb.h>
|
||||
#include <complete.h>
|
||||
#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; i<c->nfile; 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<t.nr && t.r[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;
|
||||
}else if(r == CUT){
|
||||
case Kdown:
|
||||
setorigin(line2q(t.f->maxlines/3), 1);
|
||||
if(t.qh<=t.org+t.f->nchars)
|
||||
consread();
|
||||
return;
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -1,19 +1,4 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <ctype.h>
|
||||
#include <draw.h>
|
||||
#include <thread.h>
|
||||
#include <mouse.h>
|
||||
#include <cursor.h>
|
||||
#include <keyboard.h>
|
||||
#include <frame.h>
|
||||
#include <plumb.h>
|
||||
#include <termios.h>
|
||||
#include <sys/termios.h>
|
||||
#ifdef __linux__
|
||||
#include <pty.h>
|
||||
#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[];
|
||||
|
|
|
|||
|
|
@ -1,17 +1,43 @@
|
|||
#include "9term.h"
|
||||
#include <termios.h>
|
||||
#include <sys/termios.h>
|
||||
#include <libutil.h>
|
||||
|
||||
int
|
||||
getchildwd(int pid, char *wdir, int bufn)
|
||||
{
|
||||
USED(pid);
|
||||
USED(wdir);
|
||||
USED(bufn);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
getpts(int fd[], char *slave)
|
||||
{
|
||||
return openpty(&fd[1], &fd[0], slave, 0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
childpty(int fd[], char *slave)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,46 @@
|
|||
#include <u.h>
|
||||
#include <termios.h>
|
||||
#include <sys/termios.h>
|
||||
#include <pty.h>
|
||||
#include <libc.h>
|
||||
#include "9term.h"
|
||||
|
||||
int
|
||||
getchildwd(int pid, char *wdir, int bufn)
|
||||
{
|
||||
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';
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
getpts(int fd[], char *slave)
|
||||
{
|
||||
openpty(&fd[1], &fd[0], slave, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
childpty(int fd[], char *slave)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <termios.h>
|
||||
#include <sys/termios.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
51
src/cmd/9term/rcstart.c
Normal file
51
src/cmd/9term/rcstart.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
5
src/cmd/9term/term.h
Normal file
5
src/cmd/9term/term.h
Normal file
|
|
@ -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*);
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
#include <thread.h>
|
||||
#include <fcall.h>
|
||||
#include <fs.h>
|
||||
#include "term.h"
|
||||
|
||||
#define EVENTSIZE 256
|
||||
#define STACK 32768
|
||||
|
|
@ -51,11 +52,11 @@ int ntypeb;
|
|||
int ntyper;
|
||||
int ntypebreak;
|
||||
int debug;
|
||||
int rcfd;
|
||||
|
||||
char *name;
|
||||
|
||||
char **prog;
|
||||
int p[2];
|
||||
Channel *cpid;
|
||||
Channel *cwait;
|
||||
int pid = -1;
|
||||
|
||||
|
|
@ -124,9 +125,11 @@ threadmain(int argc, char **argv)
|
|||
|
||||
prog = argv;
|
||||
|
||||
if(argc > 0)
|
||||
if(argc > 0){
|
||||
name = argv[0];
|
||||
else
|
||||
argc--;
|
||||
argv++;
|
||||
}else
|
||||
name = "gnot";
|
||||
|
||||
threadnotify(nopipes, 1);
|
||||
|
|
@ -156,14 +159,9 @@ threadmain(int argc, char **argv)
|
|||
*/
|
||||
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);
|
||||
pid = rcstart(argc, argv, &rcfd);
|
||||
if(pid == -1)
|
||||
sysfatal("exec failed");
|
||||
|
||||
|
|
@ -179,30 +177,6 @@ threadmain(int argc, char **argv)
|
|||
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)
|
||||
{
|
||||
|
|
@ -329,7 +303,7 @@ stdinproc(void *v)
|
|||
Fid *efd = eventfd;
|
||||
Fid *dfd = datafd;
|
||||
Fid *afd = addrfd;
|
||||
int fd0 = p[0];
|
||||
int fd0 = rcfd;
|
||||
Event e, e2, e3, e4;
|
||||
|
||||
USED(v);
|
||||
|
|
@ -426,7 +400,7 @@ stdinproc(void *v)
|
|||
void
|
||||
stdoutproc(void *v)
|
||||
{
|
||||
int fd1 = p[0];
|
||||
int fd1 = rcfd;
|
||||
Fid *afd = addrfd;
|
||||
Fid *dfd = datafd;
|
||||
int n, m, w, npart;
|
||||
|
|
@ -439,6 +413,8 @@ stdoutproc(void *v)
|
|||
buf = malloc(8192+UTFmax+1);
|
||||
npart = 0;
|
||||
for(;;){
|
||||
/* Let typing have a go -- maybe there's a rubout waiting. */
|
||||
yield();
|
||||
n = threadread(fd1, buf+npart, 8192);
|
||||
if(n < 0)
|
||||
error(nil);
|
||||
|
|
@ -556,7 +532,7 @@ addtype(int c, uint p0, char *b, int nb, int nr)
|
|||
for(i=0; i<nb; i+=w){
|
||||
w = chartorune(&r, b+i);
|
||||
if((r==0x7F||r==3) && c=='K'){
|
||||
postnote(PNGROUP, pid, "interrupt");
|
||||
write(rcfd, "\x7F", 1);
|
||||
/* toss all typing */
|
||||
q.p += ntyper+nr;
|
||||
ntypebreak = 0;
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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){
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)){
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ void
|
|||
done(int status)
|
||||
{
|
||||
rmtmpfiles();
|
||||
Bflush(&stdout);
|
||||
Bterm(&stdout);
|
||||
switch(status)
|
||||
{
|
||||
case 0:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
277
src/cmd/grep/comp.c
Normal file
277
src/cmd/grep/comp.c
Normal file
|
|
@ -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; i<s->count; 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; i<nfollow; i++) {
|
||||
re1 = t->re[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; i<nfollow; i++) {
|
||||
re1 = follow[i];
|
||||
t->re[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<nelem(tab1); i++) {
|
||||
m = tab1[i];
|
||||
if(p0 <= m && p1 > 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<nelem(tab2); i++) {
|
||||
m = tab2[i];
|
||||
if((p0 & ~m) != (p1 & ~m)) {
|
||||
if((p0 & m) != 0)
|
||||
return re2or(rclass(p0, p0|m), rclass((p0|m)+1, p1));
|
||||
if((p1 & m) != m)
|
||||
return re2or(rclass(p0, (p1&~m)-1), rclass(p1&~m, p1));
|
||||
}
|
||||
}
|
||||
|
||||
n = runetochar(xc0, &p0);
|
||||
i = runetochar(xc1, &p1);
|
||||
if(i != n)
|
||||
error("length");
|
||||
|
||||
x = re2char(xc0[0], xc1[0]);
|
||||
for(i=1; i<n; i++)
|
||||
x = re2cat(x, re2char(xc0[i], xc1[i]));
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
pcmp(const void *va, const void *vb)
|
||||
{
|
||||
int n;
|
||||
Rune *a, *b;
|
||||
|
||||
a = (Rune*)va;
|
||||
b = (Rune*)vb;
|
||||
|
||||
n = a[0] - b[0];
|
||||
if(n)
|
||||
return n;
|
||||
return a[1] - b[1];
|
||||
}
|
||||
|
||||
/*
|
||||
* convert character chass into
|
||||
* run-pair ranges of matches.
|
||||
* this is 10646/utf specific and
|
||||
* needs to be changed for some
|
||||
* other input character set.
|
||||
* this is the key to a fast
|
||||
* regular search of characters
|
||||
* by looking at sequential bytes.
|
||||
*/
|
||||
Re2
|
||||
re2class(char *s)
|
||||
{
|
||||
Rune pairs[200], *p, *q, ov;
|
||||
int nc;
|
||||
Re2 x;
|
||||
|
||||
nc = 0;
|
||||
if(*s == '^') {
|
||||
nc = 1;
|
||||
s++;
|
||||
}
|
||||
|
||||
p = pairs;
|
||||
s += chartorune(p, s);
|
||||
for(;;) {
|
||||
if(*p == '\\')
|
||||
s += chartorune(p, s);
|
||||
if(*p == 0)
|
||||
break;
|
||||
p[1] = *p;
|
||||
p += 2;
|
||||
s += chartorune(p, s);
|
||||
if(*p != '-')
|
||||
continue;
|
||||
s += chartorune(p, s);
|
||||
if(*p == '\\')
|
||||
s += chartorune(p, s);
|
||||
if(*p == 0)
|
||||
break;
|
||||
p[-1] = *p;
|
||||
s += chartorune(p, s);
|
||||
}
|
||||
*p = 0;
|
||||
qsort(pairs, (p-pairs)/2, 2*sizeof(*pairs), pcmp);
|
||||
|
||||
q = pairs;
|
||||
for(p=pairs+2; *p; p+=2) {
|
||||
if(p[0] > 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;
|
||||
}
|
||||
125
src/cmd/grep/grep.h
Normal file
125
src/cmd/grep/grep.h
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
|
||||
#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*, ...);
|
||||
226
src/cmd/grep/grep.y
Normal file
226
src/cmd/grep/grep.y
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
%{
|
||||
#include "grep.h"
|
||||
%}
|
||||
|
||||
%union
|
||||
{
|
||||
int val;
|
||||
char* str;
|
||||
Re2 re;
|
||||
}
|
||||
|
||||
%type <re> expr prog
|
||||
%type <re> expr0 expr1 expr2 expr3 expr4
|
||||
%token <str> LCLASS
|
||||
%token <val> 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;
|
||||
}
|
||||
260
src/cmd/grep/main.c
Normal file
260
src/cmd/grep/main.c
Normal file
|
|
@ -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<argc; i++)
|
||||
status |= search(argv[i], Hflag);
|
||||
break;
|
||||
}
|
||||
if(status)
|
||||
exits(0);
|
||||
exits("no matches");
|
||||
}
|
||||
|
||||
int
|
||||
search(char *file, int flag)
|
||||
{
|
||||
State *s, *ns;
|
||||
int c, fid, eof, nl, empty;
|
||||
long count, lineno, n;
|
||||
uchar *elp, *lp, *bol;
|
||||
|
||||
if(file == 0) {
|
||||
file = "stdin";
|
||||
fid = 0;
|
||||
flag |= Bflag;
|
||||
} else
|
||||
fid = open(file, OREAD);
|
||||
|
||||
if(fid < 0) {
|
||||
fprint(2, "grep: can't open %s: %r\n", file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(flags['b'])
|
||||
flag ^= Bflag; /* dont buffer output */
|
||||
if(flags['c'])
|
||||
flag |= Cflag; /* count */
|
||||
if(flags['h'])
|
||||
flag &= ~Hflag; /* do not print file name in output */
|
||||
if(flags['i'])
|
||||
flag |= Iflag; /* fold upper-lower */
|
||||
if(flags['l'])
|
||||
flag |= Llflag; /* print only name of file if any match */
|
||||
if(flags['L'])
|
||||
flag |= LLflag; /* print only name of file if any non match */
|
||||
if(flags['n'])
|
||||
flag |= Nflag; /* count only */
|
||||
if(flags['s'])
|
||||
flag |= Sflag; /* status only */
|
||||
if(flags['v'])
|
||||
flag |= Vflag; /* inverse match */
|
||||
|
||||
s = state0;
|
||||
lineno = 0;
|
||||
count = 0;
|
||||
eof = 0;
|
||||
empty = 1;
|
||||
nl = 0;
|
||||
lp = u.buf;
|
||||
bol = lp;
|
||||
|
||||
loop0:
|
||||
n = lp-bol;
|
||||
if(n > 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; i<nfollow; i++)
|
||||
s->re[i] = follow[i];
|
||||
return s;
|
||||
}
|
||||
20
src/cmd/grep/mkfile
Normal file
20
src/cmd/grep/mkfile
Normal file
|
|
@ -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
|
||||
317
src/cmd/grep/sub.c
Normal file
317
src/cmd/grep/sub.c
Normal file
|
|
@ -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");
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
27
src/cmd/rio/Imakefile
Normal file
27
src/cmd/rio/Imakefile
Normal file
|
|
@ -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
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#ifdef SHAPE
|
||||
#include <X11/extensions/shape.h>
|
||||
#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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue