diff options
Diffstat (limited to 'os/port/devtk.c')
| -rw-r--r-- | os/port/devtk.c | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/os/port/devtk.c b/os/port/devtk.c new file mode 100644 index 00000000..61afd667 --- /dev/null +++ b/os/port/devtk.c @@ -0,0 +1,180 @@ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/error.h" + +#include <interp.h> + +#include "draw.h" + +enum{ + Qdir, + Qtkevents +}; + +static +Dirtab tkdirtab[]={ + {".", {Qdir,0,QTDIR}, 0, 0500}, + {"tkevents", {Qtkevents, 0}, 0, 0600}, +}; + +static struct { + QLock l; + Queue* eq; + Ref inuse; +} tkevents; + +static void +tkwiretapper(void *top, char *cmd, char *result, void *image, Rectangle *rp) +{ + Block *b; + int n; + char *s, *e; + + n = 12; + if(cmd != nil) + n += strlen(cmd)+2+1; + if(result != nil) + n += strlen(result)+2+1; + if(image != nil) + n += 12; + if(rp != nil) + n += 4*20; + n++; + b = allocb(n); + if(b != nil){ + s = (char*)b->wp; + e = s+n; + s += snprint(s, e-s, "%p", top); + if(cmd != nil){ + *s++ = ' '; + *s++ = '['; + n = strlen(cmd); + memmove(s, cmd, n); + s += n; + *s++ = ']'; + } + /* ignore result for now */ + if(image != nil) + s += snprint(s, e-s, " %p", image); + if(rp != nil) + s += snprint(s, e-s, " %d %d %d %d", rp->min.x, rp->min.y, rp->max.x, rp->max.y); + *s++ = '\n'; + b->wp = (uchar*)s; + release(); + qlock(&tkevents.l); + if(waserror()){ + qunlock(&tkevents.l); + acquire(); + return; + } + if(tkevents.eq != nil) + qbwrite(tkevents.eq, b); + poperror(); + qunlock(&tkevents.l); + acquire(); + } +} + +void (*tkwiretap)(void*, char*, char*, void*, Rectangle*); + +static Chan* +tkattach(char* spec) +{ + return devattach(L'τ', spec); +} + +static Walkqid* +tkwalk(Chan *c, Chan *nc, char **name, int nname) +{ + return devwalk(c, nc, name, nname, tkdirtab, nelem(tkdirtab), devgen); +} + +static int +tkstat(Chan *c, uchar *db, int n) +{ + return devstat(c, db, n, tkdirtab, nelem(tkdirtab), devgen); +} + +static Chan* +tkopen(Chan* c, int omode) +{ + if(c->qid.type & QTDIR) + return devopen(c, omode, tkdirtab, nelem(tkdirtab), devgen); + switch((ulong)c->qid.path){ + case Qtkevents: + c = devopen(c, omode, tkdirtab, nelem(tkdirtab), devgen); + qlock(&tkevents.l); + if(incref(&tkevents.inuse) != 1){ + qunlock(&tkevents.l); + error(Einuse); + } + if(tkevents.eq == nil) + tkevents.eq = qopen(256*1024, 0, nil, nil); + else + qreopen(tkevents.eq); + tkwiretap = tkwiretapper; + qunlock(&tkevents.l); + break; + } + return c; +} + +static void +tkclose(Chan* c) +{ + if(c->qid.type & QTDIR || (c->flag & COPEN) == 0) + return; + qlock(&tkevents.l); + if(decref(&tkevents.inuse) == 0){ + tkwiretap = nil; + qclose(tkevents.eq); + } + qunlock(&tkevents.l); +} + +static long +tkread(Chan* c, void* a, long n, vlong offset) +{ + USED(offset); + switch((ulong)c->qid.path){ + case Qdir: + return devdirread(c, a, n, tkdirtab, nelem(tkdirtab), devgen); + case Qtkevents: + return qread(tkevents.eq, a, n); + default: + n=0; + break; + } + return n; +} + +static long +tkwrite(Chan*, void*, long, vlong) +{ + error(Ebadusefd); + return 0; +} + +Dev tkdevtab = { + L'τ', + "tk", + + devreset, + devinit, + devshutdown, + tkattach, + tkwalk, + tkstat, + tkopen, + devcreate, + tkclose, + tkread, + devbread, + tkwrite, + devbwrite, + devremove, + devwstat, +}; |
